forked from TrueCloudLab/neoneo-go
handle address list message.
This commit is contained in:
parent
1eab73d560
commit
1821ff1a0e
4 changed files with 54 additions and 17 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue