2015-07-06 17:54:22 -07:00
// Copyright 2014 The go-ethereum Authors
2015-07-22 09:48:40 -07:00
// This file is part of the go-ethereum library.
2015-07-06 17:54:22 -07:00
//
2015-07-23 09:35:11 -07:00
// The go-ethereum library is free software: you can redistribute it and/or modify
2015-07-06 17:54:22 -07:00
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
2015-07-22 09:48:40 -07:00
// The go-ethereum library is distributed in the hope that it will be useful,
2015-07-06 17:54:22 -07:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
2015-07-22 09:48:40 -07:00
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2015-07-06 17:54:22 -07:00
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
2015-07-22 09:48:40 -07:00
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
2015-07-06 17:54:22 -07:00
2015-07-06 20:08:16 -07:00
// Package p2p implements the Ethereum p2p network protocols.
2014-10-23 08:57:54 -07:00
package p2p
import (
2015-02-04 18:07:58 -08:00
"crypto/ecdsa"
2014-11-21 12:48:49 -08:00
"errors"
2014-10-23 08:57:54 -07:00
"fmt"
"net"
"sync"
"time"
2014-11-21 12:48:49 -08:00
"github.com/ethereum/go-ethereum/logger"
2015-04-07 05:57:04 -07:00
"github.com/ethereum/go-ethereum/logger/glog"
2015-02-04 18:07:58 -08:00
"github.com/ethereum/go-ethereum/p2p/discover"
2015-02-11 08:19:31 -08:00
"github.com/ethereum/go-ethereum/p2p/nat"
2014-10-23 08:57:54 -07:00
)
const (
2015-05-13 16:43:30 -07:00
defaultDialTimeout = 15 * time . Second
2015-04-30 09:34:33 -07:00
refreshPeersInterval = 30 * time . Second
staticPeerCheckInterval = 15 * time . Second
2015-03-04 07:27:37 -08:00
2015-05-04 07:35:49 -07:00
// Maximum number of concurrently handshaking inbound connections.
2015-05-13 16:43:30 -07:00
maxAcceptConns = 50
2015-04-10 08:24:41 -07:00
2015-04-30 05:06:05 -07:00
// Maximum number of concurrently dialing outbound connections.
2015-05-15 15:38:28 -07:00
maxActiveDialTasks = 16
2015-04-30 05:06:05 -07:00
2015-05-22 06:38:17 -07:00
// Maximum time allowed for reading a complete message.
// This is effectively the amount of time a connection can be idle.
frameReadTimeout = 30 * time . Second
// Maximum amount of time allowed for writing a complete message.
2015-06-09 03:10:40 -07:00
frameWriteTimeout = 20 * time . Second
2014-10-23 08:57:54 -07:00
)
2015-05-15 15:38:28 -07:00
var errServerStopped = errors . New ( "server stopped" )
2015-02-19 08:09:33 -08:00
var srvjslog = logger . NewJsonLogger ( )
2014-10-23 08:57:54 -07:00
2016-05-18 02:31:00 -07:00
// Config holds Server options.
type Config struct {
2015-02-04 18:07:58 -08:00
// This field must be set to a valid secp256k1 private key.
PrivateKey * ecdsa . PrivateKey
2014-11-21 12:48:49 -08:00
// MaxPeers is the maximum number of peers that can be
// connected. It must be greater than zero.
MaxPeers int
2015-05-04 07:35:49 -07:00
// MaxPendingPeers is the maximum number of peers that can be pending in the
// handshake phase, counted separately for inbound and outbound connections.
// Zero defaults to preset values.
MaxPendingPeers int
2015-05-26 09:07:24 -07:00
// Discovery specifies whether the peer discovery mechanism should be started
// or not. Disabling is usually useful for protocol debugging (manual topology).
Discovery bool
2015-02-04 18:07:58 -08:00
// Name sets the node name of this server.
2015-03-16 03:27:38 -07:00
// Use common.MakeName to create a name that follows existing conventions.
2015-02-04 18:07:58 -08:00
Name string
// Bootstrap nodes are used to establish connectivity
// with the rest of the network.
2015-02-06 15:38:36 -08:00
BootstrapNodes [ ] * discover . Node
2015-02-04 18:07:58 -08:00
2015-04-30 09:32:48 -07:00
// Static nodes are used as pre-configured connections which are always
// maintained and re-connected on disconnects.
StaticNodes [ ] * discover . Node
2015-04-29 08:04:08 -07:00
2015-05-04 03:59:51 -07:00
// Trusted nodes are used as pre-configured connections which are always
// allowed to connect, even above the peer limit.
TrustedNodes [ ] * discover . Node
2015-04-24 08:04:41 -07:00
// NodeDatabase is the path to the database containing the previously seen
// live nodes in the network.
NodeDatabase string
2015-04-23 08:47:24 -07:00
2014-11-21 12:48:49 -08:00
// Protocols should contain the protocols supported
// by the server. Matching protocols are launched for
// each peer.
Protocols [ ] Protocol
// If ListenAddr is set to a non-nil address, the server
// will listen for incoming connections.
//
// If the port is zero, the operating system will pick a port. The
// ListenAddr field will be updated with the actual address when
// the server is started.
ListenAddr string
// If set to a non-nil value, the given NAT port mapper
// is used to make the listening port available to the
// Internet.
2015-02-11 08:19:31 -08:00
NAT nat . Interface
2014-11-21 12:48:49 -08:00
// If Dialer is set to a non-nil value, the given Dialer
// is used to dial outbound peer connections.
Dialer * net . Dialer
// If NoDial is true, the server will not dial any peers.
NoDial bool
2016-11-17 15:50:28 -08:00
//Enables Permissioning
EnableNodePermission bool
//DataDir
DataDir string
2016-05-18 02:31:00 -07:00
}
// Server manages all peer connections.
type Server struct {
// Config fields may not be modified while the server is running.
Config
2014-11-21 12:48:49 -08:00
2015-02-04 18:07:58 -08:00
// Hooks for testing. These are useful because we can inhibit
2014-11-21 12:48:49 -08:00
// the whole protocol stack.
2015-05-15 15:38:28 -07:00
newTransport func ( net . Conn ) transport
newPeerHook func ( * Peer )
lock sync . Mutex // protects running
running bool
2014-10-23 08:57:54 -07:00
2015-05-15 15:38:28 -07:00
ntab discoverTable
listener net . Listener
2015-02-18 16:52:03 -08:00
ourHandshake * protoHandshake
2015-06-21 15:01:56 -07:00
lastLookup time . Time
2015-02-18 16:52:03 -08:00
2015-05-15 15:38:28 -07:00
// These are for Peers, PeerCount (and nothing else).
peerOp chan peerOpFunc
peerOpDone chan struct { }
quit chan struct { }
addstatic chan * discover . Node
2016-06-24 13:27:55 -07:00
removestatic chan * discover . Node
2015-05-15 15:38:28 -07:00
posthandshake chan * conn
addpeer chan * conn
delpeer chan * Peer
loopWG sync . WaitGroup // loop, listenLoop
}
type peerOpFunc func ( map [ discover . NodeID ] * Peer )
type connFlag int
2015-02-04 18:07:58 -08:00
2015-05-15 15:38:28 -07:00
const (
dynDialedConn connFlag = 1 << iota
staticDialedConn
inboundConn
trustedConn
)
// conn wraps a network connection with information gathered
// during the two handshakes.
type conn struct {
fd net . Conn
transport
flags connFlag
cont chan error // The run loop uses cont to signal errors to setupConn.
id discover . NodeID // valid after the encryption handshake
caps [ ] Cap // valid after the protocol handshake
name string // valid after the protocol handshake
}
2015-02-04 18:07:58 -08:00
2015-05-15 15:38:28 -07:00
type transport interface {
// The two handshakes.
doEncHandshake ( prv * ecdsa . PrivateKey , dialDest * discover . Node ) ( discover . NodeID , error )
doProtoHandshake ( our * protoHandshake ) ( * protoHandshake , error )
// The MsgReadWriter can only be used after the encryption
// handshake has completed. The code uses conn.id to track this
// by setting it to a non-nil value after the encryption handshake.
MsgReadWriter
// transports must provide Close because we use MsgPipe in some of
// the tests. Closing the actual network connection doesn't do
// anything in those tests because NsgPipe doesn't use it.
close ( err error )
2014-10-23 08:57:54 -07:00
}
2015-05-15 15:38:28 -07:00
func ( c * conn ) String ( ) string {
s := c . flags . String ( ) + " conn"
if ( c . id != discover . NodeID { } ) {
s += fmt . Sprintf ( " %x" , c . id [ : 8 ] )
}
s += " " + c . fd . RemoteAddr ( ) . String ( )
return s
}
func ( f connFlag ) String ( ) string {
s := ""
if f & trustedConn != 0 {
s += " trusted"
}
if f & dynDialedConn != 0 {
s += " dyn dial"
}
if f & staticDialedConn != 0 {
s += " static dial"
}
if f & inboundConn != 0 {
s += " inbound"
}
if s != "" {
s = s [ 1 : ]
}
return s
}
func ( c * conn ) is ( f connFlag ) bool {
return c . flags & f != 0
}
2014-10-23 08:57:54 -07:00
2014-11-21 12:48:49 -08:00
// Peers returns all connected peers.
2015-05-15 15:38:28 -07:00
func ( srv * Server ) Peers ( ) [ ] * Peer {
var ps [ ] * Peer
select {
// Note: We'd love to put this function into a variable but
// that seems to cause a weird compiler error in some
// environments.
case srv . peerOp <- func ( peers map [ discover . NodeID ] * Peer ) {
for _ , p := range peers {
ps = append ( ps , p )
2014-10-23 08:57:54 -07:00
}
2015-05-15 15:38:28 -07:00
} :
<- srv . peerOpDone
case <- srv . quit :
2014-10-23 08:57:54 -07:00
}
2015-05-15 15:38:28 -07:00
return ps
2014-10-23 08:57:54 -07:00
}
2014-11-21 12:48:49 -08:00
// PeerCount returns the number of connected peers.
func ( srv * Server ) PeerCount ( ) int {
2015-05-15 15:38:28 -07:00
var count int
select {
case srv . peerOp <- func ( ps map [ discover . NodeID ] * Peer ) { count = len ( ps ) } :
<- srv . peerOpDone
case <- srv . quit :
}
return count
2014-10-23 08:57:54 -07:00
}
2015-04-30 06:15:29 -07:00
// AddPeer connects to the given node and maintains the connection until the
// server is shut down. If the connection fails for any reason, the server will
// attempt to reconnect the peer.
func ( srv * Server ) AddPeer ( node * discover . Node ) {
2015-05-15 15:38:28 -07:00
select {
case srv . addstatic <- node :
case <- srv . quit :
}
}
2016-06-24 13:27:55 -07:00
// RemovePeer disconnects from the given node
func ( srv * Server ) RemovePeer ( node * discover . Node ) {
select {
case srv . removestatic <- node :
case <- srv . quit :
}
}
2015-05-15 15:38:28 -07:00
// Self returns the local node's endpoint information.
func ( srv * Server ) Self ( ) * discover . Node {
2015-04-30 02:41:27 -07:00
srv . lock . Lock ( )
defer srv . lock . Unlock ( )
2015-05-26 09:16:05 -07:00
// If the server's not running, return an empty node
2015-05-15 15:38:28 -07:00
if ! srv . running {
return & discover . Node { IP : net . ParseIP ( "0.0.0.0" ) }
}
2015-05-26 09:16:05 -07:00
// If the node is running but discovery is off, manually assemble the node infos
2015-05-26 09:07:24 -07:00
if srv . ntab == nil {
2015-05-26 09:16:05 -07:00
// Inbound connections disabled, use zero address
if srv . listener == nil {
return & discover . Node { IP : net . ParseIP ( "0.0.0.0" ) , ID : discover . PubkeyID ( & srv . PrivateKey . PublicKey ) }
}
// Otherwise inject the listener address too
2015-05-26 09:07:24 -07:00
addr := srv . listener . Addr ( ) . ( * net . TCPAddr )
return & discover . Node {
ID : discover . PubkeyID ( & srv . PrivateKey . PublicKey ) ,
IP : addr . IP ,
TCP : uint16 ( addr . Port ) ,
}
}
2015-05-26 09:16:05 -07:00
// Otherwise return the live node infos
2015-05-15 15:38:28 -07:00
return srv . ntab . Self ( )
}
2015-04-30 02:41:27 -07:00
2015-05-15 15:38:28 -07:00
// Stop terminates the server and all active peer connections.
// It blocks until all active connections have been closed.
func ( srv * Server ) Stop ( ) {
srv . lock . Lock ( )
defer srv . lock . Unlock ( )
if ! srv . running {
return
}
srv . running = false
if srv . listener != nil {
// this unblocks listener Accept
srv . listener . Close ( )
}
close ( srv . quit )
srv . loopWG . Wait ( )
2014-10-23 08:57:54 -07:00
}
2014-11-21 12:48:49 -08:00
// Start starts running the server.
2015-05-15 15:38:28 -07:00
// Servers can not be re-used after stopping.
2014-11-21 12:48:49 -08:00
func ( srv * Server ) Start ( ) ( err error ) {
srv . lock . Lock ( )
defer srv . lock . Unlock ( )
if srv . running {
return errors . New ( "server already running" )
}
2015-05-15 15:38:28 -07:00
srv . running = true
2015-04-07 05:57:04 -07:00
glog . V ( logger . Info ) . Infoln ( "Starting Server" )
2014-11-21 12:48:49 -08:00
2015-02-19 08:08:18 -08:00
// static fields
2015-02-04 18:07:58 -08:00
if srv . PrivateKey == nil {
return fmt . Errorf ( "Server.PrivateKey must be set to a non-nil key" )
2014-10-23 08:57:54 -07:00
}
2015-05-15 15:38:28 -07:00
if srv . newTransport == nil {
srv . newTransport = newRLPX
2015-04-29 08:04:08 -07:00
}
2015-05-15 15:38:28 -07:00
if srv . Dialer == nil {
srv . Dialer = & net . Dialer { Timeout : defaultDialTimeout }
2014-11-21 12:48:49 -08:00
}
2015-05-15 15:38:28 -07:00
srv . quit = make ( chan struct { } )
srv . addpeer = make ( chan * conn )
srv . delpeer = make ( chan * Peer )
srv . posthandshake = make ( chan * conn )
srv . addstatic = make ( chan * discover . Node )
2016-06-24 13:27:55 -07:00
srv . removestatic = make ( chan * discover . Node )
2015-05-15 15:38:28 -07:00
srv . peerOp = make ( chan peerOpFunc )
srv . peerOpDone = make ( chan struct { } )
2015-02-04 18:07:58 -08:00
2015-02-19 08:08:18 -08:00
// node table
2015-05-26 09:07:24 -07:00
if srv . Discovery {
ntab , err := discover . ListenUDP ( srv . PrivateKey , srv . ListenAddr , srv . NAT , srv . NodeDatabase )
if err != nil {
return err
}
2015-12-07 03:06:49 -08:00
if err := ntab . SetFallbackNodes ( srv . BootstrapNodes ) ; err != nil {
return err
}
2015-05-26 09:07:24 -07:00
srv . ntab = ntab
2015-02-04 18:07:58 -08:00
}
2015-05-26 09:07:24 -07:00
2015-12-03 01:45:35 -08:00
dynPeers := ( srv . MaxPeers + 1 ) / 2
2015-05-26 09:07:24 -07:00
if ! srv . Discovery {
dynPeers = 0
}
dialer := newDialState ( srv . StaticNodes , srv . ntab , dynPeers )
2015-02-18 16:52:03 -08:00
2015-02-19 08:08:18 -08:00
// handshake
2015-05-26 09:07:24 -07:00
srv . ourHandshake = & protoHandshake { Version : baseProtocolVersion , Name : srv . Name , ID : discover . PubkeyID ( & srv . PrivateKey . PublicKey ) }
2015-02-18 16:52:03 -08:00
for _ , p := range srv . Protocols {
srv . ourHandshake . Caps = append ( srv . ourHandshake . Caps , p . cap ( ) )
}
2015-02-19 08:08:18 -08:00
// listen/dial
if srv . ListenAddr != "" {
if err := srv . startListening ( ) ; err != nil {
return err
}
}
2014-11-21 12:48:49 -08:00
if srv . NoDial && srv . ListenAddr == "" {
2015-04-07 05:57:04 -07:00
glog . V ( logger . Warn ) . Infoln ( "I will be kind-of useless, neither dialing nor listening." )
2014-11-21 12:48:49 -08:00
}
2015-05-15 15:38:28 -07:00
srv . loopWG . Add ( 1 )
go srv . run ( dialer )
2014-11-21 12:48:49 -08:00
srv . running = true
return nil
2014-10-23 08:57:54 -07:00
}
2014-11-21 12:48:49 -08:00
func ( srv * Server ) startListening ( ) error {
2015-05-15 15:38:28 -07:00
// Launch the TCP listener.
2014-11-21 12:48:49 -08:00
listener , err := net . Listen ( "tcp" , srv . ListenAddr )
if err != nil {
return err
}
2015-02-11 08:19:31 -08:00
laddr := listener . Addr ( ) . ( * net . TCPAddr )
srv . ListenAddr = laddr . String ( )
2015-08-19 12:46:01 -07:00
srv . listener = listener
2015-02-04 18:07:58 -08:00
srv . loopWG . Add ( 1 )
2014-11-21 12:48:49 -08:00
go srv . listenLoop ( )
2015-05-15 15:38:28 -07:00
// Map the TCP listening port if NAT is configured.
2015-02-11 08:19:31 -08:00
if ! laddr . IP . IsLoopback ( ) && srv . NAT != nil {
2015-02-04 18:07:58 -08:00
srv . loopWG . Add ( 1 )
2015-02-11 08:19:31 -08:00
go func ( ) {
nat . Map ( srv . NAT , srv . quit , "tcp" , laddr . Port , laddr . Port , "ethereum p2p" )
srv . loopWG . Done ( )
} ( )
2014-11-21 12:48:49 -08:00
}
return nil
}
2015-05-15 15:38:28 -07:00
type dialer interface {
newTasks ( running int , peers map [ discover . NodeID ] * Peer , now time . Time ) [ ] task
taskDone ( task , time . Time )
addStatic ( * discover . Node )
2016-06-24 13:27:55 -07:00
removeStatic ( * discover . Node )
2015-05-15 15:38:28 -07:00
}
func ( srv * Server ) run ( dialstate dialer ) {
defer srv . loopWG . Done ( )
var (
2016-05-02 08:01:13 -07:00
peers = make ( map [ discover . NodeID ] * Peer )
trusted = make ( map [ discover . NodeID ] bool , len ( srv . TrustedNodes ) )
2015-05-15 15:38:28 -07:00
taskdone = make ( chan task , maxActiveDialTasks )
2016-05-02 08:01:13 -07:00
runningTasks [ ] task
queuedTasks [ ] task // tasks that can't run yet
2015-05-15 15:38:28 -07:00
)
// Put trusted nodes into a map to speed up checks.
// Trusted peers are loaded on startup and cannot be
// modified while the server is running.
for _ , n := range srv . TrustedNodes {
trusted [ n . ID ] = true
}
2016-05-02 08:01:13 -07:00
// removes t from runningTasks
2015-05-15 15:38:28 -07:00
delTask := func ( t task ) {
2016-05-02 08:01:13 -07:00
for i := range runningTasks {
if runningTasks [ i ] == t {
runningTasks = append ( runningTasks [ : i ] , runningTasks [ i + 1 : ] ... )
2015-05-15 15:38:28 -07:00
break
}
}
2014-10-23 08:57:54 -07:00
}
2016-05-02 08:01:13 -07:00
// starts until max number of active tasks is satisfied
startTasks := func ( ts [ ] task ) ( rest [ ] task ) {
i := 0
for ; len ( runningTasks ) < maxActiveDialTasks && i < len ( ts ) ; i ++ {
t := ts [ i ]
glog . V ( logger . Detail ) . Infoln ( "new task:" , t )
go func ( ) { t . Do ( srv ) ; taskdone <- t } ( )
runningTasks = append ( runningTasks , t )
2015-05-15 15:38:28 -07:00
}
2016-05-02 08:01:13 -07:00
return ts [ i : ]
}
scheduleTasks := func ( ) {
// Start from queue first.
queuedTasks = append ( queuedTasks [ : 0 ] , startTasks ( queuedTasks ) ... )
// Query dialer for new tasks and start as many as possible now.
if len ( runningTasks ) < maxActiveDialTasks {
nt := dialstate . newTasks ( len ( runningTasks ) + len ( queuedTasks ) , peers , time . Now ( ) )
queuedTasks = append ( queuedTasks , startTasks ( nt ) ... )
2015-05-15 15:38:28 -07:00
}
}
running :
for {
2016-05-02 08:01:13 -07:00
scheduleTasks ( )
2014-11-21 12:48:49 -08:00
2015-05-15 15:38:28 -07:00
select {
case <- srv . quit :
// The server was stopped. Run the cleanup logic.
glog . V ( logger . Detail ) . Infoln ( "<-quit: spinning down" )
break running
case n := <- srv . addstatic :
// This channel is used by AddPeer to add to the
// ephemeral static peer list. Add it to the dialer,
// it will keep the node connected.
glog . V ( logger . Detail ) . Infoln ( "<-addstatic:" , n )
dialstate . addStatic ( n )
2016-06-24 13:27:55 -07:00
case n := <- srv . removestatic :
// This channel is used by RemovePeer to send a
// disconnect request to a peer and begin the
// stop keeping the node connected
glog . V ( logger . Detail ) . Infoln ( "<-removestatic:" , n )
dialstate . removeStatic ( n )
if p , ok := peers [ n . ID ] ; ok {
p . Disconnect ( DiscRequested )
}
2015-05-15 15:38:28 -07:00
case op := <- srv . peerOp :
// This channel is used by Peers and PeerCount.
op ( peers )
srv . peerOpDone <- struct { } { }
case t := <- taskdone :
// A task got done. Tell dialstate about it so it
// can update its state and remove it from the active
// tasks list.
glog . V ( logger . Detail ) . Infoln ( "<-taskdone:" , t )
2016-05-02 08:01:13 -07:00
dialstate . taskDone ( t , time . Now ( ) )
2015-05-15 15:38:28 -07:00
delTask ( t )
case c := <- srv . posthandshake :
// A connection has passed the encryption handshake so
// the remote identity is known (but hasn't been verified yet).
if trusted [ c . id ] {
// Ensure that the trusted flag is set before checking against MaxPeers.
c . flags |= trustedConn
}
glog . V ( logger . Detail ) . Infoln ( "<-posthandshake:" , c )
// TODO: track in-progress inbound node IDs (pre-Peer) to avoid dialing them.
c . cont <- srv . encHandshakeChecks ( peers , c )
case c := <- srv . addpeer :
// At this point the connection is past the protocol handshake.
// Its capabilities are known and the remote identity is verified.
glog . V ( logger . Detail ) . Infoln ( "<-addpeer:" , c )
err := srv . protoHandshakeChecks ( peers , c )
if err != nil {
glog . V ( logger . Detail ) . Infof ( "Not adding %v as peer: %v" , c , err )
} else {
// The handshakes are done and it passed all checks.
p := newPeer ( c , srv . Protocols )
peers [ c . id ] = p
go srv . runPeer ( p )
}
// The dialer logic relies on the assumption that
// dial tasks complete after the peer has been added or
// discarded. Unblock the task last.
c . cont <- err
case p := <- srv . delpeer :
// A peer disconnected.
glog . V ( logger . Detail ) . Infoln ( "<-delpeer:" , p )
delete ( peers , p . ID ( ) )
}
}
// Terminate discovery. If there is a running lookup it will terminate soon.
2015-05-26 09:07:24 -07:00
if srv . ntab != nil {
srv . ntab . Close ( )
}
2015-05-15 15:38:28 -07:00
// Disconnect all peers.
for _ , p := range peers {
p . Disconnect ( DiscQuitting )
}
// Wait for peers to shut down. Pending connections and tasks are
// not handled here and will terminate soon-ish because srv.quit
// is closed.
2016-05-02 08:01:13 -07:00
glog . V ( logger . Detail ) . Infof ( "ignoring %d pending tasks at spindown" , len ( runningTasks ) )
2015-05-15 15:38:28 -07:00
for len ( peers ) > 0 {
p := <- srv . delpeer
glog . V ( logger . Detail ) . Infoln ( "<-delpeer (spindown):" , p )
delete ( peers , p . ID ( ) )
2014-11-21 12:48:49 -08:00
}
2015-05-15 15:38:28 -07:00
}
2014-11-21 12:48:49 -08:00
2015-05-15 15:38:28 -07:00
func ( srv * Server ) protoHandshakeChecks ( peers map [ discover . NodeID ] * Peer , c * conn ) error {
// Drop connections with no matching protocols.
if len ( srv . Protocols ) > 0 && countMatchingProtocols ( srv . Protocols , c . caps ) == 0 {
return DiscUselessPeer
2014-11-21 12:48:49 -08:00
}
2015-05-15 15:38:28 -07:00
// Repeat the encryption handshake checks because the
// peer set might have changed between the handshakes.
return srv . encHandshakeChecks ( peers , c )
2014-11-21 12:48:49 -08:00
}
2014-10-23 08:57:54 -07:00
2015-05-15 15:38:28 -07:00
func ( srv * Server ) encHandshakeChecks ( peers map [ discover . NodeID ] * Peer , c * conn ) error {
switch {
case ! c . is ( trustedConn | staticDialedConn ) && len ( peers ) >= srv . MaxPeers :
return DiscTooManyPeers
case peers [ c . id ] != nil :
return DiscAlreadyConnected
2015-05-26 09:07:24 -07:00
case c . id == srv . Self ( ) . ID :
2015-05-15 15:38:28 -07:00
return DiscSelf
default :
return nil
2015-04-22 01:59:15 -07:00
}
2015-04-10 04:25:35 -07:00
}
2015-08-19 05:35:01 -07:00
type tempError interface {
Temporary ( ) bool
}
2015-05-15 15:38:28 -07:00
// listenLoop runs in its own goroutine and accepts
// inbound connections.
2014-11-21 12:48:49 -08:00
func ( srv * Server ) listenLoop ( ) {
2015-02-04 18:07:58 -08:00
defer srv . loopWG . Done ( )
2015-05-15 15:38:28 -07:00
glog . V ( logger . Info ) . Infoln ( "Listening on" , srv . listener . Addr ( ) )
2015-04-10 08:24:41 -07:00
// This channel acts as a semaphore limiting
// active inbound connections that are lingering pre-handshake.
// If all slots are taken, no further connections are accepted.
2015-05-04 07:35:49 -07:00
tokens := maxAcceptConns
if srv . MaxPendingPeers > 0 {
tokens = srv . MaxPendingPeers
}
slots := make ( chan struct { } , tokens )
for i := 0 ; i < tokens ; i ++ {
2015-04-10 08:24:41 -07:00
slots <- struct { } { }
}
2014-10-23 08:57:54 -07:00
for {
2015-08-19 05:35:01 -07:00
// Wait for a handshake slot before accepting.
2015-04-10 08:24:41 -07:00
<- slots
2015-08-19 05:35:01 -07:00
var (
fd net . Conn
err error
)
for {
fd , err = srv . listener . Accept ( )
if tempErr , ok := err . ( tempError ) ; ok && tempErr . Temporary ( ) {
glog . V ( logger . Debug ) . Infof ( "Temporary read error: %v" , err )
continue
} else if err != nil {
glog . V ( logger . Debug ) . Infof ( "Read error: %v" , err )
return
}
break
2014-10-23 08:57:54 -07:00
}
2015-08-19 05:35:01 -07:00
fd = newMeteredConn ( fd , true )
glog . V ( logger . Debug ) . Infof ( "Accepted conn %v\n" , fd . RemoteAddr ( ) )
2015-06-21 10:23:37 -07:00
2015-08-19 05:35:01 -07:00
// Spawn the handler. It will give the slot back when the connection
// has been established.
2015-04-10 08:24:41 -07:00
go func ( ) {
2015-08-19 05:35:01 -07:00
srv . setupConn ( fd , inboundConn , nil )
2015-04-10 08:24:41 -07:00
slots <- struct { } { }
} ( )
2014-10-23 08:57:54 -07:00
}
}
2015-05-15 15:38:28 -07:00
// setupConn runs the handshakes and attempts to add the connection
// as a peer. It returns when the connection has been added as a peer
// or the handshakes have failed.
func ( srv * Server ) setupConn ( fd net . Conn , flags connFlag , dialDest * discover . Node ) {
// Prevent leftover pending conns from entering the handshake.
srv . lock . Lock ( )
running := srv . running
srv . lock . Unlock ( )
c := & conn { fd : fd , transport : srv . newTransport ( fd ) , flags : flags , cont : make ( chan error ) }
if ! running {
c . close ( errServerStopped )
return
2015-04-30 05:06:05 -07:00
}
2015-05-15 15:38:28 -07:00
// Run the encryption handshake.
var err error
if c . id , err = c . doEncHandshake ( srv . PrivateKey , dialDest ) ; err != nil {
glog . V ( logger . Debug ) . Infof ( "%v faild enc handshake: %v" , c , err )
c . close ( err )
return
2015-04-02 18:56:17 -07:00
}
2016-11-17 15:50:28 -08:00
//START - QUORUM Permissioning
currentNode := srv . NodeInfo ( ) . ID
cnodeName := srv . NodeInfo ( ) . Name
glog . V ( logger . Debug ) . Infof ( "EnableNodePermission <%v>, DataDir <%v>, Current Node ID <%v>, Node Name <%v>, Dialed Dest<%v>, Connection ID <%v>, Connection String <%v> " , srv . EnableNodePermission , srv . DataDir , currentNode , cnodeName , dialDest , c . id , c . id . String ( ) )
if srv . EnableNodePermission {
glog . V ( logger . Debug ) . Infof ( "Node Permissioning is Enabled. " )
node := c . id . String ( )
direction := "INCOMING"
if dialDest != nil {
node = dialDest . ID . String ( )
direction = "OUTGOING"
glog . V ( logger . Debug ) . Infof ( "Connection Direction <%v>" , direction )
}
if ! isNodePermissioned ( node , currentNode , srv . DataDir , direction ) {
return
}
} else {
glog . V ( logger . Debug ) . Infof ( "Node Permissioning is Disabled. " )
}
//END - QUORUM Permissioning
2015-05-15 15:38:28 -07:00
// For dialed connections, check that the remote public key matches.
if dialDest != nil && c . id != dialDest . ID {
c . close ( DiscUnexpectedIdentity )
glog . V ( logger . Debug ) . Infof ( "%v dialed identity mismatch, want %x" , c , dialDest . ID [ : 8 ] )
return
2014-10-23 08:57:54 -07:00
}
2015-05-15 15:38:28 -07:00
if err := srv . checkpoint ( c , srv . posthandshake ) ; err != nil {
glog . V ( logger . Debug ) . Infof ( "%v failed checkpoint posthandshake: %v" , c , err )
c . close ( err )
2014-11-04 04:21:44 -08:00
return
2014-10-23 08:57:54 -07:00
}
2015-05-15 15:38:28 -07:00
// Run the protocol handshake
phs , err := c . doProtoHandshake ( srv . ourHandshake )
2015-02-04 18:07:58 -08:00
if err != nil {
2015-05-15 15:38:28 -07:00
glog . V ( logger . Debug ) . Infof ( "%v failed proto handshake: %v" , c , err )
c . close ( err )
2015-02-04 18:07:58 -08:00
return
}
2015-05-15 15:38:28 -07:00
if phs . ID != c . id {
glog . V ( logger . Debug ) . Infof ( "%v wrong proto handshake identity: %x" , c , phs . ID [ : 8 ] )
c . close ( DiscUnexpectedIdentity )
return
2015-03-04 07:27:37 -08:00
}
2015-05-15 15:38:28 -07:00
c . caps , c . name = phs . Caps , phs . Name
if err := srv . checkpoint ( c , srv . addpeer ) ; err != nil {
glog . V ( logger . Debug ) . Infof ( "%v failed checkpoint addpeer: %v" , c , err )
c . close ( err )
2015-02-04 18:07:58 -08:00
return
2014-10-23 08:57:54 -07:00
}
2015-05-15 15:38:28 -07:00
// If the checks completed successfully, runPeer has now been
// launched by run.
2015-04-02 18:56:17 -07:00
}
2015-02-19 08:09:33 -08:00
2015-05-15 15:38:28 -07:00
// checkpoint sends the conn to run, which performs the
// post-handshake checks for the stage (posthandshake, addpeer).
func ( srv * Server ) checkpoint ( c * conn , stage chan <- * conn ) error {
select {
case stage <- c :
case <- srv . quit :
return errServerStopped
2015-05-08 06:54:35 -07:00
}
2015-05-15 15:38:28 -07:00
select {
case err := <- c . cont :
return err
case <- srv . quit :
return errServerStopped
2015-05-08 06:54:35 -07:00
}
}
2015-05-15 15:38:28 -07:00
// runPeer runs in its own goroutine for each peer.
// it waits until the Peer logic returns and removes
// the peer.
2015-04-02 18:56:17 -07:00
func ( srv * Server ) runPeer ( p * Peer ) {
2015-04-07 05:57:04 -07:00
glog . V ( logger . Debug ) . Infof ( "Added %v\n" , p )
2015-02-19 08:09:33 -08:00
srvjslog . LogJson ( & logger . P2PConnected {
2015-04-02 18:56:17 -07:00
RemoteId : p . ID ( ) . String ( ) ,
RemoteAddress : p . RemoteAddr ( ) . String ( ) ,
RemoteVersionString : p . Name ( ) ,
2015-02-19 08:09:33 -08:00
NumConnections : srv . PeerCount ( ) ,
} )
2015-05-15 15:38:28 -07:00
2015-02-06 15:13:22 -08:00
if srv . newPeerHook != nil {
srv . newPeerHook ( p )
}
2015-02-13 05:47:05 -08:00
discreason := p . run ( )
2015-05-15 15:38:28 -07:00
// Note: run waits for existing peers to be sent on srv.delpeer
// before returning, so this send should not select on srv.quit.
srv . delpeer <- p
2015-04-07 05:57:04 -07:00
glog . V ( logger . Debug ) . Infof ( "Removed %v (%v)\n" , p , discreason )
2015-02-19 08:09:33 -08:00
srvjslog . LogJson ( & logger . P2PDisconnected {
2015-04-02 18:56:17 -07:00
RemoteId : p . ID ( ) . String ( ) ,
2015-02-19 08:09:33 -08:00
NumConnections : srv . PeerCount ( ) ,
} )
2014-10-23 08:57:54 -07:00
}
2015-10-27 06:10:30 -07:00
// NodeInfo represents a short summary of the information known about the host.
type NodeInfo struct {
ID string ` json:"id" ` // Unique node identifier (also the encryption key)
Name string ` json:"name" ` // Name of the node, including client type, version, OS, custom data
Enode string ` json:"enode" ` // Enode URL for adding this peer from remote peers
IP string ` json:"ip" ` // IP address of the node
Ports struct {
Discovery int ` json:"discovery" ` // UDP listening port for discovery protocol
Listener int ` json:"listener" ` // TCP listening port for RLPx
} ` json:"ports" `
ListenAddr string ` json:"listenAddr" `
Protocols map [ string ] interface { } ` json:"protocols" `
}
// Info gathers and returns a collection of metadata known about the host.
func ( srv * Server ) NodeInfo ( ) * NodeInfo {
node := srv . Self ( )
// Gather and assemble the generic node infos
info := & NodeInfo {
Name : srv . Name ,
Enode : node . String ( ) ,
ID : node . ID . String ( ) ,
IP : node . IP . String ( ) ,
ListenAddr : srv . ListenAddr ,
Protocols : make ( map [ string ] interface { } ) ,
}
info . Ports . Discovery = int ( node . UDP )
info . Ports . Listener = int ( node . TCP )
// Gather all the running protocol infos (only once per protocol type)
for _ , proto := range srv . Protocols {
if _ , ok := info . Protocols [ proto . Name ] ; ! ok {
nodeInfo := interface { } ( "unknown" )
if query := proto . NodeInfo ; query != nil {
nodeInfo = proto . NodeInfo ( )
}
info . Protocols [ proto . Name ] = nodeInfo
}
}
return info
}
// PeersInfo returns an array of metadata objects describing connected peers.
func ( srv * Server ) PeersInfo ( ) [ ] * PeerInfo {
// Gather all the generic and sub-protocol specific infos
infos := make ( [ ] * PeerInfo , 0 , srv . PeerCount ( ) )
for _ , peer := range srv . Peers ( ) {
if peer != nil {
infos = append ( infos , peer . Info ( ) )
}
}
// Sort the result array alphabetically by node identifier
for i := 0 ; i < len ( infos ) ; i ++ {
for j := i + 1 ; j < len ( infos ) ; j ++ {
if infos [ i ] . ID > infos [ j ] . ID {
infos [ i ] , infos [ j ] = infos [ j ] , infos [ i ]
}
}
}
return infos
}