github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/p2p/net/mock/mock_net.go (about)

     1  package mocknet
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"sync"
     7  
     8  	ic "github.com/ipfs/go-ipfs/p2p/crypto"
     9  	host "github.com/ipfs/go-ipfs/p2p/host"
    10  	bhost "github.com/ipfs/go-ipfs/p2p/host/basic"
    11  	inet "github.com/ipfs/go-ipfs/p2p/net"
    12  	peer "github.com/ipfs/go-ipfs/p2p/peer"
    13  	p2putil "github.com/ipfs/go-ipfs/p2p/test/util"
    14  	testutil "github.com/ipfs/go-ipfs/util/testutil"
    15  
    16  	ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
    17  	"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
    18  	goprocessctx "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context"
    19  	context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
    20  )
    21  
    22  // mocknet implements mocknet.Mocknet
    23  type mocknet struct {
    24  	nets  map[peer.ID]*peernet
    25  	hosts map[peer.ID]*bhost.BasicHost
    26  
    27  	// links make it possible to connect two peers.
    28  	// think of links as the physical medium.
    29  	// usually only one, but there could be multiple
    30  	// **links are shared between peers**
    31  	links map[peer.ID]map[peer.ID]map[*link]struct{}
    32  
    33  	linkDefaults LinkOptions
    34  
    35  	proc goprocess.Process // for Context closing
    36  	ctx  context.Context
    37  	sync.RWMutex
    38  }
    39  
    40  func New(ctx context.Context) Mocknet {
    41  	return &mocknet{
    42  		nets:  map[peer.ID]*peernet{},
    43  		hosts: map[peer.ID]*bhost.BasicHost{},
    44  		links: map[peer.ID]map[peer.ID]map[*link]struct{}{},
    45  		proc:  goprocessctx.WithContext(ctx),
    46  		ctx:   ctx,
    47  	}
    48  }
    49  
    50  func (mn *mocknet) GenPeer() (host.Host, error) {
    51  	sk, err := p2putil.RandTestBogusPrivateKey()
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	a := testutil.RandLocalTCPAddress()
    57  
    58  	h, err := mn.AddPeer(sk, a)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  
    63  	return h, nil
    64  }
    65  
    66  func (mn *mocknet) AddPeer(k ic.PrivKey, a ma.Multiaddr) (host.Host, error) {
    67  	p, err := peer.IDFromPublicKey(k.GetPublic())
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	ps := peer.NewPeerstore()
    73  	ps.AddAddr(p, a, peer.PermanentAddrTTL)
    74  	ps.AddPrivKey(p, k)
    75  	ps.AddPubKey(p, k.GetPublic())
    76  
    77  	return mn.AddPeerWithPeerstore(p, ps)
    78  }
    79  
    80  func (mn *mocknet) AddPeerWithPeerstore(p peer.ID, ps peer.Peerstore) (host.Host, error) {
    81  	n, err := newPeernet(mn.ctx, mn, p, ps)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	h := bhost.New(n)
    87  
    88  	mn.proc.AddChild(n.proc)
    89  
    90  	mn.Lock()
    91  	mn.nets[n.peer] = n
    92  	mn.hosts[n.peer] = h
    93  	mn.Unlock()
    94  	return h, nil
    95  }
    96  
    97  func (mn *mocknet) Peers() []peer.ID {
    98  	mn.RLock()
    99  	defer mn.RUnlock()
   100  
   101  	cp := make([]peer.ID, 0, len(mn.nets))
   102  	for _, n := range mn.nets {
   103  		cp = append(cp, n.peer)
   104  	}
   105  	sort.Sort(peer.IDSlice(cp))
   106  	return cp
   107  }
   108  
   109  func (mn *mocknet) Host(pid peer.ID) host.Host {
   110  	mn.RLock()
   111  	host := mn.hosts[pid]
   112  	mn.RUnlock()
   113  	return host
   114  }
   115  
   116  func (mn *mocknet) Net(pid peer.ID) inet.Network {
   117  	mn.RLock()
   118  	n := mn.nets[pid]
   119  	mn.RUnlock()
   120  	return n
   121  }
   122  
   123  func (mn *mocknet) Hosts() []host.Host {
   124  	mn.RLock()
   125  	defer mn.RUnlock()
   126  
   127  	cp := make([]host.Host, 0, len(mn.hosts))
   128  	for _, h := range mn.hosts {
   129  		cp = append(cp, h)
   130  	}
   131  
   132  	sort.Sort(hostSlice(cp))
   133  	return cp
   134  }
   135  
   136  func (mn *mocknet) Nets() []inet.Network {
   137  	mn.RLock()
   138  	defer mn.RUnlock()
   139  
   140  	cp := make([]inet.Network, 0, len(mn.nets))
   141  	for _, n := range mn.nets {
   142  		cp = append(cp, n)
   143  	}
   144  	sort.Sort(netSlice(cp))
   145  	return cp
   146  }
   147  
   148  // Links returns a copy of the internal link state map.
   149  // (wow, much map. so data structure. how compose. ahhh pointer)
   150  func (mn *mocknet) Links() LinkMap {
   151  	mn.RLock()
   152  	defer mn.RUnlock()
   153  
   154  	links := map[string]map[string]map[Link]struct{}{}
   155  	for p1, lm := range mn.links {
   156  		sp1 := string(p1)
   157  		links[sp1] = map[string]map[Link]struct{}{}
   158  		for p2, ls := range lm {
   159  			sp2 := string(p2)
   160  			links[sp1][sp2] = map[Link]struct{}{}
   161  			for l := range ls {
   162  				links[sp1][sp2][l] = struct{}{}
   163  			}
   164  		}
   165  	}
   166  	return links
   167  }
   168  
   169  func (mn *mocknet) LinkAll() error {
   170  	nets := mn.Nets()
   171  	for _, n1 := range nets {
   172  		for _, n2 := range nets {
   173  			if _, err := mn.LinkNets(n1, n2); err != nil {
   174  				return err
   175  			}
   176  		}
   177  	}
   178  	return nil
   179  }
   180  
   181  func (mn *mocknet) LinkPeers(p1, p2 peer.ID) (Link, error) {
   182  	mn.RLock()
   183  	n1 := mn.nets[p1]
   184  	n2 := mn.nets[p2]
   185  	mn.RUnlock()
   186  
   187  	if n1 == nil {
   188  		return nil, fmt.Errorf("network for p1 not in mocknet")
   189  	}
   190  
   191  	if n2 == nil {
   192  		return nil, fmt.Errorf("network for p2 not in mocknet")
   193  	}
   194  
   195  	return mn.LinkNets(n1, n2)
   196  }
   197  
   198  func (mn *mocknet) validate(n inet.Network) (*peernet, error) {
   199  	// WARNING: assumes locks acquired
   200  
   201  	nr, ok := n.(*peernet)
   202  	if !ok {
   203  		return nil, fmt.Errorf("Network not supported (use mock package nets only)")
   204  	}
   205  
   206  	if _, found := mn.nets[nr.peer]; !found {
   207  		return nil, fmt.Errorf("Network not on mocknet. is it from another mocknet?")
   208  	}
   209  
   210  	return nr, nil
   211  }
   212  
   213  func (mn *mocknet) LinkNets(n1, n2 inet.Network) (Link, error) {
   214  	mn.RLock()
   215  	n1r, err1 := mn.validate(n1)
   216  	n2r, err2 := mn.validate(n2)
   217  	ld := mn.linkDefaults
   218  	mn.RUnlock()
   219  
   220  	if err1 != nil {
   221  		return nil, err1
   222  	}
   223  	if err2 != nil {
   224  		return nil, err2
   225  	}
   226  
   227  	l := newLink(mn, ld)
   228  	l.nets = append(l.nets, n1r, n2r)
   229  	mn.addLink(l)
   230  	return l, nil
   231  }
   232  
   233  func (mn *mocknet) Unlink(l2 Link) error {
   234  
   235  	l, ok := l2.(*link)
   236  	if !ok {
   237  		return fmt.Errorf("only links from mocknet are supported")
   238  	}
   239  
   240  	mn.removeLink(l)
   241  	return nil
   242  }
   243  
   244  func (mn *mocknet) UnlinkPeers(p1, p2 peer.ID) error {
   245  	ls := mn.LinksBetweenPeers(p1, p2)
   246  	if ls == nil {
   247  		return fmt.Errorf("no link between p1 and p2")
   248  	}
   249  
   250  	for _, l := range ls {
   251  		if err := mn.Unlink(l); err != nil {
   252  			return err
   253  		}
   254  	}
   255  	return nil
   256  }
   257  
   258  func (mn *mocknet) UnlinkNets(n1, n2 inet.Network) error {
   259  	return mn.UnlinkPeers(n1.LocalPeer(), n2.LocalPeer())
   260  }
   261  
   262  // get from the links map. and lazily contruct.
   263  func (mn *mocknet) linksMapGet(p1, p2 peer.ID) *map[*link]struct{} {
   264  
   265  	l1, found := mn.links[p1]
   266  	if !found {
   267  		mn.links[p1] = map[peer.ID]map[*link]struct{}{}
   268  		l1 = mn.links[p1] // so we make sure it's there.
   269  	}
   270  
   271  	l2, found := l1[p2]
   272  	if !found {
   273  		m := map[*link]struct{}{}
   274  		l1[p2] = m
   275  		l2 = l1[p2]
   276  	}
   277  
   278  	return &l2
   279  }
   280  
   281  func (mn *mocknet) addLink(l *link) {
   282  	mn.Lock()
   283  	defer mn.Unlock()
   284  
   285  	n1, n2 := l.nets[0], l.nets[1]
   286  	(*mn.linksMapGet(n1.peer, n2.peer))[l] = struct{}{}
   287  	(*mn.linksMapGet(n2.peer, n1.peer))[l] = struct{}{}
   288  }
   289  
   290  func (mn *mocknet) removeLink(l *link) {
   291  	mn.Lock()
   292  	defer mn.Unlock()
   293  
   294  	n1, n2 := l.nets[0], l.nets[1]
   295  	delete(*mn.linksMapGet(n1.peer, n2.peer), l)
   296  	delete(*mn.linksMapGet(n2.peer, n1.peer), l)
   297  }
   298  
   299  func (mn *mocknet) ConnectAllButSelf() error {
   300  	nets := mn.Nets()
   301  	for _, n1 := range nets {
   302  		for _, n2 := range nets {
   303  			if n1 == n2 {
   304  				continue
   305  			}
   306  
   307  			if _, err := mn.ConnectNets(n1, n2); err != nil {
   308  				return err
   309  			}
   310  		}
   311  	}
   312  	return nil
   313  }
   314  
   315  func (mn *mocknet) ConnectPeers(a, b peer.ID) (inet.Conn, error) {
   316  	return mn.Net(a).DialPeer(mn.ctx, b)
   317  }
   318  
   319  func (mn *mocknet) ConnectNets(a, b inet.Network) (inet.Conn, error) {
   320  	return a.DialPeer(mn.ctx, b.LocalPeer())
   321  }
   322  
   323  func (mn *mocknet) DisconnectPeers(p1, p2 peer.ID) error {
   324  	return mn.Net(p1).ClosePeer(p2)
   325  }
   326  
   327  func (mn *mocknet) DisconnectNets(n1, n2 inet.Network) error {
   328  	return n1.ClosePeer(n2.LocalPeer())
   329  }
   330  
   331  func (mn *mocknet) LinksBetweenPeers(p1, p2 peer.ID) []Link {
   332  	mn.RLock()
   333  	defer mn.RUnlock()
   334  
   335  	ls2 := *mn.linksMapGet(p1, p2)
   336  	cp := make([]Link, 0, len(ls2))
   337  	for l := range ls2 {
   338  		cp = append(cp, l)
   339  	}
   340  	return cp
   341  }
   342  
   343  func (mn *mocknet) LinksBetweenNets(n1, n2 inet.Network) []Link {
   344  	return mn.LinksBetweenPeers(n1.LocalPeer(), n2.LocalPeer())
   345  }
   346  
   347  func (mn *mocknet) SetLinkDefaults(o LinkOptions) {
   348  	mn.Lock()
   349  	mn.linkDefaults = o
   350  	mn.Unlock()
   351  }
   352  
   353  func (mn *mocknet) LinkDefaults() LinkOptions {
   354  	mn.RLock()
   355  	defer mn.RUnlock()
   356  	return mn.linkDefaults
   357  }
   358  
   359  // netSlice for sorting by peer
   360  type netSlice []inet.Network
   361  
   362  func (es netSlice) Len() int           { return len(es) }
   363  func (es netSlice) Swap(i, j int)      { es[i], es[j] = es[j], es[i] }
   364  func (es netSlice) Less(i, j int) bool { return string(es[i].LocalPeer()) < string(es[j].LocalPeer()) }
   365  
   366  // hostSlice for sorting by peer
   367  type hostSlice []host.Host
   368  
   369  func (es hostSlice) Len() int           { return len(es) }
   370  func (es hostSlice) Swap(i, j int)      { es[i], es[j] = es[j], es[i] }
   371  func (es hostSlice) Less(i, j int) bool { return string(es[i].ID()) < string(es[j].ID()) }