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 }