handle address list message.

This commit is contained in:
anthdm 2018-01-28 14:59:32 +01:00
parent 1eab73d560
commit 1821ff1a0e
4 changed files with 54 additions and 17 deletions

View file

@ -3,16 +3,30 @@ package payload
import ( import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"fmt"
) )
// Endpoint host + port of a node. // Endpoint host + port of a node, compatible with net.Addr.
type Endpoint struct { type Endpoint struct {
IP [16]byte // TODO: make a uint128 type IP [16]byte // TODO: make a uint128 type
Port uint16 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 // AddrWithTime payload
type AddrWithTime struct { type AddrWithTime struct {
// Timestamp the node connected to the network.
Timestamp uint32 Timestamp uint32
Services uint64 Services uint64
Addr Endpoint Addr Endpoint

View file

@ -7,7 +7,8 @@ import (
// Peer represents a remote node, backed by TCP transport. // Peer represents a remote node, backed by TCP transport.
type Peer struct { type Peer struct {
// underlaying TCP connection id uint32
// underlying TCP connection
conn net.Conn conn net.Conn
// channel to coordinate message writes back to the connection. // channel to coordinate message writes back to the connection.
send chan *Message send chan *Message

View file

@ -7,6 +7,7 @@ import (
"net" "net"
"os" "os"
"strconv" "strconv"
"sync"
"time" "time"
"github.com/anthdm/neo-go/pkg/network/payload" "github.com/anthdm/neo-go/pkg/network/payload"
@ -23,7 +24,7 @@ const (
var ( var (
// rpcLogger used for debugging RPC messages between nodes. // rpcLogger used for debugging RPC messages between nodes.
rpcLogger = log.New(os.Stdout, "RPC :: ", 0) rpcLogger = log.New(os.Stdout, "", 0)
) )
type messageTuple struct { type messageTuple struct {
@ -35,6 +36,8 @@ type messageTuple struct {
type Server struct { type Server struct {
logger *log.Logger logger *log.Logger
mtx sync.RWMutex
// id of the server // id of the server
id uint32 id uint32
@ -171,7 +174,7 @@ func (s *Server) loop() {
// TODO: unregister peers on error. // TODO: unregister peers on error.
// processMessage processes the received message from a remote node. // processMessage processes the received message from a remote node.
func (s *Server) processMessage(msg *Message, peer *Peer) error { 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() { switch msg.commandType() {
case cmdVersion: 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 // we respond with a verack, we successfully received peer's version
// at this point. // at this point.
peer.verack = true peer.verack = true
peer.id = v.Nonce
verackMsg := newMessage(s.net, cmdVerack, nil) verackMsg := newMessage(s.net, cmdVerack, nil)
peer.send <- verackMsg peer.send <- verackMsg
@ -224,13 +228,29 @@ func (s *Server) handleVersionCmd(v *payload.Version, peer *Peer) error {
return nil 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 { func (s *Server) handleAddrCmd(addrList *payload.AddressList, peer *Peer) error {
for _, addr := range addrList.Addrs { for _, addr := range addrList.Addrs {
fmt.Println(addr) if !s.addrAlreadyConnected(addr.Addr) {
go connectToRemoteNode(s, addr.Addr.String())
}
} }
return nil 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. // After receiving the "getaddr" the server needs to respond with an "addr" message.
// providing information about the other nodes in the network. // providing information about the other nodes in the network.
// e.g. this server's connected peers. // e.g. this server's connected peers.

View file

@ -2,7 +2,6 @@ package network
import ( import (
"io" "io"
"log"
"net" "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) { func connectToSeeds(s *Server, addrs []string) {
for _, addr := range addrs { for _, addr := range addrs {
go func(addr string) { go connectToRemoteNode(s, addr)
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)
} }
} }