|
|
@ -23,6 +23,7 @@ import ( |
|
|
|
"fmt" |
|
|
|
"fmt" |
|
|
|
"net" |
|
|
|
"net" |
|
|
|
"sync" |
|
|
|
"sync" |
|
|
|
|
|
|
|
"sync/atomic" |
|
|
|
"time" |
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
@ -169,6 +170,8 @@ type Server struct { |
|
|
|
quit chan struct{} |
|
|
|
quit chan struct{} |
|
|
|
addstatic chan *discover.Node |
|
|
|
addstatic chan *discover.Node |
|
|
|
removestatic chan *discover.Node |
|
|
|
removestatic chan *discover.Node |
|
|
|
|
|
|
|
addtrusted chan *discover.Node |
|
|
|
|
|
|
|
removetrusted chan *discover.Node |
|
|
|
posthandshake chan *conn |
|
|
|
posthandshake chan *conn |
|
|
|
addpeer chan *conn |
|
|
|
addpeer chan *conn |
|
|
|
delpeer chan peerDrop |
|
|
|
delpeer chan peerDrop |
|
|
@ -185,7 +188,7 @@ type peerDrop struct { |
|
|
|
requested bool // true if signaled by the peer
|
|
|
|
requested bool // true if signaled by the peer
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type connFlag int |
|
|
|
type connFlag int32 |
|
|
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
const ( |
|
|
|
dynDialedConn connFlag = 1 << iota |
|
|
|
dynDialedConn connFlag = 1 << iota |
|
|
@ -250,7 +253,18 @@ func (f connFlag) String() string { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (c *conn) is(f connFlag) bool { |
|
|
|
func (c *conn) is(f connFlag) bool { |
|
|
|
return c.flags&f != 0 |
|
|
|
flags := connFlag(atomic.LoadInt32((*int32)(&c.flags))) |
|
|
|
|
|
|
|
return flags&f != 0 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (c *conn) set(f connFlag, val bool) { |
|
|
|
|
|
|
|
flags := connFlag(atomic.LoadInt32((*int32)(&c.flags))) |
|
|
|
|
|
|
|
if val { |
|
|
|
|
|
|
|
flags |= f |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
flags &= ^f |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
atomic.StoreInt32((*int32)(&c.flags), int32(flags)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Peers returns all connected peers.
|
|
|
|
// Peers returns all connected peers.
|
|
|
@ -300,6 +314,23 @@ func (srv *Server) RemovePeer(node *discover.Node) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// AddTrustedPeer adds the given node to a reserved whitelist which allows the
|
|
|
|
|
|
|
|
// node to always connect, even if the slot are full.
|
|
|
|
|
|
|
|
func (srv *Server) AddTrustedPeer(node *discover.Node) { |
|
|
|
|
|
|
|
select { |
|
|
|
|
|
|
|
case srv.addtrusted <- node: |
|
|
|
|
|
|
|
case <-srv.quit: |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// RemoveTrustedPeer removes the given node from the trusted peer set.
|
|
|
|
|
|
|
|
func (srv *Server) RemoveTrustedPeer(node *discover.Node) { |
|
|
|
|
|
|
|
select { |
|
|
|
|
|
|
|
case srv.removetrusted <- node: |
|
|
|
|
|
|
|
case <-srv.quit: |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// SubscribePeers subscribes the given channel to peer events
|
|
|
|
// SubscribePeers subscribes the given channel to peer events
|
|
|
|
func (srv *Server) SubscribeEvents(ch chan *PeerEvent) event.Subscription { |
|
|
|
func (srv *Server) SubscribeEvents(ch chan *PeerEvent) event.Subscription { |
|
|
|
return srv.peerFeed.Subscribe(ch) |
|
|
|
return srv.peerFeed.Subscribe(ch) |
|
|
@ -411,6 +442,8 @@ func (srv *Server) Start() (err error) { |
|
|
|
srv.posthandshake = make(chan *conn) |
|
|
|
srv.posthandshake = make(chan *conn) |
|
|
|
srv.addstatic = make(chan *discover.Node) |
|
|
|
srv.addstatic = make(chan *discover.Node) |
|
|
|
srv.removestatic = make(chan *discover.Node) |
|
|
|
srv.removestatic = make(chan *discover.Node) |
|
|
|
|
|
|
|
srv.addtrusted = make(chan *discover.Node) |
|
|
|
|
|
|
|
srv.removetrusted = make(chan *discover.Node) |
|
|
|
srv.peerOp = make(chan peerOpFunc) |
|
|
|
srv.peerOp = make(chan peerOpFunc) |
|
|
|
srv.peerOpDone = make(chan struct{}) |
|
|
|
srv.peerOpDone = make(chan struct{}) |
|
|
|
|
|
|
|
|
|
|
@ -547,8 +580,7 @@ func (srv *Server) run(dialstate dialer) { |
|
|
|
queuedTasks []task // tasks that can't run yet
|
|
|
|
queuedTasks []task // tasks that can't run yet
|
|
|
|
) |
|
|
|
) |
|
|
|
// Put trusted nodes into a map to speed up checks.
|
|
|
|
// Put trusted nodes into a map to speed up checks.
|
|
|
|
// Trusted peers are loaded on startup and cannot be
|
|
|
|
// Trusted peers are loaded on startup or added via AddTrustedPeer RPC.
|
|
|
|
// modified while the server is running.
|
|
|
|
|
|
|
|
for _, n := range srv.TrustedNodes { |
|
|
|
for _, n := range srv.TrustedNodes { |
|
|
|
trusted[n.ID] = true |
|
|
|
trusted[n.ID] = true |
|
|
|
} |
|
|
|
} |
|
|
@ -600,12 +632,32 @@ running: |
|
|
|
case n := <-srv.removestatic: |
|
|
|
case n := <-srv.removestatic: |
|
|
|
// This channel is used by RemovePeer to send a
|
|
|
|
// This channel is used by RemovePeer to send a
|
|
|
|
// disconnect request to a peer and begin the
|
|
|
|
// disconnect request to a peer and begin the
|
|
|
|
// stop keeping the node connected
|
|
|
|
// stop keeping the node connected.
|
|
|
|
srv.log.Trace("Removing static node", "node", n) |
|
|
|
srv.log.Trace("Removing static node", "node", n) |
|
|
|
dialstate.removeStatic(n) |
|
|
|
dialstate.removeStatic(n) |
|
|
|
if p, ok := peers[n.ID]; ok { |
|
|
|
if p, ok := peers[n.ID]; ok { |
|
|
|
p.Disconnect(DiscRequested) |
|
|
|
p.Disconnect(DiscRequested) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
case n := <-srv.addtrusted: |
|
|
|
|
|
|
|
// This channel is used by AddTrustedPeer to add an enode
|
|
|
|
|
|
|
|
// to the trusted node set.
|
|
|
|
|
|
|
|
srv.log.Trace("Adding trusted node", "node", n) |
|
|
|
|
|
|
|
trusted[n.ID] = true |
|
|
|
|
|
|
|
// Mark any already-connected peer as trusted
|
|
|
|
|
|
|
|
if p, ok := peers[n.ID]; ok { |
|
|
|
|
|
|
|
p.rw.set(trustedConn, true) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case n := <-srv.removetrusted: |
|
|
|
|
|
|
|
// This channel is used by RemoveTrustedPeer to remove an enode
|
|
|
|
|
|
|
|
// from the trusted node set.
|
|
|
|
|
|
|
|
srv.log.Trace("Removing trusted node", "node", n) |
|
|
|
|
|
|
|
if _, ok := trusted[n.ID]; ok { |
|
|
|
|
|
|
|
delete(trusted, n.ID) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Unmark any already-connected peer as trusted
|
|
|
|
|
|
|
|
if p, ok := peers[n.ID]; ok { |
|
|
|
|
|
|
|
p.rw.set(trustedConn, false) |
|
|
|
|
|
|
|
} |
|
|
|
case op := <-srv.peerOp: |
|
|
|
case op := <-srv.peerOp: |
|
|
|
// This channel is used by Peers and PeerCount.
|
|
|
|
// This channel is used by Peers and PeerCount.
|
|
|
|
op(peers) |
|
|
|
op(peers) |
|
|
|