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