Skip to content

Commit 88740b0

Browse files
authored
Merge pull request #31 from cloudstruct/feature/server-handshake
Basic server support
2 parents 2c422e8 + 7163ce0 commit 88740b0

File tree

13 files changed

+298
-107
lines changed

13 files changed

+298
-107
lines changed

cmd/go-ouroboros-network/chainsync.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func buildBlockFetchCallbackConfig() *blockfetch.BlockFetchCallbackConfig {
8181
}
8282
}
8383

84-
func testChainSync(o *ouroboros.Ouroboros, f *globalFlags) {
84+
func testChainSync(f *globalFlags) {
8585
chainSyncFlags := newChainSyncFlags()
8686
err := chainSyncFlags.flagset.Parse(f.flagset.Args()[1:])
8787
if err != nil {
@@ -93,6 +93,31 @@ func testChainSync(o *ouroboros.Ouroboros, f *globalFlags) {
9393
fmt.Printf("ERROR: unknown era '%s' specified as chain-sync start point\n", chainSyncFlags.startEra)
9494
os.Exit(1)
9595
}
96+
97+
conn := createClientConnection(f)
98+
errorChan := make(chan error)
99+
oOpts := &ouroboros.OuroborosOptions{
100+
Conn: conn,
101+
NetworkMagic: uint32(f.networkMagic),
102+
ErrorChan: errorChan,
103+
UseNodeToNodeProtocol: f.ntnProto,
104+
SendKeepAlives: true,
105+
ChainSyncCallbackConfig: buildChainSyncCallbackConfig(),
106+
BlockFetchCallbackConfig: buildBlockFetchCallbackConfig(),
107+
}
108+
go func() {
109+
for {
110+
err := <-errorChan
111+
fmt.Printf("ERROR: %s\n", err)
112+
os.Exit(1)
113+
}
114+
}()
115+
o, err := ouroboros.New(oOpts)
116+
if err != nil {
117+
fmt.Printf("ERROR: %s\n", err)
118+
os.Exit(1)
119+
}
120+
96121
syncState.oConn = o
97122
syncState.readyForNextBlockChan = make(chan bool)
98123
syncState.nodeToNode = f.ntnProto

cmd/go-ouroboros-network/localtxsubmission.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func buildLocalTxSubmissionCallbackConfig() *localtxsubmission.CallbackConfig {
3838
}
3939
}
4040

41-
func testLocalTxSubmission(o *ouroboros.Ouroboros, f *globalFlags) {
41+
func testLocalTxSubmission(f *globalFlags) {
4242
localTxSubmissionFlags := newLocalTxSubmissionFlags()
4343
err := localTxSubmissionFlags.flagset.Parse(f.flagset.Args()[1:])
4444
if err != nil {
@@ -48,6 +48,29 @@ func testLocalTxSubmission(o *ouroboros.Ouroboros, f *globalFlags) {
4848

4949
localTxSubmitState.submitResponse = make(chan bool)
5050

51+
conn := createClientConnection(f)
52+
errorChan := make(chan error)
53+
oOpts := &ouroboros.OuroborosOptions{
54+
Conn: conn,
55+
NetworkMagic: uint32(f.networkMagic),
56+
ErrorChan: errorChan,
57+
UseNodeToNodeProtocol: f.ntnProto,
58+
SendKeepAlives: true,
59+
LocalTxSubmissionCallbackConfig: buildLocalTxSubmissionCallbackConfig(),
60+
}
61+
go func() {
62+
for {
63+
err := <-errorChan
64+
fmt.Printf("ERROR: %s\n", err)
65+
os.Exit(1)
66+
}
67+
}()
68+
o, err := ouroboros.New(oOpts)
69+
if err != nil {
70+
fmt.Printf("ERROR: %s\n", err)
71+
os.Exit(1)
72+
}
73+
5174
txData, err := ioutil.ReadFile(localTxSubmissionFlags.txFile)
5275
if err != nil {
5376
fmt.Printf("Failed to load transaction file: %s\n", err)

cmd/go-ouroboros-network/main.go

Lines changed: 33 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import (
44
"crypto/tls"
55
"flag"
66
"fmt"
7-
ouroboros "github.com/cloudstruct/go-ouroboros-network"
8-
"io"
97
"net"
108
"os"
119
)
@@ -50,29 +48,6 @@ func main() {
5048
os.Exit(1)
5149
}
5250

53-
var conn io.ReadWriteCloser
54-
var dialProto string
55-
var dialAddress string
56-
if f.socket != "" {
57-
dialProto = "unix"
58-
dialAddress = f.socket
59-
} else if f.address != "" {
60-
dialProto = "tcp"
61-
dialAddress = f.address
62-
} else {
63-
fmt.Printf("You must specify one of -socket or -address\n\n")
64-
flag.PrintDefaults()
65-
os.Exit(1)
66-
}
67-
if f.useTls {
68-
conn, err = tls.Dial(dialProto, dialAddress, nil)
69-
} else {
70-
conn, err = net.Dial(dialProto, dialAddress)
71-
}
72-
if err != nil {
73-
fmt.Printf("Connection failed: %s\n", err)
74-
os.Exit(1)
75-
}
7651
if f.networkMagic == 0 {
7752
if f.testnet {
7853
f.networkMagic = TESTNET_MAGIC
@@ -84,35 +59,15 @@ func main() {
8459
os.Exit(1)
8560
}
8661
}
87-
errorChan := make(chan error, 10)
88-
oOpts := &ouroboros.OuroborosOptions{
89-
Conn: conn,
90-
NetworkMagic: uint32(f.networkMagic),
91-
ErrorChan: errorChan,
92-
UseNodeToNodeProtocol: f.ntnProto,
93-
SendKeepAlives: true,
94-
ChainSyncCallbackConfig: buildChainSyncCallbackConfig(),
95-
BlockFetchCallbackConfig: buildBlockFetchCallbackConfig(),
96-
LocalTxSubmissionCallbackConfig: buildLocalTxSubmissionCallbackConfig(),
97-
}
98-
go func() {
99-
for {
100-
err := <-errorChan
101-
fmt.Printf("ERROR: %s\n", err)
102-
os.Exit(1)
103-
}
104-
}()
105-
o, err := ouroboros.New(oOpts)
106-
if err != nil {
107-
fmt.Printf("ERROR: %s\n", err)
108-
os.Exit(1)
109-
}
62+
11063
if len(f.flagset.Args()) > 0 {
11164
switch f.flagset.Arg(0) {
11265
case "chain-sync":
113-
testChainSync(o, f)
66+
testChainSync(f)
11467
case "local-tx-submission":
115-
testLocalTxSubmission(o, f)
68+
testLocalTxSubmission(f)
69+
case "server":
70+
testServer(f)
11671
default:
11772
fmt.Printf("Unknown subcommand: %s\n", f.flagset.Arg(0))
11873
os.Exit(1)
@@ -122,3 +77,31 @@ func main() {
12277
os.Exit(1)
12378
}
12479
}
80+
81+
func createClientConnection(f *globalFlags) net.Conn {
82+
var err error
83+
var conn net.Conn
84+
var dialProto string
85+
var dialAddress string
86+
if f.socket != "" {
87+
dialProto = "unix"
88+
dialAddress = f.socket
89+
} else if f.address != "" {
90+
dialProto = "tcp"
91+
dialAddress = f.address
92+
} else {
93+
fmt.Printf("You must specify one of -socket or -address\n\n")
94+
flag.PrintDefaults()
95+
os.Exit(1)
96+
}
97+
if f.useTls {
98+
conn, err = tls.Dial(dialProto, dialAddress, nil)
99+
} else {
100+
conn, err = net.Dial(dialProto, dialAddress)
101+
}
102+
if err != nil {
103+
fmt.Printf("Connection failed: %s\n", err)
104+
os.Exit(1)
105+
}
106+
return conn
107+
}

cmd/go-ouroboros-network/server.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
ouroboros "github.com/cloudstruct/go-ouroboros-network"
7+
"net"
8+
"os"
9+
)
10+
11+
type serverFlags struct {
12+
flagset *flag.FlagSet
13+
//txFile string
14+
}
15+
16+
func newServerFlags() *serverFlags {
17+
f := &serverFlags{
18+
flagset: flag.NewFlagSet("server", flag.ExitOnError),
19+
}
20+
//f.flagset.StringVar(&f.txFile, "tx-file", "", "path to the transaction file to submit")
21+
return f
22+
}
23+
24+
func createListenerSocket(f *globalFlags) (net.Listener, error) {
25+
var err error
26+
var listen net.Listener
27+
if f.socket != "" {
28+
if err := os.RemoveAll(f.socket); err != nil {
29+
return nil, fmt.Errorf("failed to remove existing socket: %s", err)
30+
}
31+
listen, err = net.Listen("unix", f.socket)
32+
if err != nil {
33+
return nil, fmt.Errorf("failed to open listening socket: %s", err)
34+
}
35+
} else if f.address != "" {
36+
listen, err = net.Listen("tcp", f.address)
37+
if err != nil {
38+
return nil, fmt.Errorf("failed to open listening socket: %s", err)
39+
}
40+
}
41+
return listen, nil
42+
}
43+
44+
func testServer(f *globalFlags) {
45+
serverFlags := newServerFlags()
46+
err := serverFlags.flagset.Parse(f.flagset.Args()[1:])
47+
if err != nil {
48+
fmt.Printf("failed to parse subcommand args: %s\n", err)
49+
os.Exit(1)
50+
}
51+
52+
listen, err := createListenerSocket(f)
53+
if err != nil {
54+
fmt.Printf("ERROR: failed to create listener: %s\n", err)
55+
os.Exit(1)
56+
}
57+
58+
for {
59+
conn, err := listen.Accept()
60+
if err != nil {
61+
fmt.Printf("ERROR: failed to accept connection: %s\n", err)
62+
continue
63+
}
64+
errorChan := make(chan error)
65+
oOpts := &ouroboros.OuroborosOptions{
66+
Conn: conn,
67+
NetworkMagic: uint32(f.networkMagic),
68+
ErrorChan: errorChan,
69+
UseNodeToNodeProtocol: f.ntnProto,
70+
Server: true,
71+
}
72+
go func() {
73+
for {
74+
err := <-errorChan
75+
fmt.Printf("ERROR: %s\n", err)
76+
}
77+
}()
78+
_, err = ouroboros.New(oOpts)
79+
if err != nil {
80+
fmt.Printf("ERROR: %s\n", err)
81+
}
82+
}
83+
}

ouroboros.go

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ package ouroboros
22

33
import (
44
"github.com/cloudstruct/go-ouroboros-network/muxer"
5+
"github.com/cloudstruct/go-ouroboros-network/protocol"
56
"github.com/cloudstruct/go-ouroboros-network/protocol/blockfetch"
67
"github.com/cloudstruct/go-ouroboros-network/protocol/chainsync"
78
"github.com/cloudstruct/go-ouroboros-network/protocol/handshake"
89
"github.com/cloudstruct/go-ouroboros-network/protocol/keepalive"
910
"github.com/cloudstruct/go-ouroboros-network/protocol/localtxsubmission"
10-
"io"
1111
"net"
1212
)
1313

1414
type Ouroboros struct {
15-
conn io.ReadWriteCloser
15+
conn net.Conn
1616
networkMagic uint32
17-
waitForHandshake bool
17+
server bool
1818
useNodeToNodeProto bool
1919
handshakeComplete bool
2020
muxer *muxer.Muxer
@@ -33,12 +33,10 @@ type Ouroboros struct {
3333
}
3434

3535
type OuroborosOptions struct {
36-
Conn io.ReadWriteCloser
37-
NetworkMagic uint32
38-
ErrorChan chan error
39-
// Whether to wait for the other side to initiate the handshake. This is useful
40-
// for servers
41-
WaitForHandshake bool
36+
Conn net.Conn
37+
NetworkMagic uint32
38+
ErrorChan chan error
39+
Server bool
4240
UseNodeToNodeProtocol bool
4341
SendKeepAlives bool
4442
ChainSyncCallbackConfig *chainsync.ChainSyncCallbackConfig
@@ -51,7 +49,7 @@ func New(options *OuroborosOptions) (*Ouroboros, error) {
5149
o := &Ouroboros{
5250
conn: options.Conn,
5351
networkMagic: options.NetworkMagic,
54-
waitForHandshake: options.WaitForHandshake,
52+
server: options.Server,
5553
useNodeToNodeProto: options.UseNodeToNodeProtocol,
5654
chainSyncCallbackConfig: options.ChainSyncCallbackConfig,
5755
blockFetchCallbackConfig: options.BlockFetchCallbackConfig,
@@ -92,37 +90,49 @@ func (o *Ouroboros) setupConnection() error {
9290
err := <-o.muxer.ErrorChan
9391
o.ErrorChan <- err
9492
}()
95-
// Perform handshake
96-
o.Handshake = handshake.New(o.muxer, o.ErrorChan, o.useNodeToNodeProto)
93+
protoOptions := protocol.ProtocolOptions{
94+
Muxer: o.muxer,
95+
ErrorChan: o.ErrorChan,
96+
}
9797
var protoVersions []uint16
9898
if o.useNodeToNodeProto {
9999
protoVersions = GetProtocolVersionsNtN()
100+
protoOptions.Mode = protocol.ProtocolModeNodeToNode
100101
} else {
101102
protoVersions = GetProtocolVersionsNtC()
103+
protoOptions.Mode = protocol.ProtocolModeNodeToClient
102104
}
105+
if o.server {
106+
protoOptions.Role = protocol.ProtocolRoleServer
107+
} else {
108+
protoOptions.Role = protocol.ProtocolRoleClient
109+
}
110+
// Perform handshake
111+
o.Handshake = handshake.New(protoOptions, protoVersions)
103112
// TODO: figure out better way to signify automatic handshaking and returning the chosen version
104-
if !o.waitForHandshake {
113+
if !o.server {
105114
err := o.Handshake.ProposeVersions(protoVersions, o.networkMagic)
106115
if err != nil {
107116
return err
108117
}
109118
}
110119
o.handshakeComplete = <-o.Handshake.Finished
111-
// TODO: register additional mini-protocols
112120
if o.useNodeToNodeProto {
113121
versionNtN := GetProtocolVersionNtN(o.Handshake.Version)
114-
o.ChainSync = chainsync.New(o.muxer, o.ErrorChan, o.useNodeToNodeProto, o.chainSyncCallbackConfig)
115-
o.BlockFetch = blockfetch.New(o.muxer, o.ErrorChan, o.blockFetchCallbackConfig)
122+
protoOptions.Mode = protocol.ProtocolModeNodeToNode
123+
o.ChainSync = chainsync.New(protoOptions, o.chainSyncCallbackConfig)
124+
o.BlockFetch = blockfetch.New(protoOptions, o.blockFetchCallbackConfig)
116125
if versionNtN.EnableKeepAliveProtocol {
117-
o.KeepAlive = keepalive.New(o.muxer, o.ErrorChan, o.keepAliveCallbackConfig)
126+
o.KeepAlive = keepalive.New(protoOptions, o.keepAliveCallbackConfig)
118127
if o.sendKeepAlives {
119128
o.KeepAlive.Start()
120129
}
121130
}
122131
} else {
123132
//versionNtC := GetProtocolVersionNtC(o.Handshake.Version)
124-
o.ChainSync = chainsync.New(o.muxer, o.ErrorChan, o.useNodeToNodeProto, o.chainSyncCallbackConfig)
125-
o.LocalTxSubmission = localtxsubmission.New(o.muxer, o.ErrorChan, o.localTxSubmissionCallbackConfig)
133+
protoOptions.Mode = protocol.ProtocolModeNodeToClient
134+
o.ChainSync = chainsync.New(protoOptions, o.chainSyncCallbackConfig)
135+
o.LocalTxSubmission = localtxsubmission.New(protoOptions, o.localTxSubmissionCallbackConfig)
126136
}
127137
return nil
128138
}

0 commit comments

Comments
 (0)