github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/p2p/server_test.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package p2p 18 19 import ( 20 "crypto/ecdsa" 21 "crypto/sha256" 22 "errors" 23 "io" 24 "io/ioutil" 25 "math/rand" 26 "net" 27 "os" 28 "path" 29 "reflect" 30 "testing" 31 "time" 32 33 "github.com/kisexp/xdchain/crypto" 34 "github.com/kisexp/xdchain/internal/testlog" 35 "github.com/kisexp/xdchain/log" 36 "github.com/kisexp/xdchain/p2p/enode" 37 "github.com/kisexp/xdchain/p2p/enr" 38 "github.com/kisexp/xdchain/p2p/rlpx" 39 "github.com/kisexp/xdchain/params" 40 "github.com/stretchr/testify/assert" 41 ) 42 43 type testTransport struct { 44 *rlpxTransport 45 rpub *ecdsa.PublicKey 46 closeErr error 47 } 48 49 func newTestTransport(rpub *ecdsa.PublicKey, fd net.Conn, dialDest *ecdsa.PublicKey) transport { 50 wrapped := newRLPX(fd, dialDest).(*rlpxTransport) 51 wrapped.conn.InitWithSecrets(rlpx.Secrets{ 52 AES: make([]byte, 16), 53 MAC: make([]byte, 16), 54 EgressMAC: sha256.New(), 55 IngressMAC: sha256.New(), 56 }) 57 return &testTransport{rpub: rpub, rlpxTransport: wrapped} 58 } 59 60 func (c *testTransport) doEncHandshake(prv *ecdsa.PrivateKey) (*ecdsa.PublicKey, error) { 61 return c.rpub, nil 62 } 63 64 func (c *testTransport) doProtoHandshake(our *protoHandshake) (*protoHandshake, error) { 65 pubkey := crypto.FromECDSAPub(c.rpub)[1:] 66 return &protoHandshake{ID: pubkey, Name: "test"}, nil 67 } 68 69 func (c *testTransport) close(err error) { 70 c.conn.Close() 71 c.closeErr = err 72 } 73 74 func startTestServer(t *testing.T, remoteKey *ecdsa.PublicKey, pf func(*Peer)) *Server { 75 config := Config{ 76 Name: "test", 77 MaxPeers: 10, 78 ListenAddr: "127.0.0.1:0", 79 NoDiscovery: true, 80 PrivateKey: newkey(), 81 Logger: testlog.Logger(t, log.LvlTrace), 82 } 83 server := &Server{ 84 Config: config, 85 newPeerHook: pf, 86 newTransport: func(fd net.Conn, dialDest *ecdsa.PublicKey) transport { 87 return newTestTransport(remoteKey, fd, dialDest) 88 }, 89 } 90 if err := server.Start(); err != nil { 91 t.Fatalf("Could not start server: %v", err) 92 } 93 return server 94 } 95 96 func TestServerListen(t *testing.T) { 97 // start the test server 98 connected := make(chan *Peer) 99 remid := &newkey().PublicKey 100 srv := startTestServer(t, remid, func(p *Peer) { 101 if p.ID() != enode.PubkeyToIDV4(remid) { 102 t.Error("peer func called with wrong node id") 103 } 104 connected <- p 105 }) 106 defer close(connected) 107 defer srv.Stop() 108 109 // dial the test server 110 conn, err := net.DialTimeout("tcp", srv.ListenAddr, 5*time.Second) 111 if err != nil { 112 t.Fatalf("could not dial: %v", err) 113 } 114 defer conn.Close() 115 116 select { 117 case peer := <-connected: 118 if peer.LocalAddr().String() != conn.RemoteAddr().String() { 119 t.Errorf("peer started with wrong conn: got %v, want %v", 120 peer.LocalAddr(), conn.RemoteAddr()) 121 } 122 peers := srv.Peers() 123 if !reflect.DeepEqual(peers, []*Peer{peer}) { 124 t.Errorf("Peers mismatch: got %v, want %v", peers, []*Peer{peer}) 125 } 126 case <-time.After(1 * time.Second): 127 t.Error("server did not accept within one second") 128 } 129 } 130 131 func TestServerDial(t *testing.T) { 132 // run a one-shot TCP server to handle the connection. 133 listener, err := net.Listen("tcp", "127.0.0.1:0") 134 if err != nil { 135 t.Fatalf("could not setup listener: %v", err) 136 } 137 defer listener.Close() 138 accepted := make(chan net.Conn, 1) 139 go func() { 140 conn, err := listener.Accept() 141 if err != nil { 142 return 143 } 144 accepted <- conn 145 }() 146 147 // start the server 148 connected := make(chan *Peer) 149 remid := &newkey().PublicKey 150 srv := startTestServer(t, remid, func(p *Peer) { connected <- p }) 151 defer close(connected) 152 defer srv.Stop() 153 154 // tell the server to connect 155 tcpAddr := listener.Addr().(*net.TCPAddr) 156 node := enode.NewV4(remid, tcpAddr.IP, tcpAddr.Port, 0) 157 srv.AddPeer(node) 158 159 select { 160 case conn := <-accepted: 161 defer conn.Close() 162 163 select { 164 case peer := <-connected: 165 if peer.ID() != enode.PubkeyToIDV4(remid) { 166 t.Errorf("peer has wrong id") 167 } 168 if peer.Name() != "test" { 169 t.Errorf("peer has wrong name") 170 } 171 if peer.RemoteAddr().String() != conn.LocalAddr().String() { 172 t.Errorf("peer started with wrong conn: got %v, want %v", 173 peer.RemoteAddr(), conn.LocalAddr()) 174 } 175 peers := srv.Peers() 176 if !reflect.DeepEqual(peers, []*Peer{peer}) { 177 t.Errorf("Peers mismatch: got %v, want %v", peers, []*Peer{peer}) 178 } 179 180 // Test AddTrustedPeer/RemoveTrustedPeer and changing Trusted flags 181 // Particularly for race conditions on changing the flag state. 182 if peer := srv.Peers()[0]; peer.Info().Network.Trusted { 183 t.Errorf("peer is trusted prematurely: %v", peer) 184 } 185 done := make(chan bool) 186 go func() { 187 srv.AddTrustedPeer(node) 188 if peer := srv.Peers()[0]; !peer.Info().Network.Trusted { 189 t.Errorf("peer is not trusted after AddTrustedPeer: %v", peer) 190 } 191 srv.RemoveTrustedPeer(node) 192 if peer := srv.Peers()[0]; peer.Info().Network.Trusted { 193 t.Errorf("peer is trusted after RemoveTrustedPeer: %v", peer) 194 } 195 done <- true 196 }() 197 // Trigger potential race conditions 198 peer = srv.Peers()[0] 199 _ = peer.Inbound() 200 _ = peer.Info() 201 <-done 202 case <-time.After(1 * time.Second): 203 t.Error("server did not launch peer within one second") 204 } 205 206 case <-time.After(1 * time.Second): 207 t.Error("server did not connect within one second") 208 } 209 } 210 211 // This test checks that RemovePeer disconnects the peer if it is connected. 212 func TestServerRemovePeerDisconnect(t *testing.T) { 213 srv1 := &Server{Config: Config{ 214 PrivateKey: newkey(), 215 MaxPeers: 1, 216 NoDiscovery: true, 217 Logger: testlog.Logger(t, log.LvlTrace).New("server", "1"), 218 }} 219 srv2 := &Server{Config: Config{ 220 PrivateKey: newkey(), 221 MaxPeers: 1, 222 NoDiscovery: true, 223 NoDial: true, 224 ListenAddr: "127.0.0.1:0", 225 Logger: testlog.Logger(t, log.LvlTrace).New("server", "2"), 226 }} 227 srv1.Start() 228 defer srv1.Stop() 229 srv2.Start() 230 defer srv2.Stop() 231 232 if !syncAddPeer(srv1, srv2.Self()) { 233 t.Fatal("peer not connected") 234 } 235 srv1.RemovePeer(srv2.Self()) 236 if srv1.PeerCount() > 0 { 237 t.Fatal("removed peer still connected") 238 } 239 } 240 241 // This test checks that connections are disconnected just after the encryption handshake 242 // when the server is at capacity. Trusted connections should still be accepted. 243 func TestServerAtCap(t *testing.T) { 244 trustedNode := newkey() 245 trustedID := enode.PubkeyToIDV4(&trustedNode.PublicKey) 246 srv := &Server{ 247 Config: Config{ 248 PrivateKey: newkey(), 249 MaxPeers: 10, 250 NoDial: true, 251 NoDiscovery: true, 252 TrustedNodes: []*enode.Node{newNode(trustedID, "")}, 253 Logger: testlog.Logger(t, log.LvlTrace), 254 }, 255 } 256 if err := srv.Start(); err != nil { 257 t.Fatalf("could not start: %v", err) 258 } 259 defer srv.Stop() 260 261 newconn := func(id enode.ID) *conn { 262 fd, _ := net.Pipe() 263 tx := newTestTransport(&trustedNode.PublicKey, fd, nil) 264 node := enode.SignNull(new(enr.Record), id) 265 return &conn{fd: fd, transport: tx, flags: inboundConn, node: node, cont: make(chan error)} 266 } 267 268 // Inject a few connections to fill up the peer set. 269 for i := 0; i < 10; i++ { 270 c := newconn(randomID()) 271 if err := srv.checkpoint(c, srv.checkpointAddPeer); err != nil { 272 t.Fatalf("could not add conn %d: %v", i, err) 273 } 274 } 275 // Try inserting a non-trusted connection. 276 anotherID := randomID() 277 c := newconn(anotherID) 278 if err := srv.checkpoint(c, srv.checkpointPostHandshake); err != DiscTooManyPeers { 279 t.Error("wrong error for insert:", err) 280 } 281 // Try inserting a trusted connection. 282 c = newconn(trustedID) 283 if err := srv.checkpoint(c, srv.checkpointPostHandshake); err != nil { 284 t.Error("unexpected error for trusted conn @posthandshake:", err) 285 } 286 if !c.is(trustedConn) { 287 t.Error("Server did not set trusted flag") 288 } 289 290 // Remove from trusted set and try again 291 srv.RemoveTrustedPeer(newNode(trustedID, "")) 292 c = newconn(trustedID) 293 if err := srv.checkpoint(c, srv.checkpointPostHandshake); err != DiscTooManyPeers { 294 t.Error("wrong error for insert:", err) 295 } 296 297 // Add anotherID to trusted set and try again 298 srv.AddTrustedPeer(newNode(anotherID, "")) 299 c = newconn(anotherID) 300 if err := srv.checkpoint(c, srv.checkpointPostHandshake); err != nil { 301 t.Error("unexpected error for trusted conn @posthandshake:", err) 302 } 303 if !c.is(trustedConn) { 304 t.Error("Server did not set trusted flag") 305 } 306 } 307 308 func TestServerPeerLimits(t *testing.T) { 309 srvkey := newkey() 310 clientkey := newkey() 311 clientnode := enode.NewV4(&clientkey.PublicKey, nil, 0, 0) 312 313 var tp = &setupTransport{ 314 pubkey: &clientkey.PublicKey, 315 phs: protoHandshake{ 316 ID: crypto.FromECDSAPub(&clientkey.PublicKey)[1:], 317 // Force "DiscUselessPeer" due to unmatching caps 318 // Caps: []Cap{discard.cap()}, 319 }, 320 } 321 322 srv := &Server{ 323 Config: Config{ 324 PrivateKey: srvkey, 325 MaxPeers: 0, 326 NoDial: true, 327 NoDiscovery: true, 328 Protocols: []Protocol{discard}, 329 Logger: testlog.Logger(t, log.LvlTrace), 330 }, 331 newTransport: func(fd net.Conn, dialDest *ecdsa.PublicKey) transport { return tp }, 332 } 333 if err := srv.Start(); err != nil { 334 t.Fatalf("couldn't start server: %v", err) 335 } 336 defer srv.Stop() 337 338 // Check that server is full (MaxPeers=0) 339 flags := dynDialedConn 340 dialDest := clientnode 341 conn, _ := net.Pipe() 342 srv.SetupConn(conn, flags, dialDest) 343 if tp.closeErr != DiscTooManyPeers { 344 t.Errorf("unexpected close error: %q", tp.closeErr) 345 } 346 conn.Close() 347 348 srv.AddTrustedPeer(clientnode) 349 350 // Check that server allows a trusted peer despite being full. 351 conn, _ = net.Pipe() 352 srv.SetupConn(conn, flags, dialDest) 353 if tp.closeErr == DiscTooManyPeers { 354 t.Errorf("failed to bypass MaxPeers with trusted node: %q", tp.closeErr) 355 } 356 357 if tp.closeErr != DiscUselessPeer { 358 t.Errorf("unexpected close error: %q", tp.closeErr) 359 } 360 conn.Close() 361 362 srv.RemoveTrustedPeer(clientnode) 363 364 // Check that server is full again. 365 conn, _ = net.Pipe() 366 srv.SetupConn(conn, flags, dialDest) 367 if tp.closeErr != DiscTooManyPeers { 368 t.Errorf("unexpected close error: %q", tp.closeErr) 369 } 370 conn.Close() 371 } 372 373 func TestServerSetupConn(t *testing.T) { 374 var ( 375 clientkey, srvkey = newkey(), newkey() 376 clientpub = &clientkey.PublicKey 377 srvpub = &srvkey.PublicKey 378 ) 379 tests := []struct { 380 dontstart bool 381 tt *setupTransport 382 flags connFlag 383 dialDest *enode.Node 384 385 wantCloseErr error 386 wantCalls string 387 }{ 388 { 389 dontstart: true, 390 tt: &setupTransport{pubkey: clientpub}, 391 wantCalls: "close,", 392 wantCloseErr: errServerStopped, 393 }, 394 { 395 tt: &setupTransport{pubkey: clientpub, encHandshakeErr: errors.New("read error")}, 396 flags: inboundConn, 397 wantCalls: "doEncHandshake,close,", 398 wantCloseErr: errors.New("read error"), 399 }, 400 { 401 tt: &setupTransport{pubkey: clientpub, phs: protoHandshake{ID: randomID().Bytes()}}, 402 dialDest: enode.NewV4(clientpub, nil, 0, 0), 403 flags: dynDialedConn, 404 wantCalls: "doEncHandshake,doProtoHandshake,close,", 405 wantCloseErr: DiscUnexpectedIdentity, 406 }, 407 { 408 tt: &setupTransport{pubkey: clientpub, protoHandshakeErr: errors.New("foo")}, 409 dialDest: enode.NewV4(clientpub, nil, 0, 0), 410 flags: dynDialedConn, 411 wantCalls: "doEncHandshake,doProtoHandshake,close,", 412 wantCloseErr: errors.New("foo"), 413 }, 414 { 415 tt: &setupTransport{pubkey: srvpub, phs: protoHandshake{ID: crypto.FromECDSAPub(srvpub)[1:]}}, 416 flags: inboundConn, 417 wantCalls: "doEncHandshake,close,", 418 wantCloseErr: DiscSelf, 419 }, 420 { 421 tt: &setupTransport{pubkey: clientpub, phs: protoHandshake{ID: crypto.FromECDSAPub(clientpub)[1:]}}, 422 flags: inboundConn, 423 wantCalls: "doEncHandshake,doProtoHandshake,close,", 424 wantCloseErr: DiscUselessPeer, 425 }, 426 } 427 428 for i, test := range tests { 429 t.Run(test.wantCalls, func(t *testing.T) { 430 cfg := Config{ 431 PrivateKey: srvkey, 432 MaxPeers: 10, 433 NoDial: true, 434 NoDiscovery: true, 435 Protocols: []Protocol{discard}, 436 Logger: testlog.Logger(t, log.LvlTrace), 437 } 438 srv := &Server{ 439 Config: cfg, 440 newTransport: func(fd net.Conn, dialDest *ecdsa.PublicKey) transport { return test.tt }, 441 log: cfg.Logger, 442 } 443 if !test.dontstart { 444 if err := srv.Start(); err != nil { 445 t.Fatalf("couldn't start server: %v", err) 446 } 447 defer srv.Stop() 448 } 449 p1, _ := net.Pipe() 450 srv.SetupConn(p1, test.flags, test.dialDest) 451 if !reflect.DeepEqual(test.tt.closeErr, test.wantCloseErr) { 452 t.Errorf("test %d: close error mismatch: got %q, want %q", i, test.tt.closeErr, test.wantCloseErr) 453 } 454 if test.tt.calls != test.wantCalls { 455 t.Errorf("test %d: calls mismatch: got %q, want %q", i, test.tt.calls, test.wantCalls) 456 } 457 }) 458 } 459 } 460 461 func TestServerSetupConn_whenNotInRaftCluster(t *testing.T) { 462 var ( 463 clientkey, srvkey = newkey(), newkey() 464 clientpub = &clientkey.PublicKey 465 ) 466 467 clientNode := enode.NewV4(clientpub, nil, 0, 0) 468 srv := &Server{ 469 Config: Config{ 470 PrivateKey: srvkey, 471 NoDiscovery: true, 472 }, 473 newTransport: func(fd net.Conn, key *ecdsa.PublicKey) transport { return newTestTransport(clientpub, fd, key) }, 474 log: log.New(), 475 checkPeerInRaft: func(node *enode.Node) bool { 476 return false 477 }, 478 } 479 if err := srv.Start(); err != nil { 480 t.Fatalf("couldn't start server: %v", err) 481 } 482 defer srv.Stop() 483 p1, _ := net.Pipe() 484 err := srv.SetupConn(p1, inboundConn, clientNode) 485 486 assert.IsType(t, &peerError{}, err) 487 perr := err.(*peerError) 488 t.Log(perr.Error()) 489 assert.Equal(t, errNotInRaftCluster, perr.code) 490 } 491 492 func TestServerSetupConn_whenNotPermissioned(t *testing.T) { 493 tmpDir, err := ioutil.TempDir("", "") 494 if err != nil { 495 t.Fatal(err) 496 } 497 defer func() { _ = os.RemoveAll(tmpDir) }() 498 if err := ioutil.WriteFile(path.Join(tmpDir, params.PERMISSIONED_CONFIG), []byte("[]"), 0644); err != nil { 499 t.Fatal(err) 500 } 501 var ( 502 clientkey, srvkey = newkey(), newkey() 503 clientpub = &clientkey.PublicKey 504 ) 505 clientNode := enode.NewV4(clientpub, nil, 0, 0) 506 srv := &Server{ 507 Config: Config{ 508 PrivateKey: srvkey, 509 NoDiscovery: true, 510 DataDir: tmpDir, 511 EnableNodePermission: true, 512 }, 513 newTransport: func(fd net.Conn, key *ecdsa.PublicKey) transport { return newTestTransport(clientpub, fd, key) }, 514 log: log.New(), 515 } 516 if err := srv.Start(); err != nil { 517 t.Fatalf("couldn't start server: %v", err) 518 } 519 defer srv.Stop() 520 p1, _ := net.Pipe() 521 err = srv.SetupConn(p1, inboundConn, clientNode) 522 523 assert.IsType(t, &peerError{}, err) 524 perr := err.(*peerError) 525 t.Log(perr.Error()) 526 assert.Equal(t, errPermissionDenied, perr.code) 527 } 528 529 type setupTransport struct { 530 pubkey *ecdsa.PublicKey 531 encHandshakeErr error 532 phs protoHandshake 533 protoHandshakeErr error 534 535 calls string 536 closeErr error 537 } 538 539 func (c *setupTransport) doEncHandshake(prv *ecdsa.PrivateKey) (*ecdsa.PublicKey, error) { 540 c.calls += "doEncHandshake," 541 return c.pubkey, c.encHandshakeErr 542 } 543 544 func (c *setupTransport) doProtoHandshake(our *protoHandshake) (*protoHandshake, error) { 545 c.calls += "doProtoHandshake," 546 if c.protoHandshakeErr != nil { 547 return nil, c.protoHandshakeErr 548 } 549 return &c.phs, nil 550 } 551 func (c *setupTransport) close(err error) { 552 c.calls += "close," 553 c.closeErr = err 554 } 555 556 // setupConn shouldn't write to/read from the connection. 557 func (c *setupTransport) WriteMsg(Msg) error { 558 panic("WriteMsg called on setupTransport") 559 } 560 func (c *setupTransport) ReadMsg() (Msg, error) { 561 panic("ReadMsg called on setupTransport") 562 } 563 564 func newkey() *ecdsa.PrivateKey { 565 key, err := crypto.GenerateKey() 566 if err != nil { 567 panic("couldn't generate key: " + err.Error()) 568 } 569 return key 570 } 571 572 func randomID() (id enode.ID) { 573 for i := range id { 574 id[i] = byte(rand.Intn(255)) 575 } 576 return id 577 } 578 579 // This test checks that inbound connections are throttled by IP. 580 func TestServerInboundThrottle(t *testing.T) { 581 const timeout = 5 * time.Second 582 newTransportCalled := make(chan struct{}) 583 srv := &Server{ 584 Config: Config{ 585 PrivateKey: newkey(), 586 ListenAddr: "127.0.0.1:0", 587 MaxPeers: 10, 588 NoDial: true, 589 NoDiscovery: true, 590 Protocols: []Protocol{discard}, 591 Logger: testlog.Logger(t, log.LvlTrace), 592 }, 593 newTransport: func(fd net.Conn, dialDest *ecdsa.PublicKey) transport { 594 newTransportCalled <- struct{}{} 595 return newRLPX(fd, dialDest) 596 }, 597 listenFunc: func(network, laddr string) (net.Listener, error) { 598 fakeAddr := &net.TCPAddr{IP: net.IP{95, 33, 21, 2}, Port: 4444} 599 return listenFakeAddr(network, laddr, fakeAddr) 600 }, 601 } 602 if err := srv.Start(); err != nil { 603 t.Fatal("can't start: ", err) 604 } 605 defer srv.Stop() 606 607 // Dial the test server. 608 conn, err := net.DialTimeout("tcp", srv.ListenAddr, timeout) 609 if err != nil { 610 t.Fatalf("could not dial: %v", err) 611 } 612 select { 613 case <-newTransportCalled: 614 // OK 615 case <-time.After(timeout): 616 t.Error("newTransport not called") 617 } 618 conn.Close() 619 620 // Dial again. This time the server should close the connection immediately. 621 connClosed := make(chan struct{}, 1) 622 conn, err = net.DialTimeout("tcp", srv.ListenAddr, timeout) 623 if err != nil { 624 t.Fatalf("could not dial: %v", err) 625 } 626 defer conn.Close() 627 go func() { 628 conn.SetDeadline(time.Now().Add(timeout)) 629 buf := make([]byte, 10) 630 if n, err := conn.Read(buf); err != io.EOF || n != 0 { 631 t.Errorf("expected io.EOF and n == 0, got error %q and n == %d", err, n) 632 } 633 connClosed <- struct{}{} 634 }() 635 select { 636 case <-connClosed: 637 // OK 638 case <-newTransportCalled: 639 t.Error("newTransport called for second attempt") 640 case <-time.After(timeout): 641 t.Error("connection not closed within timeout") 642 } 643 } 644 645 func listenFakeAddr(network, laddr string, remoteAddr net.Addr) (net.Listener, error) { 646 l, err := net.Listen(network, laddr) 647 if err == nil { 648 l = &fakeAddrListener{l, remoteAddr} 649 } 650 return l, err 651 } 652 653 // fakeAddrListener is a listener that creates connections with a mocked remote address. 654 type fakeAddrListener struct { 655 net.Listener 656 remoteAddr net.Addr 657 } 658 659 type fakeAddrConn struct { 660 net.Conn 661 remoteAddr net.Addr 662 } 663 664 func (l *fakeAddrListener) Accept() (net.Conn, error) { 665 c, err := l.Listener.Accept() 666 if err != nil { 667 return nil, err 668 } 669 return &fakeAddrConn{c, l.remoteAddr}, nil 670 } 671 672 func (c *fakeAddrConn) RemoteAddr() net.Addr { 673 return c.remoteAddr 674 } 675 676 func syncAddPeer(srv *Server, node *enode.Node) bool { 677 var ( 678 ch = make(chan *PeerEvent) 679 sub = srv.SubscribeEvents(ch) 680 timeout = time.After(2 * time.Second) 681 ) 682 defer sub.Unsubscribe() 683 srv.AddPeer(node) 684 for { 685 select { 686 case ev := <-ch: 687 if ev.Type == PeerEventTypeAdd && ev.Peer == node.ID() { 688 return true 689 } 690 case <-timeout: 691 return false 692 } 693 } 694 }