github.com/koko1123/flow-go-1@v0.29.6/network/p2p/conduit/conduit.go (about)

     1  package conduit
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/koko1123/flow-go-1/model/flow"
     8  	"github.com/koko1123/flow-go-1/network"
     9  	"github.com/koko1123/flow-go-1/network/channels"
    10  )
    11  
    12  // DefaultConduitFactory is a wrapper around the network Adapter.
    13  // It directly passes the incoming messages to the corresponding methods of the
    14  // network Adapter.
    15  type DefaultConduitFactory struct {
    16  	adapter network.Adapter
    17  }
    18  
    19  func NewDefaultConduitFactory() *DefaultConduitFactory {
    20  	return &DefaultConduitFactory{}
    21  }
    22  
    23  // RegisterAdapter sets the Adapter component of the factory.
    24  // The Adapter is a wrapper around the Network layer that only exposes the set of methods
    25  // that are needed by a conduit.
    26  func (d *DefaultConduitFactory) RegisterAdapter(adapter network.Adapter) error {
    27  	if d.adapter != nil {
    28  		return fmt.Errorf("could not register a new network adapter, one already exists")
    29  	}
    30  
    31  	d.adapter = adapter
    32  
    33  	return nil
    34  }
    35  
    36  // NewConduit creates a conduit on the specified channel.
    37  // Prior to creating any conduit, the factory requires an Adapter to be registered with it.
    38  func (d *DefaultConduitFactory) NewConduit(ctx context.Context, channel channels.Channel) (network.Conduit, error) {
    39  	if d.adapter == nil {
    40  		return nil, fmt.Errorf("could not create a new conduit, missing a registered network adapter")
    41  	}
    42  
    43  	child, cancel := context.WithCancel(ctx)
    44  
    45  	return &Conduit{
    46  		ctx:     child,
    47  		cancel:  cancel,
    48  		channel: channel,
    49  		adapter: d.adapter,
    50  	}, nil
    51  }
    52  
    53  // Conduit is a helper of the overlay layer which functions as an accessor for
    54  // sending messages within a single engine process. It sends all messages to
    55  // what can be considered a bus reserved for that specific engine.
    56  type Conduit struct {
    57  	ctx     context.Context
    58  	cancel  context.CancelFunc
    59  	channel channels.Channel
    60  	adapter network.Adapter
    61  }
    62  
    63  // Publish sends an event to the network layer for unreliable delivery
    64  // to subscribers of the given event on the network layer. It uses a
    65  // publish-subscribe layer and can thus not guarantee that the specified
    66  // recipients received the event.
    67  func (c *Conduit) Publish(event interface{}, targetIDs ...flow.Identifier) error {
    68  	if c.ctx.Err() != nil {
    69  		return fmt.Errorf("conduit for channel %s closed", c.channel)
    70  	}
    71  	return c.adapter.PublishOnChannel(c.channel, event, targetIDs...)
    72  }
    73  
    74  // Unicast sends an event in a reliable way to the given recipient.
    75  // It uses 1-1 direct messaging over the underlying network to deliver the event.
    76  // It returns an error if the unicast fails.
    77  func (c *Conduit) Unicast(event interface{}, targetID flow.Identifier) error {
    78  	if c.ctx.Err() != nil {
    79  		return fmt.Errorf("conduit for channel %s closed", c.channel)
    80  	}
    81  	return c.adapter.UnicastOnChannel(c.channel, event, targetID)
    82  }
    83  
    84  // Multicast unreliably sends the specified event to the specified number of recipients selected from the specified subset.
    85  // The recipients are selected randomly from targetIDs
    86  func (c *Conduit) Multicast(event interface{}, num uint, targetIDs ...flow.Identifier) error {
    87  	if c.ctx.Err() != nil {
    88  		return fmt.Errorf("conduit for channel %s closed", c.channel)
    89  	}
    90  	return c.adapter.MulticastOnChannel(c.channel, event, num, targetIDs...)
    91  }
    92  
    93  func (c *Conduit) Close() error {
    94  	if c.ctx.Err() != nil {
    95  		return fmt.Errorf("conduit for channel %s already closed", c.channel)
    96  	}
    97  	// close the conduit context
    98  	c.cancel()
    99  	// call the close function
   100  	return c.adapter.UnRegisterChannel(c.channel)
   101  }