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 (
"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

View file

@ -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

View file

@ -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.

View file

@ -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)
}
}