github.com/jonasnick/go-ethereum@v0.7.12-0.20150216215225-22176f05d387/p2p/server.go (about)

     1  package p2p
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/ecdsa"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  	"net"
    10  	"runtime"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/jonasnick/go-ethereum/logger"
    15  	"github.com/jonasnick/go-ethereum/p2p/discover"
    16  	"github.com/jonasnick/go-ethereum/p2p/nat"
    17  )
    18  
    19  const (
    20  	handshakeTimeout     = 5 * time.Second
    21  	defaultDialTimeout   = 10 * time.Second
    22  	refreshPeersInterval = 30 * time.Second
    23  )
    24  
    25  var srvlog = logger.NewLogger("P2P Server")
    26  
    27  // MakeName creates a node name that follows the ethereum convention
    28  // for such names. It adds the operation system name and Go runtime version
    29  // the name.
    30  func MakeName(name, version string) string {
    31  	return fmt.Sprintf("%s/v%s/%s/%s", name, version, runtime.GOOS, runtime.Version())
    32  }
    33  
    34  // Server manages all peer connections.
    35  //
    36  // The fields of Server are used as configuration parameters.
    37  // You should set them before starting the Server. Fields may not be
    38  // modified while the server is running.
    39  type Server struct {
    40  	// This field must be set to a valid secp256k1 private key.
    41  	PrivateKey *ecdsa.PrivateKey
    42  
    43  	// MaxPeers is the maximum number of peers that can be
    44  	// connected. It must be greater than zero.
    45  	MaxPeers int
    46  
    47  	// Name sets the node name of this server.
    48  	// Use MakeName to create a name that follows existing conventions.
    49  	Name string
    50  
    51  	// Bootstrap nodes are used to establish connectivity
    52  	// with the rest of the network.
    53  	BootstrapNodes []*discover.Node
    54  
    55  	// Protocols should contain the protocols supported
    56  	// by the server. Matching protocols are launched for
    57  	// each peer.
    58  	Protocols []Protocol
    59  
    60  	// If Blacklist is set to a non-nil value, the given Blacklist
    61  	// is used to verify peer connections.
    62  	Blacklist Blacklist
    63  
    64  	// If ListenAddr is set to a non-nil address, the server
    65  	// will listen for incoming connections.
    66  	//
    67  	// If the port is zero, the operating system will pick a port. The
    68  	// ListenAddr field will be updated with the actual address when
    69  	// the server is started.
    70  	ListenAddr string
    71  
    72  	// If set to a non-nil value, the given NAT port mapper
    73  	// is used to make the listening port available to the
    74  	// Internet.
    75  	NAT nat.Interface
    76  
    77  	// If Dialer is set to a non-nil value, the given Dialer
    78  	// is used to dial outbound peer connections.
    79  	Dialer *net.Dialer
    80  
    81  	// If NoDial is true, the server will not dial any peers.
    82  	NoDial bool
    83  
    84  	// Hooks for testing. These are useful because we can inhibit
    85  	// the whole protocol stack.
    86  	handshakeFunc
    87  	newPeerHook
    88  
    89  	lock     sync.RWMutex
    90  	running  bool
    91  	listener net.Listener
    92  	peers    map[discover.NodeID]*Peer
    93  
    94  	ntab *discover.Table
    95  
    96  	quit        chan struct{}
    97  	loopWG      sync.WaitGroup // {dial,listen,nat}Loop
    98  	peerWG      sync.WaitGroup // active peer goroutines
    99  	peerConnect chan *discover.Node
   100  }
   101  
   102  type handshakeFunc func(io.ReadWriter, *ecdsa.PrivateKey, *discover.Node) (discover.NodeID, []byte, error)
   103  type newPeerHook func(*Peer)
   104  
   105  // Peers returns all connected peers.
   106  func (srv *Server) Peers() (peers []*Peer) {
   107  	srv.lock.RLock()
   108  	defer srv.lock.RUnlock()
   109  	for _, peer := range srv.peers {
   110  		if peer != nil {
   111  			peers = append(peers, peer)
   112  		}
   113  	}
   114  	return
   115  }
   116  
   117  // PeerCount returns the number of connected peers.
   118  func (srv *Server) PeerCount() int {
   119  	srv.lock.RLock()
   120  	n := len(srv.peers)
   121  	srv.lock.RUnlock()
   122  	return n
   123  }
   124  
   125  // SuggestPeer creates a connection to the given Node if it
   126  // is not already connected.
   127  func (srv *Server) SuggestPeer(n *discover.Node) {
   128  	srv.peerConnect <- n
   129  }
   130  
   131  // Broadcast sends an RLP-encoded message to all connected peers.
   132  // This method is deprecated and will be removed later.
   133  func (srv *Server) Broadcast(protocol string, code uint64, data ...interface{}) {
   134  	var payload []byte
   135  	if data != nil {
   136  		payload = encodePayload(data...)
   137  	}
   138  	srv.lock.RLock()
   139  	defer srv.lock.RUnlock()
   140  	for _, peer := range srv.peers {
   141  		if peer != nil {
   142  			var msg = Msg{Code: code}
   143  			if data != nil {
   144  				msg.Payload = bytes.NewReader(payload)
   145  				msg.Size = uint32(len(payload))
   146  			}
   147  			peer.writeProtoMsg(protocol, msg)
   148  		}
   149  	}
   150  }
   151  
   152  // Start starts running the server.
   153  // Servers can be re-used and started again after stopping.
   154  func (srv *Server) Start() (err error) {
   155  	srv.lock.Lock()
   156  	defer srv.lock.Unlock()
   157  	if srv.running {
   158  		return errors.New("server already running")
   159  	}
   160  	srvlog.Infoln("Starting Server")
   161  
   162  	// initialize all the fields
   163  	if srv.PrivateKey == nil {
   164  		return fmt.Errorf("Server.PrivateKey must be set to a non-nil key")
   165  	}
   166  	if srv.MaxPeers <= 0 {
   167  		return fmt.Errorf("Server.MaxPeers must be > 0")
   168  	}
   169  	srv.quit = make(chan struct{})
   170  	srv.peers = make(map[discover.NodeID]*Peer)
   171  	srv.peerConnect = make(chan *discover.Node)
   172  
   173  	if srv.handshakeFunc == nil {
   174  		srv.handshakeFunc = encHandshake
   175  	}
   176  	if srv.Blacklist == nil {
   177  		srv.Blacklist = NewBlacklist()
   178  	}
   179  	if srv.ListenAddr != "" {
   180  		if err := srv.startListening(); err != nil {
   181  			return err
   182  		}
   183  	}
   184  
   185  	// dial stuff
   186  	dt, err := discover.ListenUDP(srv.PrivateKey, srv.ListenAddr, srv.NAT)
   187  	if err != nil {
   188  		return err
   189  	}
   190  	srv.ntab = dt
   191  	if srv.Dialer == nil {
   192  		srv.Dialer = &net.Dialer{Timeout: defaultDialTimeout}
   193  	}
   194  	if !srv.NoDial {
   195  		srv.loopWG.Add(1)
   196  		go srv.dialLoop()
   197  	}
   198  	if srv.NoDial && srv.ListenAddr == "" {
   199  		srvlog.Warnln("I will be kind-of useless, neither dialing nor listening.")
   200  	}
   201  
   202  	srv.running = true
   203  	return nil
   204  }
   205  
   206  func (srv *Server) startListening() error {
   207  	listener, err := net.Listen("tcp", srv.ListenAddr)
   208  	if err != nil {
   209  		return err
   210  	}
   211  	laddr := listener.Addr().(*net.TCPAddr)
   212  	srv.ListenAddr = laddr.String()
   213  	srv.listener = listener
   214  	srv.loopWG.Add(1)
   215  	go srv.listenLoop()
   216  	if !laddr.IP.IsLoopback() && srv.NAT != nil {
   217  		srv.loopWG.Add(1)
   218  		go func() {
   219  			nat.Map(srv.NAT, srv.quit, "tcp", laddr.Port, laddr.Port, "ethereum p2p")
   220  			srv.loopWG.Done()
   221  		}()
   222  	}
   223  	return nil
   224  }
   225  
   226  // Stop terminates the server and all active peer connections.
   227  // It blocks until all active connections have been closed.
   228  func (srv *Server) Stop() {
   229  	srv.lock.Lock()
   230  	if !srv.running {
   231  		srv.lock.Unlock()
   232  		return
   233  	}
   234  	srv.running = false
   235  	srv.lock.Unlock()
   236  
   237  	srvlog.Infoln("Stopping Server")
   238  	srv.ntab.Close()
   239  	if srv.listener != nil {
   240  		// this unblocks listener Accept
   241  		srv.listener.Close()
   242  	}
   243  	close(srv.quit)
   244  	srv.loopWG.Wait()
   245  
   246  	// No new peers can be added at this point because dialLoop and
   247  	// listenLoop are down. It is safe to call peerWG.Wait because
   248  	// peerWG.Add is not called outside of those loops.
   249  	for _, peer := range srv.peers {
   250  		peer.Disconnect(DiscQuitting)
   251  	}
   252  	srv.peerWG.Wait()
   253  }
   254  
   255  // main loop for adding connections via listening
   256  func (srv *Server) listenLoop() {
   257  	defer srv.loopWG.Done()
   258  	srvlog.Infoln("Listening on", srv.listener.Addr())
   259  	for {
   260  		conn, err := srv.listener.Accept()
   261  		if err != nil {
   262  			return
   263  		}
   264  		srvlog.Debugf("Accepted conn %v\n", conn.RemoteAddr())
   265  		srv.peerWG.Add(1)
   266  		go srv.startPeer(conn, nil)
   267  	}
   268  }
   269  
   270  func (srv *Server) dialLoop() {
   271  	defer srv.loopWG.Done()
   272  	refresh := time.NewTicker(refreshPeersInterval)
   273  	defer refresh.Stop()
   274  
   275  	srv.ntab.Bootstrap(srv.BootstrapNodes)
   276  	go srv.findPeers()
   277  
   278  	dialed := make(chan *discover.Node)
   279  	dialing := make(map[discover.NodeID]bool)
   280  
   281  	// TODO: limit number of active dials
   282  	// TODO: ensure only one findPeers goroutine is running
   283  	// TODO: pause findPeers when we're at capacity
   284  
   285  	for {
   286  		select {
   287  		case <-refresh.C:
   288  
   289  			go srv.findPeers()
   290  
   291  		case dest := <-srv.peerConnect:
   292  			// avoid dialing nodes that are already connected.
   293  			// there is another check for this in addPeer,
   294  			// which runs after the handshake.
   295  			srv.lock.Lock()
   296  			_, isconnected := srv.peers[dest.ID]
   297  			srv.lock.Unlock()
   298  			if isconnected || dialing[dest.ID] || dest.ID == srv.ntab.Self() {
   299  				continue
   300  			}
   301  
   302  			dialing[dest.ID] = true
   303  			srv.peerWG.Add(1)
   304  			go func() {
   305  				srv.dialNode(dest)
   306  				// at this point, the peer has been added
   307  				// or discarded. either way, we're not dialing it anymore.
   308  				dialed <- dest
   309  			}()
   310  
   311  		case dest := <-dialed:
   312  			delete(dialing, dest.ID)
   313  
   314  		case <-srv.quit:
   315  			// TODO: maybe wait for active dials
   316  			return
   317  		}
   318  	}
   319  }
   320  
   321  func (srv *Server) dialNode(dest *discover.Node) {
   322  	addr := &net.TCPAddr{IP: dest.IP, Port: dest.TCPPort}
   323  	srvlog.Debugf("Dialing %v\n", dest)
   324  	conn, err := srv.Dialer.Dial("tcp", addr.String())
   325  	if err != nil {
   326  		srvlog.DebugDetailf("dial error: %v", err)
   327  		return
   328  	}
   329  	srv.startPeer(conn, dest)
   330  }
   331  
   332  func (srv *Server) findPeers() {
   333  	far := srv.ntab.Self()
   334  	for i := range far {
   335  		far[i] = ^far[i]
   336  	}
   337  	closeToSelf := srv.ntab.Lookup(srv.ntab.Self())
   338  	farFromSelf := srv.ntab.Lookup(far)
   339  
   340  	for i := 0; i < len(closeToSelf) || i < len(farFromSelf); i++ {
   341  		if i < len(closeToSelf) {
   342  			srv.peerConnect <- closeToSelf[i]
   343  		}
   344  		if i < len(farFromSelf) {
   345  			srv.peerConnect <- farFromSelf[i]
   346  		}
   347  	}
   348  }
   349  
   350  func (srv *Server) startPeer(conn net.Conn, dest *discover.Node) {
   351  	// TODO: handle/store session token
   352  	conn.SetDeadline(time.Now().Add(handshakeTimeout))
   353  	remoteID, _, err := srv.handshakeFunc(conn, srv.PrivateKey, dest)
   354  	if err != nil {
   355  		conn.Close()
   356  		srvlog.Debugf("Encryption Handshake with %v failed: %v", conn.RemoteAddr(), err)
   357  		return
   358  	}
   359  	ourID := srv.ntab.Self()
   360  	p := newPeer(conn, srv.Protocols, srv.Name, &ourID, &remoteID)
   361  	if ok, reason := srv.addPeer(remoteID, p); !ok {
   362  		srvlog.DebugDetailf("Not adding %v (%v)\n", p, reason)
   363  		p.politeDisconnect(reason)
   364  		return
   365  	}
   366  	srvlog.Debugf("Added %v\n", p)
   367  
   368  	if srv.newPeerHook != nil {
   369  		srv.newPeerHook(p)
   370  	}
   371  	discreason := p.run()
   372  	srv.removePeer(p)
   373  	srvlog.Debugf("Removed %v (%v)\n", p, discreason)
   374  }
   375  
   376  func (srv *Server) addPeer(id discover.NodeID, p *Peer) (bool, DiscReason) {
   377  	srv.lock.Lock()
   378  	defer srv.lock.Unlock()
   379  	switch {
   380  	case !srv.running:
   381  		return false, DiscQuitting
   382  	case len(srv.peers) >= srv.MaxPeers:
   383  		return false, DiscTooManyPeers
   384  	case srv.peers[id] != nil:
   385  		return false, DiscAlreadyConnected
   386  	case srv.Blacklist.Exists(id[:]):
   387  		return false, DiscUselessPeer
   388  	case id == srv.ntab.Self():
   389  		return false, DiscSelf
   390  	}
   391  	srv.peers[id] = p
   392  	return true, 0
   393  }
   394  
   395  func (srv *Server) removePeer(p *Peer) {
   396  	srv.lock.Lock()
   397  	delete(srv.peers, *p.remoteID)
   398  	srv.lock.Unlock()
   399  	srv.peerWG.Done()
   400  }
   401  
   402  type Blacklist interface {
   403  	Get([]byte) (bool, error)
   404  	Put([]byte) error
   405  	Delete([]byte) error
   406  	Exists(pubkey []byte) (ok bool)
   407  }
   408  
   409  type BlacklistMap struct {
   410  	blacklist map[string]bool
   411  	lock      sync.RWMutex
   412  }
   413  
   414  func NewBlacklist() *BlacklistMap {
   415  	return &BlacklistMap{
   416  		blacklist: make(map[string]bool),
   417  	}
   418  }
   419  
   420  func (self *BlacklistMap) Get(pubkey []byte) (bool, error) {
   421  	self.lock.RLock()
   422  	defer self.lock.RUnlock()
   423  	v, ok := self.blacklist[string(pubkey)]
   424  	var err error
   425  	if !ok {
   426  		err = fmt.Errorf("not found")
   427  	}
   428  	return v, err
   429  }
   430  
   431  func (self *BlacklistMap) Exists(pubkey []byte) (ok bool) {
   432  	self.lock.RLock()
   433  	defer self.lock.RUnlock()
   434  	_, ok = self.blacklist[string(pubkey)]
   435  	return
   436  }
   437  
   438  func (self *BlacklistMap) Put(pubkey []byte) error {
   439  	self.lock.Lock()
   440  	defer self.lock.Unlock()
   441  	self.blacklist[string(pubkey)] = true
   442  	return nil
   443  }
   444  
   445  func (self *BlacklistMap) Delete(pubkey []byte) error {
   446  	self.lock.Lock()
   447  	defer self.lock.Unlock()
   448  	delete(self.blacklist, string(pubkey))
   449  	return nil
   450  }