github.com/insight-chain/inb-go@v1.1.3-0.20191221022159-da049980ae38/p2p/simulations/network.go (about) 1 // Copyright 2017 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 simulations 18 19 import ( 20 "bytes" 21 "context" 22 "encoding/json" 23 "errors" 24 "fmt" 25 "sync" 26 "time" 27 28 "github.com/insight-chain/inb-go/event" 29 "github.com/insight-chain/inb-go/log" 30 "github.com/insight-chain/inb-go/p2p" 31 "github.com/insight-chain/inb-go/p2p/enode" 32 "github.com/insight-chain/inb-go/p2p/simulations/adapters" 33 ) 34 35 var DialBanTimeout = 200 * time.Millisecond 36 37 // NetworkConfig defines configuration options for starting a Network 38 type NetworkConfig struct { 39 ID string `json:"id"` 40 DefaultService string `json:"default_service,omitempty"` 41 } 42 43 // Network models a p2p simulation network which consists of a collection of 44 // simulated nodes and the connections which exist between them. 45 // 46 // The Network has a single NodeAdapter which is responsible for actually 47 // starting nodes and connecting them together. 48 // 49 // The Network emits events when nodes are started and stopped, when they are 50 // connected and disconnected, and also when messages are sent between nodes. 51 type Network struct { 52 NetworkConfig 53 54 Nodes []*Node `json:"nodes"` 55 nodeMap map[enode.ID]int 56 57 Conns []*Conn `json:"conns"` 58 connMap map[string]int 59 60 nodeAdapter adapters.NodeAdapter 61 events event.Feed 62 lock sync.RWMutex 63 quitc chan struct{} 64 } 65 66 // NewNetwork returns a Network which uses the given NodeAdapter and NetworkConfig 67 func NewNetwork(nodeAdapter adapters.NodeAdapter, conf *NetworkConfig) *Network { 68 return &Network{ 69 NetworkConfig: *conf, 70 nodeAdapter: nodeAdapter, 71 nodeMap: make(map[enode.ID]int), 72 connMap: make(map[string]int), 73 quitc: make(chan struct{}), 74 } 75 } 76 77 // Events returns the output event feed of the Network. 78 func (net *Network) Events() *event.Feed { 79 return &net.events 80 } 81 82 // NewNodeWithConfig adds a new node to the network with the given config, 83 // returning an error if a node with the same ID or name already exists 84 func (net *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error) { 85 net.lock.Lock() 86 defer net.lock.Unlock() 87 88 if conf.Reachable == nil { 89 conf.Reachable = func(otherID enode.ID) bool { 90 _, err := net.InitConn(conf.ID, otherID) 91 if err != nil && bytes.Compare(conf.ID.Bytes(), otherID.Bytes()) < 0 { 92 return false 93 } 94 return true 95 } 96 } 97 98 // check the node doesn't already exist 99 if node := net.getNode(conf.ID); node != nil { 100 return nil, fmt.Errorf("node with ID %q already exists", conf.ID) 101 } 102 if node := net.getNodeByName(conf.Name); node != nil { 103 return nil, fmt.Errorf("node with name %q already exists", conf.Name) 104 } 105 106 // if no services are configured, use the default service 107 if len(conf.Services) == 0 { 108 conf.Services = []string{net.DefaultService} 109 } 110 111 // use the NodeAdapter to create the node 112 adapterNode, err := net.nodeAdapter.NewNode(conf) 113 if err != nil { 114 return nil, err 115 } 116 node := &Node{ 117 Node: adapterNode, 118 Config: conf, 119 } 120 log.Trace("Node created", "id", conf.ID) 121 net.nodeMap[conf.ID] = len(net.Nodes) 122 net.Nodes = append(net.Nodes, node) 123 124 // emit a "control" event 125 net.events.Send(ControlEvent(node)) 126 127 return node, nil 128 } 129 130 // Config returns the network configuration 131 func (net *Network) Config() *NetworkConfig { 132 return &net.NetworkConfig 133 } 134 135 // StartAll starts all nodes in the network 136 func (net *Network) StartAll() error { 137 for _, node := range net.Nodes { 138 if node.Up { 139 continue 140 } 141 if err := net.Start(node.ID()); err != nil { 142 return err 143 } 144 } 145 return nil 146 } 147 148 // StopAll stops all nodes in the network 149 func (net *Network) StopAll() error { 150 for _, node := range net.Nodes { 151 if !node.Up { 152 continue 153 } 154 if err := net.Stop(node.ID()); err != nil { 155 return err 156 } 157 } 158 return nil 159 } 160 161 // Start starts the node with the given ID 162 func (net *Network) Start(id enode.ID) error { 163 return net.startWithSnapshots(id, nil) 164 } 165 166 // startWithSnapshots starts the node with the given ID using the give 167 // snapshots 168 func (net *Network) startWithSnapshots(id enode.ID, snapshots map[string][]byte) error { 169 net.lock.Lock() 170 defer net.lock.Unlock() 171 172 node := net.getNode(id) 173 if node == nil { 174 return fmt.Errorf("node %v does not exist", id) 175 } 176 if node.Up { 177 return fmt.Errorf("node %v already up", id) 178 } 179 log.Trace("Starting node", "id", id, "adapter", net.nodeAdapter.Name()) 180 if err := node.Start(snapshots); err != nil { 181 log.Warn("Node startup failed", "id", id, "err", err) 182 return err 183 } 184 node.Up = true 185 log.Info("Started node", "id", id) 186 187 net.events.Send(NewEvent(node)) 188 189 // subscribe to peer events 190 client, err := node.Client() 191 if err != nil { 192 return fmt.Errorf("error getting rpc client for node %v: %s", id, err) 193 } 194 events := make(chan *p2p.PeerEvent) 195 sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents") 196 if err != nil { 197 return fmt.Errorf("error getting peer events for node %v: %s", id, err) 198 } 199 go net.watchPeerEvents(id, events, sub) 200 return nil 201 } 202 203 // watchPeerEvents reads peer events from the given channel and emits 204 // corresponding network events 205 func (net *Network) watchPeerEvents(id enode.ID, events chan *p2p.PeerEvent, sub event.Subscription) { 206 defer func() { 207 sub.Unsubscribe() 208 209 // assume the node is now down 210 net.lock.Lock() 211 defer net.lock.Unlock() 212 node := net.getNode(id) 213 if node == nil { 214 return 215 } 216 node.Up = false 217 net.events.Send(NewEvent(node)) 218 }() 219 for { 220 select { 221 case event, ok := <-events: 222 if !ok { 223 return 224 } 225 peer := event.Peer 226 switch event.Type { 227 228 case p2p.PeerEventTypeAdd: 229 net.DidConnect(id, peer) 230 231 case p2p.PeerEventTypeDrop: 232 net.DidDisconnect(id, peer) 233 234 case p2p.PeerEventTypeMsgSend: 235 net.DidSend(id, peer, event.Protocol, *event.MsgCode) 236 237 case p2p.PeerEventTypeMsgRecv: 238 net.DidReceive(peer, id, event.Protocol, *event.MsgCode) 239 240 } 241 242 case err := <-sub.Err(): 243 if err != nil { 244 log.Error("Error in peer event subscription", "id", id, "err", err) 245 } 246 return 247 } 248 } 249 } 250 251 // Stop stops the node with the given ID 252 func (net *Network) Stop(id enode.ID) error { 253 net.lock.Lock() 254 node := net.getNode(id) 255 if node == nil { 256 return fmt.Errorf("node %v does not exist", id) 257 } 258 if !node.Up { 259 return fmt.Errorf("node %v already down", id) 260 } 261 node.Up = false 262 net.lock.Unlock() 263 264 err := node.Stop() 265 if err != nil { 266 net.lock.Lock() 267 node.Up = true 268 net.lock.Unlock() 269 return err 270 } 271 log.Info("Stopped node", "id", id, "err", err) 272 net.events.Send(ControlEvent(node)) 273 return nil 274 } 275 276 // Connect connects two nodes together by calling the "admin_addPeer" RPC 277 // method on the "one" node so that it connects to the "other" node 278 func (net *Network) Connect(oneID, otherID enode.ID) error { 279 log.Debug("Connecting nodes with addPeer", "id", oneID, "other", otherID) 280 conn, err := net.InitConn(oneID, otherID) 281 if err != nil { 282 return err 283 } 284 client, err := conn.one.Client() 285 if err != nil { 286 return err 287 } 288 net.events.Send(ControlEvent(conn)) 289 return client.Call(nil, "admin_addPeer", string(conn.other.Addr())) 290 } 291 292 // Disconnect disconnects two nodes by calling the "admin_removePeer" RPC 293 // method on the "one" node so that it disconnects from the "other" node 294 func (net *Network) Disconnect(oneID, otherID enode.ID) error { 295 conn := net.GetConn(oneID, otherID) 296 if conn == nil { 297 return fmt.Errorf("connection between %v and %v does not exist", oneID, otherID) 298 } 299 if !conn.Up { 300 return fmt.Errorf("%v and %v already disconnected", oneID, otherID) 301 } 302 client, err := conn.one.Client() 303 if err != nil { 304 return err 305 } 306 net.events.Send(ControlEvent(conn)) 307 return client.Call(nil, "admin_removePeer", string(conn.other.Addr())) 308 } 309 310 // DidConnect tracks the fact that the "one" node connected to the "other" node 311 func (net *Network) DidConnect(one, other enode.ID) error { 312 net.lock.Lock() 313 defer net.lock.Unlock() 314 conn, err := net.getOrCreateConn(one, other) 315 if err != nil { 316 return fmt.Errorf("connection between %v and %v does not exist", one, other) 317 } 318 if conn.Up { 319 return fmt.Errorf("%v and %v already connected", one, other) 320 } 321 conn.Up = true 322 net.events.Send(NewEvent(conn)) 323 return nil 324 } 325 326 // DidDisconnect tracks the fact that the "one" node disconnected from the 327 // "other" node 328 func (net *Network) DidDisconnect(one, other enode.ID) error { 329 net.lock.Lock() 330 defer net.lock.Unlock() 331 conn := net.getConn(one, other) 332 if conn == nil { 333 return fmt.Errorf("connection between %v and %v does not exist", one, other) 334 } 335 if !conn.Up { 336 return fmt.Errorf("%v and %v already disconnected", one, other) 337 } 338 conn.Up = false 339 conn.initiated = time.Now().Add(-DialBanTimeout) 340 net.events.Send(NewEvent(conn)) 341 return nil 342 } 343 344 // DidSend tracks the fact that "sender" sent a message to "receiver" 345 func (net *Network) DidSend(sender, receiver enode.ID, proto string, code uint64) error { 346 msg := &Msg{ 347 One: sender, 348 Other: receiver, 349 Protocol: proto, 350 Code: code, 351 Received: false, 352 } 353 net.events.Send(NewEvent(msg)) 354 return nil 355 } 356 357 // DidReceive tracks the fact that "receiver" received a message from "sender" 358 func (net *Network) DidReceive(sender, receiver enode.ID, proto string, code uint64) error { 359 msg := &Msg{ 360 One: sender, 361 Other: receiver, 362 Protocol: proto, 363 Code: code, 364 Received: true, 365 } 366 net.events.Send(NewEvent(msg)) 367 return nil 368 } 369 370 // GetNode gets the node with the given ID, returning nil if the node does not 371 // exist 372 func (net *Network) GetNode(id enode.ID) *Node { 373 net.lock.Lock() 374 defer net.lock.Unlock() 375 return net.getNode(id) 376 } 377 378 // GetNode gets the node with the given name, returning nil if the node does 379 // not exist 380 func (net *Network) GetNodeByName(name string) *Node { 381 net.lock.Lock() 382 defer net.lock.Unlock() 383 return net.getNodeByName(name) 384 } 385 386 // GetNodes returns the existing nodes 387 func (net *Network) GetNodes() (nodes []*Node) { 388 net.lock.Lock() 389 defer net.lock.Unlock() 390 391 nodes = append(nodes, net.Nodes...) 392 return nodes 393 } 394 395 func (net *Network) getNode(id enode.ID) *Node { 396 i, found := net.nodeMap[id] 397 if !found { 398 return nil 399 } 400 return net.Nodes[i] 401 } 402 403 func (net *Network) getNodeByName(name string) *Node { 404 for _, node := range net.Nodes { 405 if node.Config.Name == name { 406 return node 407 } 408 } 409 return nil 410 } 411 412 // GetConn returns the connection which exists between "one" and "other" 413 // regardless of which node initiated the connection 414 func (net *Network) GetConn(oneID, otherID enode.ID) *Conn { 415 net.lock.Lock() 416 defer net.lock.Unlock() 417 return net.getConn(oneID, otherID) 418 } 419 420 // GetOrCreateConn is like GetConn but creates the connection if it doesn't 421 // already exist 422 func (net *Network) GetOrCreateConn(oneID, otherID enode.ID) (*Conn, error) { 423 net.lock.Lock() 424 defer net.lock.Unlock() 425 return net.getOrCreateConn(oneID, otherID) 426 } 427 428 func (net *Network) getOrCreateConn(oneID, otherID enode.ID) (*Conn, error) { 429 if conn := net.getConn(oneID, otherID); conn != nil { 430 return conn, nil 431 } 432 433 one := net.getNode(oneID) 434 if one == nil { 435 return nil, fmt.Errorf("node %v does not exist", oneID) 436 } 437 other := net.getNode(otherID) 438 if other == nil { 439 return nil, fmt.Errorf("node %v does not exist", otherID) 440 } 441 conn := &Conn{ 442 One: oneID, 443 Other: otherID, 444 one: one, 445 other: other, 446 } 447 label := ConnLabel(oneID, otherID) 448 net.connMap[label] = len(net.Conns) 449 net.Conns = append(net.Conns, conn) 450 return conn, nil 451 } 452 453 func (net *Network) getConn(oneID, otherID enode.ID) *Conn { 454 label := ConnLabel(oneID, otherID) 455 i, found := net.connMap[label] 456 if !found { 457 return nil 458 } 459 return net.Conns[i] 460 } 461 462 // InitConn(one, other) retrieves the connectiton model for the connection between 463 // peers one and other, or creates a new one if it does not exist 464 // the order of nodes does not matter, i.e., Conn(i,j) == Conn(j, i) 465 // it checks if the connection is already up, and if the nodes are running 466 // NOTE: 467 // it also checks whether there has been recent attempt to connect the peers 468 // this is cheating as the simulation is used as an oracle and know about 469 // remote peers attempt to connect to a node which will then not initiate the connection 470 func (net *Network) InitConn(oneID, otherID enode.ID) (*Conn, error) { 471 net.lock.Lock() 472 defer net.lock.Unlock() 473 if oneID == otherID { 474 return nil, fmt.Errorf("refusing to connect to self %v", oneID) 475 } 476 conn, err := net.getOrCreateConn(oneID, otherID) 477 if err != nil { 478 return nil, err 479 } 480 if conn.Up { 481 return nil, fmt.Errorf("%v and %v already connected", oneID, otherID) 482 } 483 if time.Since(conn.initiated) < DialBanTimeout { 484 return nil, fmt.Errorf("connection between %v and %v recently attempted", oneID, otherID) 485 } 486 487 err = conn.nodesUp() 488 if err != nil { 489 log.Trace("Nodes not up", "err", err) 490 return nil, fmt.Errorf("nodes not up: %v", err) 491 } 492 log.Debug("Connection initiated", "id", oneID, "other", otherID) 493 conn.initiated = time.Now() 494 return conn, nil 495 } 496 497 // Shutdown stops all nodes in the network and closes the quit channel 498 func (net *Network) Shutdown() { 499 for _, node := range net.Nodes { 500 log.Debug("Stopping node", "id", node.ID()) 501 if err := node.Stop(); err != nil { 502 log.Warn("Can't stop node", "id", node.ID(), "err", err) 503 } 504 } 505 close(net.quitc) 506 } 507 508 //Reset resets all network properties: 509 //emtpies the nodes and the connection list 510 func (net *Network) Reset() { 511 net.lock.Lock() 512 defer net.lock.Unlock() 513 514 //re-initialize the maps 515 net.connMap = make(map[string]int) 516 net.nodeMap = make(map[enode.ID]int) 517 518 net.Nodes = nil 519 net.Conns = nil 520 } 521 522 // Node is a wrapper around adapters.Node which is used to track the status 523 // of a node in the network 524 type Node struct { 525 adapters.Node `json:"-"` 526 527 // Config if the config used to created the node 528 Config *adapters.NodeConfig `json:"config"` 529 530 // Up tracks whether or not the node is running 531 Up bool `json:"up"` 532 } 533 534 // ID returns the ID of the node 535 func (n *Node) ID() enode.ID { 536 return n.Config.ID 537 } 538 539 // String returns a log-friendly string 540 func (n *Node) String() string { 541 return fmt.Sprintf("Node %v", n.ID().TerminalString()) 542 } 543 544 // NodeInfo returns information about the node 545 func (n *Node) NodeInfo() *p2p.NodeInfo { 546 // avoid a panic if the node is not started yet 547 if n.Node == nil { 548 return nil 549 } 550 info := n.Node.NodeInfo() 551 info.Name = n.Config.Name 552 return info 553 } 554 555 // MarshalJSON implements the json.Marshaler interface so that the encoded 556 // JSON includes the NodeInfo 557 func (n *Node) MarshalJSON() ([]byte, error) { 558 return json.Marshal(struct { 559 Info *p2p.NodeInfo `json:"info,omitempty"` 560 Config *adapters.NodeConfig `json:"config,omitempty"` 561 Up bool `json:"up"` 562 }{ 563 Info: n.NodeInfo(), 564 Config: n.Config, 565 Up: n.Up, 566 }) 567 } 568 569 // Conn represents a connection between two nodes in the network 570 type Conn struct { 571 // One is the node which initiated the connection 572 One enode.ID `json:"one"` 573 574 // Other is the node which the connection was made to 575 Other enode.ID `json:"other"` 576 577 // Up tracks whether or not the connection is active 578 Up bool `json:"up"` 579 // Registers when the connection was grabbed to dial 580 initiated time.Time 581 582 one *Node 583 other *Node 584 } 585 586 // nodesUp returns whether both nodes are currently up 587 func (c *Conn) nodesUp() error { 588 if !c.one.Up { 589 return fmt.Errorf("one %v is not up", c.One) 590 } 591 if !c.other.Up { 592 return fmt.Errorf("other %v is not up", c.Other) 593 } 594 return nil 595 } 596 597 // String returns a log-friendly string 598 func (c *Conn) String() string { 599 return fmt.Sprintf("Conn %v->%v", c.One.TerminalString(), c.Other.TerminalString()) 600 } 601 602 // Msg represents a p2p message sent between two nodes in the network 603 type Msg struct { 604 One enode.ID `json:"one"` 605 Other enode.ID `json:"other"` 606 Protocol string `json:"protocol"` 607 Code uint64 `json:"code"` 608 Received bool `json:"received"` 609 } 610 611 // String returns a log-friendly string 612 func (m *Msg) String() string { 613 return fmt.Sprintf("Msg(%d) %v->%v", m.Code, m.One.TerminalString(), m.Other.TerminalString()) 614 } 615 616 // ConnLabel generates a deterministic string which represents a connection 617 // between two nodes, used to compare if two connections are between the same 618 // nodes 619 func ConnLabel(source, target enode.ID) string { 620 var first, second enode.ID 621 if bytes.Compare(source.Bytes(), target.Bytes()) > 0 { 622 first = target 623 second = source 624 } else { 625 first = source 626 second = target 627 } 628 return fmt.Sprintf("%v-%v", first, second) 629 } 630 631 // Snapshot represents the state of a network at a single point in time and can 632 // be used to restore the state of a network 633 type Snapshot struct { 634 Nodes []NodeSnapshot `json:"nodes,omitempty"` 635 Conns []Conn `json:"conns,omitempty"` 636 } 637 638 // NodeSnapshot represents the state of a node in the network 639 type NodeSnapshot struct { 640 Node Node `json:"node,omitempty"` 641 642 // Snapshots is arbitrary data gathered from calling node.Snapshots() 643 Snapshots map[string][]byte `json:"snapshots,omitempty"` 644 } 645 646 // Snapshot creates a network snapshot 647 func (net *Network) Snapshot() (*Snapshot, error) { 648 return net.snapshot(nil, nil) 649 } 650 651 func (net *Network) SnapshotWithServices(addServices []string, removeServices []string) (*Snapshot, error) { 652 return net.snapshot(addServices, removeServices) 653 } 654 655 func (net *Network) snapshot(addServices []string, removeServices []string) (*Snapshot, error) { 656 net.lock.Lock() 657 defer net.lock.Unlock() 658 snap := &Snapshot{ 659 Nodes: make([]NodeSnapshot, len(net.Nodes)), 660 } 661 for i, node := range net.Nodes { 662 snap.Nodes[i] = NodeSnapshot{Node: *node} 663 if !node.Up { 664 continue 665 } 666 snapshots, err := node.Snapshots() 667 if err != nil { 668 return nil, err 669 } 670 snap.Nodes[i].Snapshots = snapshots 671 for _, addSvc := range addServices { 672 haveSvc := false 673 for _, svc := range snap.Nodes[i].Node.Config.Services { 674 if svc == addSvc { 675 haveSvc = true 676 break 677 } 678 } 679 if !haveSvc { 680 snap.Nodes[i].Node.Config.Services = append(snap.Nodes[i].Node.Config.Services, addSvc) 681 } 682 } 683 if len(removeServices) > 0 { 684 var cleanedServices []string 685 for _, svc := range snap.Nodes[i].Node.Config.Services { 686 haveSvc := false 687 for _, rmSvc := range removeServices { 688 if rmSvc == svc { 689 haveSvc = true 690 break 691 } 692 } 693 if !haveSvc { 694 cleanedServices = append(cleanedServices, svc) 695 } 696 697 } 698 snap.Nodes[i].Node.Config.Services = cleanedServices 699 } 700 } 701 for _, conn := range net.Conns { 702 if conn.Up { 703 snap.Conns = append(snap.Conns, *conn) 704 } 705 } 706 return snap, nil 707 } 708 709 var snapshotLoadTimeout = 120 * time.Second 710 711 // Load loads a network snapshot 712 func (net *Network) Load(snap *Snapshot) error { 713 // Start nodes. 714 for _, n := range snap.Nodes { 715 if _, err := net.NewNodeWithConfig(n.Node.Config); err != nil { 716 return err 717 } 718 if !n.Node.Up { 719 continue 720 } 721 if err := net.startWithSnapshots(n.Node.Config.ID, n.Snapshots); err != nil { 722 return err 723 } 724 } 725 726 // Prepare connection events counter. 727 allConnected := make(chan struct{}) // closed when all connections are established 728 done := make(chan struct{}) // ensures that the event loop goroutine is terminated 729 defer close(done) 730 731 // Subscribe to event channel. 732 // It needs to be done outside of the event loop goroutine (created below) 733 // to ensure that the event channel is blocking before connect calls are made. 734 events := make(chan *Event) 735 sub := net.Events().Subscribe(events) 736 defer sub.Unsubscribe() 737 738 go func() { 739 // Expected number of connections. 740 total := len(snap.Conns) 741 // Set of all established connections from the snapshot, not other connections. 742 // Key array element 0 is the connection One field value, and element 1 connection Other field. 743 connections := make(map[[2]enode.ID]struct{}, total) 744 745 for { 746 select { 747 case e := <-events: 748 // Ignore control events as they do not represent 749 // connect or disconnect (Up) state change. 750 if e.Control { 751 continue 752 } 753 // Detect only connection events. 754 if e.Type != EventTypeConn { 755 continue 756 } 757 connection := [2]enode.ID{e.Conn.One, e.Conn.Other} 758 // Nodes are still not connected or have been disconnected. 759 if !e.Conn.Up { 760 // Delete the connection from the set of established connections. 761 // This will prevent false positive in case disconnections happen. 762 delete(connections, connection) 763 log.Warn("load snapshot: unexpected disconnection", "one", e.Conn.One, "other", e.Conn.Other) 764 continue 765 } 766 // Check that the connection is from the snapshot. 767 for _, conn := range snap.Conns { 768 if conn.One == e.Conn.One && conn.Other == e.Conn.Other { 769 // Add the connection to the set of established connections. 770 connections[connection] = struct{}{} 771 if len(connections) == total { 772 // Signal that all nodes are connected. 773 close(allConnected) 774 return 775 } 776 777 break 778 } 779 } 780 case <-done: 781 // Load function returned, terminate this goroutine. 782 return 783 } 784 } 785 }() 786 787 // Start connecting. 788 for _, conn := range snap.Conns { 789 790 if !net.GetNode(conn.One).Up || !net.GetNode(conn.Other).Up { 791 //in this case, at least one of the nodes of a connection is not up, 792 //so it would result in the snapshot `Load` to fail 793 continue 794 } 795 if err := net.Connect(conn.One, conn.Other); err != nil { 796 return err 797 } 798 } 799 800 select { 801 // Wait until all connections from the snapshot are established. 802 case <-allConnected: 803 // Make sure that we do not wait forever. 804 case <-time.After(snapshotLoadTimeout): 805 return errors.New("snapshot connections not established") 806 } 807 return nil 808 } 809 810 // Subscribe reads control events from a channel and executes them 811 func (net *Network) Subscribe(events chan *Event) { 812 for { 813 select { 814 case event, ok := <-events: 815 if !ok { 816 return 817 } 818 if event.Control { 819 net.executeControlEvent(event) 820 } 821 case <-net.quitc: 822 return 823 } 824 } 825 } 826 827 func (net *Network) executeControlEvent(event *Event) { 828 log.Trace("Executing control event", "type", event.Type, "event", event) 829 switch event.Type { 830 case EventTypeNode: 831 if err := net.executeNodeEvent(event); err != nil { 832 log.Error("Error executing node event", "event", event, "err", err) 833 } 834 case EventTypeConn: 835 if err := net.executeConnEvent(event); err != nil { 836 log.Error("Error executing conn event", "event", event, "err", err) 837 } 838 case EventTypeMsg: 839 log.Warn("Ignoring control msg event") 840 } 841 } 842 843 func (net *Network) executeNodeEvent(e *Event) error { 844 if !e.Node.Up { 845 return net.Stop(e.Node.ID()) 846 } 847 848 if _, err := net.NewNodeWithConfig(e.Node.Config); err != nil { 849 return err 850 } 851 return net.Start(e.Node.ID()) 852 } 853 854 func (net *Network) executeConnEvent(e *Event) error { 855 if e.Conn.Up { 856 return net.Connect(e.Conn.One, e.Conn.Other) 857 } else { 858 return net.Disconnect(e.Conn.One, e.Conn.Other) 859 } 860 }