diff --git a/ethereum.go b/ethereum.go index d9281cd574..a6cb78b1fc 100644 --- a/ethereum.go +++ b/ethereum.go @@ -149,7 +149,9 @@ func (s *Ethereum) IsUpToDate() bool { }) return upToDate } - +func (s *Ethereum) PushPeer(peer *Peer) { + s.peers.PushBack(peer) +} func (s *Ethereum) IsListening() bool { return s.listening } @@ -159,14 +161,11 @@ func (s *Ethereum) AddPeer(conn net.Conn) { if peer != nil { if s.peers.Len() < s.MaxPeers { - s.peers.PushBack(peer) peer.Start() } else { ethutil.Config.Log.Debugf("[SERV] Max connected peers reached. Not adding incoming peer.") } } - - s.reactor.Post("peerList", s.peers) } func (s *Ethereum) ProcessPeerList(addrs []string) { @@ -233,12 +232,7 @@ func (s *Ethereum) ConnectToPeer(addr string) error { return nil } - peer := NewOutboundPeer(addr, s, s.serverCaps) - - s.peers.PushBack(peer) - - ethutil.Config.Log.Infof("[SERV] Adding peer (%s) %d / %d\n", addr, s.peers.Len(), s.MaxPeers) - s.reactor.Post("peerList", s.peers) + NewOutboundPeer(addr, s, s.serverCaps) } return nil diff --git a/peer.go b/peer.go index 07c93e5b45..2ece9b3596 100644 --- a/peer.go +++ b/peer.go @@ -2,6 +2,7 @@ package eth import ( "bytes" + "container/list" "fmt" "github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethutil" @@ -124,6 +125,7 @@ type Peer struct { port uint16 caps Caps + // This peer's public key pubkey []byte // Indicated whether the node is catching up or not @@ -171,7 +173,7 @@ func NewOutboundPeer(addr string, ethereum *Ethereum, caps Caps) *Peer { // Set up the connection in another goroutine so we don't block the main thread go func() { - conn, err := net.DialTimeout("tcp", addr, 30*time.Second) + conn, err := net.DialTimeout("tcp", addr, 10*time.Second) if err != nil { ethutil.Config.Log.Debugln("Connection to peer failed", err) @@ -614,6 +616,30 @@ func (p *Peer) pushPeers() { func (p *Peer) handleHandshake(msg *ethwire.Msg) { c := msg.Data + // Set pubkey + p.pubkey = c.Get(5).Bytes() + + if p.pubkey == nil { + //ethutil.Config.Log.Debugln("Pubkey required, not supplied in handshake.") + p.Stop() + return + } + + usedPub := 0 + // This peer is already added to the peerlist so we expect to find a double pubkey at least once + + eachPeer(p.ethereum.Peers(), func(peer *Peer, e *list.Element) { + if bytes.Compare(p.pubkey, peer.pubkey) == 0 { + usedPub++ + } + }) + + if usedPub > 0 { + //ethutil.Config.Log.Debugf("Pubkey %x found more then once. Already connected to client.", p.pubkey) + p.Stop() + return + } + if c.Get(0).Uint() != ProtocolVersion { ethutil.Config.Log.Debugf("Invalid peer version. Require protocol: %d. Received: %d\n", ProtocolVersion, c.Get(0).Uint()) p.Stop() @@ -625,7 +651,6 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) { // If this is an inbound connection send an ack back if p.inbound { - p.pubkey = c.Get(5).Bytes() p.port = uint16(c.Get(4).Uint()) // Self connect detection @@ -647,6 +672,11 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) { p.SetVersion(c.Get(2).Str()) } + p.ethereum.PushPeer(p) + p.ethereum.reactor.Post("peerList", p.ethereum.Peers()) + + ethutil.Config.Log.Infof("[SERV] Added peer (%s) %d / %d\n", p.conn.RemoteAddr(), p.ethereum.Peers().Len(), p.ethereum.MaxPeers) + // Catch up with the connected peer if !p.ethereum.IsUpToDate() { ethutil.Config.Log.Debugln("Already syncing up with a peer; sleeping")