2018-01-26 18:04:13 +00:00
|
|
|
package network
|
|
|
|
|
|
|
|
import (
|
2018-01-31 19:11:08 +00:00
|
|
|
"bytes"
|
2018-01-26 18:04:13 +00:00
|
|
|
"net"
|
2018-01-31 19:11:08 +00:00
|
|
|
|
|
|
|
"github.com/anthdm/neo-go/pkg/network/payload"
|
2018-01-26 18:04:13 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func listenTCP(s *Server, port string) error {
|
|
|
|
ln, err := net.Listen("tcp", port)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-01-31 13:32:57 +00:00
|
|
|
s.listener = ln
|
|
|
|
|
2018-01-26 18:04:13 +00:00
|
|
|
for {
|
|
|
|
conn, err := ln.Accept()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-01-29 18:17:49 +00:00
|
|
|
go handleConnection(s, conn)
|
2018-01-26 18:04:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-28 13:59:32 +00:00
|
|
|
func connectToRemoteNode(s *Server, address string) {
|
|
|
|
conn, err := net.Dial("tcp", address)
|
|
|
|
if err != nil {
|
2018-01-28 17:42:22 +00:00
|
|
|
s.logger.Printf("failed to connect to remote node %s", address)
|
2018-01-28 13:59:32 +00:00
|
|
|
if conn != nil {
|
|
|
|
conn.Close()
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2018-01-29 18:17:49 +00:00
|
|
|
go handleConnection(s, conn)
|
2018-01-28 13:59:32 +00:00
|
|
|
}
|
|
|
|
|
2018-01-26 18:04:13 +00:00
|
|
|
func connectToSeeds(s *Server, addrs []string) {
|
|
|
|
for _, addr := range addrs {
|
2018-01-28 13:59:32 +00:00
|
|
|
go connectToRemoteNode(s, addr)
|
2018-01-26 18:04:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-29 18:17:49 +00:00
|
|
|
func handleConnection(s *Server, conn net.Conn) {
|
2018-01-31 19:11:08 +00:00
|
|
|
peer := NewTCPPeer(conn, s)
|
2018-01-26 18:04:13 +00:00
|
|
|
s.register <- peer
|
|
|
|
|
|
|
|
// remove the peer from connected peers and cleanup the connection.
|
|
|
|
defer func() {
|
2018-01-28 17:42:22 +00:00
|
|
|
// all cleanup will happen in the server's loop when unregister is received.
|
2018-01-26 18:04:13 +00:00
|
|
|
s.unregister <- peer
|
|
|
|
}()
|
|
|
|
|
|
|
|
// Start a goroutine that will handle all writes to the registered peer.
|
|
|
|
go peer.writeLoop()
|
|
|
|
|
2018-01-31 19:11:08 +00:00
|
|
|
// Read from the connection and decode it into a Message ready for processing.
|
|
|
|
buf := make([]byte, 1024)
|
2018-01-26 18:04:13 +00:00
|
|
|
for {
|
2018-01-31 19:11:08 +00:00
|
|
|
_, err := conn.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
s.logger.Printf("conn read error: %s", err)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2018-01-28 10:20:42 +00:00
|
|
|
msg := &Message{}
|
2018-01-31 19:11:08 +00:00
|
|
|
if err := msg.decode(bytes.NewReader(buf)); err != nil {
|
|
|
|
s.logger.Printf("decode error %s", err)
|
2018-01-26 18:04:13 +00:00
|
|
|
break
|
|
|
|
}
|
2018-01-31 19:11:08 +00:00
|
|
|
handleMessage(msg, s, peer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func handleMessage(msg *Message, s *Server, p *TCPPeer) {
|
|
|
|
command := msg.commandType()
|
|
|
|
|
|
|
|
s.logger.Printf("%d :: IN :: %s :: %v", p.id(), command, msg)
|
|
|
|
|
|
|
|
switch command {
|
|
|
|
case cmdVersion:
|
|
|
|
resp := s.handleVersionCmd(msg, p)
|
|
|
|
p.isVerack = true
|
|
|
|
p.nonce = msg.Payload.(*payload.Version).Nonce
|
|
|
|
p.send <- resp
|
|
|
|
case cmdAddr:
|
|
|
|
s.handleAddrCmd(msg, p)
|
|
|
|
case cmdGetAddr:
|
|
|
|
s.handleGetaddrCmd(msg, p)
|
|
|
|
case cmdInv:
|
|
|
|
resp := s.handleInvCmd(msg, p)
|
|
|
|
p.send <- resp
|
|
|
|
case cmdBlock:
|
|
|
|
case cmdConsensus:
|
|
|
|
case cmdTX:
|
|
|
|
case cmdVerack:
|
|
|
|
go s.sendLoop(p)
|
|
|
|
case cmdGetHeaders:
|
|
|
|
case cmdGetBlocks:
|
|
|
|
case cmdGetData:
|
|
|
|
case cmdHeaders:
|
|
|
|
default:
|
2018-01-26 18:04:13 +00:00
|
|
|
}
|
|
|
|
}
|