From 1821ff1a0ef8c697b0f303dff755949ec6ee5cf0 Mon Sep 17 00:00:00 2001 From: anthdm Date: Sun, 28 Jan 2018 14:59:32 +0100 Subject: [PATCH] handle address list message. --- pkg/network/payload/addr.go | 16 +++++++++++++++- pkg/network/peer.go | 3 ++- pkg/network/server.go | 26 +++++++++++++++++++++++--- pkg/network/tcp.go | 26 ++++++++++++++------------ 4 files changed, 54 insertions(+), 17 deletions(-) diff --git a/pkg/network/payload/addr.go b/pkg/network/payload/addr.go index 08ecd61fa..9711a0ece 100644 --- a/pkg/network/payload/addr.go +++ b/pkg/network/payload/addr.go @@ -3,16 +3,30 @@ package payload import ( "bytes" "encoding/binary" + "fmt" ) -// Endpoint host + port of a node. +// Endpoint host + port of a node, compatible with net.Addr. type Endpoint struct { IP [16]byte // TODO: make a uint128 type Port uint16 } +// Network implements the net.Addr interface. +func (e Endpoint) Network() string { return "tcp" } + +// String implements the net.Addr interface. +func (e Endpoint) String() string { + b := make([]uint8, 4) + for i := 0; i < 4; i++ { + b[i] = byte(e.IP[len(e.IP)-4+i]) + } + return fmt.Sprintf("%d.%d.%d.%d:%d", b[0], b[1], b[2], b[3], e.Port) +} + // AddrWithTime payload type AddrWithTime struct { + // Timestamp the node connected to the network. Timestamp uint32 Services uint64 Addr Endpoint diff --git a/pkg/network/peer.go b/pkg/network/peer.go index 68adb4b00..d0c54dcb1 100644 --- a/pkg/network/peer.go +++ b/pkg/network/peer.go @@ -7,7 +7,8 @@ import ( // Peer represents a remote node, backed by TCP transport. type Peer struct { - // underlaying TCP connection + id uint32 + // underlying TCP connection conn net.Conn // channel to coordinate message writes back to the connection. send chan *Message diff --git a/pkg/network/server.go b/pkg/network/server.go index c9e3adaae..9f5d615c7 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -7,6 +7,7 @@ import ( "net" "os" "strconv" + "sync" "time" "github.com/anthdm/neo-go/pkg/network/payload" @@ -23,7 +24,7 @@ const ( var ( // rpcLogger used for debugging RPC messages between nodes. - rpcLogger = log.New(os.Stdout, "RPC :: ", 0) + rpcLogger = log.New(os.Stdout, "", 0) ) type messageTuple struct { @@ -35,6 +36,8 @@ type messageTuple struct { type Server struct { logger *log.Logger + mtx sync.RWMutex + // id of the server id uint32 @@ -171,7 +174,7 @@ func (s *Server) loop() { // TODO: unregister peers on error. // processMessage processes the received message from a remote node. func (s *Server) processMessage(msg *Message, peer *Peer) error { - rpcLogger.Printf("IN :: %s :: %+v", msg.commandType(), msg.Payload) + rpcLogger.Printf("[NODE %d] :: IN :: %s :: %+v", peer.id, msg.commandType(), msg.Payload) switch msg.commandType() { case cmdVersion: @@ -216,6 +219,7 @@ func (s *Server) handleVersionCmd(v *payload.Version, peer *Peer) error { // we respond with a verack, we successfully received peer's version // at this point. peer.verack = true + peer.id = v.Nonce verackMsg := newMessage(s.net, cmdVerack, nil) peer.send <- verackMsg @@ -224,13 +228,29 @@ func (s *Server) handleVersionCmd(v *payload.Version, peer *Peer) error { return nil } +// When the remote node reveals its known peers we try to connect to all of them. func (s *Server) handleAddrCmd(addrList *payload.AddressList, peer *Peer) error { for _, addr := range addrList.Addrs { - fmt.Println(addr) + if !s.addrAlreadyConnected(addr.Addr) { + go connectToRemoteNode(s, addr.Addr.String()) + } } return nil } +func (s *Server) addrAlreadyConnected(addr net.Addr) bool { + // TODO: check for race conditions + //s.mtx.RLock() + //defer s.mtx.RUnlock() + + for peer := range s.peers { + if peer.conn.RemoteAddr().String() == addr.String() { + return true + } + } + return false +} + // After receiving the "getaddr" the server needs to respond with an "addr" message. // providing information about the other nodes in the network. // e.g. this server's connected peers. diff --git a/pkg/network/tcp.go b/pkg/network/tcp.go index 408be9b06..06249d132 100644 --- a/pkg/network/tcp.go +++ b/pkg/network/tcp.go @@ -2,7 +2,6 @@ package network import ( "io" - "log" "net" ) @@ -21,19 +20,22 @@ func listenTCP(s *Server, port string) error { } } +func connectToRemoteNode(s *Server, address string) { + conn, err := net.Dial("tcp", address) + if err != nil { + s.logger.Printf("failed to connects to remote node %s", address) + if conn != nil { + conn.Close() + } + return + } + s.logger.Printf("connected to %s", conn.RemoteAddr()) + go handleConnection(s, conn, false) +} + func connectToSeeds(s *Server, addrs []string) { for _, addr := range addrs { - go func(addr string) { - conn, err := net.Dial("tcp", addr) - if err != nil { - log.Printf("failed to connect to remote node %s: %s", addr, err) - if conn != nil { - conn.Close() - } - return - } - go handleConnection(s, conn, false) - }(addr) + go connectToRemoteNode(s, addr) } }