go.dedis.ch/onet/v3@v3.2.11-0.20210930124529-e36530bca7ef/simul/manage/close_all.go (about)

     1  package manage
     2  
     3  import (
     4  	"time"
     5  
     6  	"go.dedis.ch/onet/v3"
     7  	"go.dedis.ch/onet/v3/log"
     8  	"go.dedis.ch/onet/v3/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  }