github.com/zignig/go-ipfs@v0.0.0-20141111235910-c9e5fdf55a52/exchange/bitswap/testnet/network.go (about)

     1  package bitswap
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  
     8  	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
     9  	bsmsg "github.com/jbenet/go-ipfs/exchange/bitswap/message"
    10  	bsnet "github.com/jbenet/go-ipfs/exchange/bitswap/network"
    11  	peer "github.com/jbenet/go-ipfs/peer"
    12  	"github.com/jbenet/go-ipfs/util"
    13  )
    14  
    15  type Network interface {
    16  	Adapter(peer.Peer) bsnet.Adapter
    17  
    18  	HasPeer(peer.Peer) bool
    19  
    20  	SendMessage(
    21  		ctx context.Context,
    22  		from peer.Peer,
    23  		to peer.Peer,
    24  		message bsmsg.BitSwapMessage) error
    25  
    26  	SendRequest(
    27  		ctx context.Context,
    28  		from peer.Peer,
    29  		to peer.Peer,
    30  		message bsmsg.BitSwapMessage) (
    31  		incoming bsmsg.BitSwapMessage, err error)
    32  }
    33  
    34  // network impl
    35  
    36  func VirtualNetwork() Network {
    37  	return &network{
    38  		clients: make(map[util.Key]bsnet.Receiver),
    39  	}
    40  }
    41  
    42  type network struct {
    43  	clients map[util.Key]bsnet.Receiver
    44  }
    45  
    46  func (n *network) Adapter(p peer.Peer) bsnet.Adapter {
    47  	client := &networkClient{
    48  		local:   p,
    49  		network: n,
    50  	}
    51  	n.clients[p.Key()] = client
    52  	return client
    53  }
    54  
    55  func (n *network) HasPeer(p peer.Peer) bool {
    56  	_, found := n.clients[p.Key()]
    57  	return found
    58  }
    59  
    60  // TODO should this be completely asynchronous?
    61  // TODO what does the network layer do with errors received from services?
    62  func (n *network) SendMessage(
    63  	ctx context.Context,
    64  	from peer.Peer,
    65  	to peer.Peer,
    66  	message bsmsg.BitSwapMessage) error {
    67  
    68  	receiver, ok := n.clients[to.Key()]
    69  	if !ok {
    70  		return errors.New("Cannot locate peer on network")
    71  	}
    72  
    73  	// nb: terminate the context since the context wouldn't actually be passed
    74  	// over the network in a real scenario
    75  
    76  	go n.deliver(receiver, from, message)
    77  
    78  	return nil
    79  }
    80  
    81  func (n *network) deliver(
    82  	r bsnet.Receiver, from peer.Peer, message bsmsg.BitSwapMessage) error {
    83  	if message == nil || from == nil {
    84  		return errors.New("Invalid input")
    85  	}
    86  
    87  	nextPeer, nextMsg := r.ReceiveMessage(context.TODO(), from, message)
    88  
    89  	if (nextPeer == nil && nextMsg != nil) || (nextMsg == nil && nextPeer != nil) {
    90  		return errors.New("Malformed client request")
    91  	}
    92  
    93  	if nextPeer == nil && nextMsg == nil {
    94  		return nil
    95  	}
    96  
    97  	nextReceiver, ok := n.clients[nextPeer.Key()]
    98  	if !ok {
    99  		return errors.New("Cannot locate peer on network")
   100  	}
   101  	go n.deliver(nextReceiver, nextPeer, nextMsg)
   102  	return nil
   103  }
   104  
   105  var NoResponse = errors.New("No response received from the receiver")
   106  
   107  // TODO
   108  func (n *network) SendRequest(
   109  	ctx context.Context,
   110  	from peer.Peer,
   111  	to peer.Peer,
   112  	message bsmsg.BitSwapMessage) (
   113  	incoming bsmsg.BitSwapMessage, err error) {
   114  
   115  	r, ok := n.clients[to.Key()]
   116  	if !ok {
   117  		return nil, errors.New("Cannot locate peer on network")
   118  	}
   119  	nextPeer, nextMsg := r.ReceiveMessage(context.TODO(), from, message)
   120  
   121  	// TODO dedupe code
   122  	if (nextPeer == nil && nextMsg != nil) || (nextMsg == nil && nextPeer != nil) {
   123  		r.ReceiveError(errors.New("Malformed client request"))
   124  		return nil, nil
   125  	}
   126  
   127  	// TODO dedupe code
   128  	if nextPeer == nil && nextMsg == nil {
   129  		return nil, nil
   130  	}
   131  
   132  	// TODO test when receiver doesn't immediately respond to the initiator of the request
   133  	if !bytes.Equal(nextPeer.ID(), from.ID()) {
   134  		go func() {
   135  			nextReceiver, ok := n.clients[nextPeer.Key()]
   136  			if !ok {
   137  				// TODO log the error?
   138  			}
   139  			n.deliver(nextReceiver, nextPeer, nextMsg)
   140  		}()
   141  		return nil, nil
   142  	}
   143  	return nextMsg, nil
   144  }
   145  
   146  type networkClient struct {
   147  	local peer.Peer
   148  	bsnet.Receiver
   149  	network Network
   150  }
   151  
   152  func (nc *networkClient) SendMessage(
   153  	ctx context.Context,
   154  	to peer.Peer,
   155  	message bsmsg.BitSwapMessage) error {
   156  	return nc.network.SendMessage(ctx, nc.local, to, message)
   157  }
   158  
   159  func (nc *networkClient) SendRequest(
   160  	ctx context.Context,
   161  	to peer.Peer,
   162  	message bsmsg.BitSwapMessage) (incoming bsmsg.BitSwapMessage, err error) {
   163  	return nc.network.SendRequest(ctx, nc.local, to, message)
   164  }
   165  
   166  func (nc *networkClient) DialPeer(ctx context.Context, p peer.Peer) error {
   167  	// no need to do anything because dialing isn't a thing in this test net.
   168  	if !nc.network.HasPeer(p) {
   169  		return fmt.Errorf("Peer not in network: %s", p)
   170  	}
   171  	return nil
   172  }
   173  
   174  func (nc *networkClient) SetDelegate(r bsnet.Receiver) {
   175  	nc.Receiver = r
   176  }