go.dedis.ch/onet/v4@v4.0.0-pre1/simul/manage/close_all.go (about) 1 package manage 2 3 import ( 4 "time" 5 6 "go.dedis.ch/onet/v4" 7 "go.dedis.ch/onet/v4/log" 8 "go.dedis.ch/onet/v4/network" 9 "golang.org/x/xerrors" 10 ) 11 12 /* 13 Protocol used to close all connections, starting from the leaf-nodes. 14 It first sends down a message `PrepareClose` through the tree, then 15 from the leaf-nodes a `Close`-message up to the root. Every node receiving 16 the `Close`-message will shut down all network communications. 17 18 The protocol waits for the `Close`-message to arrive at the root. 19 */ 20 21 func init() { 22 network.RegisterMessage(PrepareClose{}) 23 network.RegisterMessage(Close{}) 24 onet.GlobalProtocolRegister("CloseAll", NewCloseAll) 25 } 26 27 // ProtocolCloseAll is the structure used to hold the Done-channel 28 type ProtocolCloseAll struct { 29 *onet.TreeNodeInstance 30 // Done receives a 'true' once the protocol is done. 31 Done chan bool 32 } 33 34 // PrepareClose is sent down the tree until the nodes 35 type PrepareClose struct{} 36 37 // PrepareCloseMsg is the wrapper for the PrepareClose message 38 type PrepareCloseMsg struct { 39 *onet.TreeNode 40 PrepareClose 41 } 42 43 // Close is sent to the parent just before the node shuts down 44 type Close struct{} 45 46 // CloseMsg is the wrapper for the Close message 47 type CloseMsg struct { 48 *onet.TreeNode 49 Close 50 } 51 52 // NewCloseAll will create a new protocol 53 func NewCloseAll(n *onet.TreeNodeInstance) (onet.ProtocolInstance, error) { 54 p := &ProtocolCloseAll{TreeNodeInstance: n} 55 p.Done = make(chan bool, 1) 56 if err := p.RegisterHandler(p.FuncPrepareClose); err != nil { 57 return nil, xerrors.Errorf("registering handler: %v", err) 58 } 59 if err := p.RegisterHandler(p.FuncClose); err != nil { 60 return nil, xerrors.Errorf("registering handler: %v", err) 61 } 62 return p, nil 63 } 64 65 // Start the protocol and waits for the `Close`-message to arrive back at 66 // the root-node. 67 func (p *ProtocolCloseAll) Start() error { 68 // Send an empty message 69 p.FuncPrepareClose(PrepareCloseMsg{TreeNode: p.TreeNode()}) 70 // Wait till the end 71 <-p.Done 72 return nil 73 } 74 75 // FuncPrepareClose sends a `PrepareClose`-message down the tree. 76 func (p *ProtocolCloseAll) FuncPrepareClose(pc PrepareCloseMsg) error { 77 log.Lvl3(pc.ServerIdentity.Address, "sent PrepClose to", p.ServerIdentity().Address) 78 if !p.IsLeaf() { 79 for _, c := range p.Children() { 80 err := p.SendTo(c, &PrepareClose{}) 81 log.Lvl3(p.ServerIdentity().Address, "sends to", c.ServerIdentity.Address, "(err=", err, ")") 82 } 83 } else { 84 p.FuncClose(nil) 85 } 86 return nil 87 } 88 89 // FuncClose is called from the leafs to the parents and up the tree. Everybody 90 // receiving all `Close`-messages from all children will close down all 91 // network communication. 92 func (p *ProtocolCloseAll) FuncClose(c []CloseMsg) error { 93 if !p.IsRoot() { 94 log.Lvl3("Sending closeall from", p.ServerIdentity().Address, 95 "to", p.Parent().ServerIdentity.Address) 96 if err := p.SendTo(p.Parent(), &Close{}); err != nil { 97 log.Error(p.Info(), "couldn't send 'close' tp parent", 98 p.Parent(), err) 99 } 100 } 101 time.Sleep(time.Second) 102 log.Lvl3("Closing host", p.ServerIdentity().Address) 103 err := p.TreeNodeInstance.CloseHost() 104 if err != nil { 105 log.Error("Couldn't close:", err) 106 } 107 if p.IsRoot() { 108 log.Lvl2("Root received Close") 109 p.Done <- true 110 } 111 p.TreeNodeInstance.Done() 112 return nil 113 }