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