mocknet now uses peer.ID

This commit is contained in:
Juan Batiz-Benet 2014-12-19 21:29:12 -08:00
parent b70f40113d
commit fc56ffee00
6 changed files with 96 additions and 141 deletions

View File

@ -19,12 +19,11 @@ type Mocknet interface {
AddPeer(peer.ID) (inet.Network, error)
// retrieve things
Peer(peer.ID) peer.Peer
Peers() []peer.Peer
Peers() []peer.ID
Net(peer.ID) inet.Network
Nets() []inet.Network
Links() LinkMap
LinksBetweenPeers(a, b peer.Peer) []Link
LinksBetweenPeers(a, b peer.ID) []Link
LinksBetweenNets(a, b inet.Network) []Link
// Links are the **ability to connect**.
@ -32,10 +31,10 @@ type Mocknet interface {
// For p1 and p2 to connect, a link must exist between them.
// (this makes it possible to test dial failures, and
// things like relaying traffic)
LinkPeers(peer.Peer, peer.Peer) (Link, error)
LinkPeers(peer.ID, peer.ID) (Link, error)
LinkNets(inet.Network, inet.Network) (Link, error)
Unlink(Link) error
UnlinkPeers(peer.Peer, peer.Peer) error
UnlinkPeers(peer.ID, peer.ID) error
UnlinkNets(inet.Network, inet.Network) error
// LinkDefaults are the default options that govern links
@ -45,9 +44,9 @@ type Mocknet interface {
// Connections are the usual. Connecting means Dialing.
// **to succeed, peers must be linked beforehand**
ConnectPeers(peer.Peer, peer.Peer) error
ConnectPeers(peer.ID, peer.ID) error
ConnectNets(inet.Network, inet.Network) error
DisconnectPeers(peer.Peer, peer.Peer) error
DisconnectPeers(peer.ID, peer.ID) error
DisconnectNets(inet.Network, inet.Network) error
}
@ -66,7 +65,7 @@ type LinkOptions struct {
// nodes cannot talk to each other directly. :)
type Link interface {
Networks() []inet.Network
Peers() []peer.Peer
Peers() []peer.ID
SetOptions(LinkOptions)
Options() LinkOptions

View File

@ -14,8 +14,8 @@ import (
// live connection between two peers.
// it goes over a particular link.
type conn struct {
local peer.Peer
remote peer.Peer
local peer.ID
remote peer.ID
net *peernet
link *link
rconn *conn // counterpart
@ -74,7 +74,7 @@ func (c *conn) openStream() *stream {
return sl
}
func (c *conn) NewStreamWithProtocol(pr inet.ProtocolID, p peer.Peer) (inet.Stream, error) {
func (c *conn) NewStreamWithProtocol(pr inet.ProtocolID, p peer.ID) (inet.Stream, error) {
log.Debugf("Conn.NewStreamWithProtocol: %s --> %s", c.local, p)
s := c.openStream()
@ -91,7 +91,7 @@ func (c *conn) LocalMultiaddr() ma.Multiaddr {
}
// LocalPeer is the Peer on our side of the connection
func (c *conn) LocalPeer() peer.Peer {
func (c *conn) LocalPeer() peer.ID {
return c.local
}
@ -101,6 +101,6 @@ func (c *conn) RemoteMultiaddr() ma.Multiaddr {
}
// RemotePeer is the Peer on the remote side
func (c *conn) RemotePeer() peer.Peer {
func (c *conn) RemotePeer() peer.ID {
return c.remote
}

View File

@ -1,7 +1,6 @@
package mocknet
import (
"fmt"
"io"
"sync"
@ -30,17 +29,12 @@ func (l *link) newConnPair(dialer *peernet) (*conn, *conn) {
mkconn := func(n *peernet, rid peer.ID) *conn {
c := &conn{net: n, link: l}
c.local = n.peer
r, err := n.ps.FindOrCreate(rid)
if err != nil {
panic(fmt.Errorf("error creating peer: %s", err))
}
c.remote = r
c.remote = rid
return c
}
c1 := mkconn(l.nets[0], l.nets[1].peer.ID())
c2 := mkconn(l.nets[1], l.nets[0].peer.ID())
c1 := mkconn(l.nets[0], l.nets[1].peer)
c2 := mkconn(l.nets[1], l.nets[0].peer)
c1.rconn = c2
c2.rconn = c1
@ -70,11 +64,11 @@ func (l *link) Networks() []inet.Network {
return cp
}
func (l *link) Peers() []peer.Peer {
func (l *link) Peers() []peer.ID {
l.RLock()
defer l.RUnlock()
cp := make([]peer.Peer, len(l.nets))
cp := make([]peer.ID, len(l.nets))
for i, n := range l.nets {
cp[i] = n.peer
}

View File

@ -12,19 +12,17 @@ import (
ctxgroup "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
)
type peerID string
// mocknet implements mocknet.Mocknet
type mocknet struct {
// must map on peer.ID (instead of peer.Peer) because
// must map on peer.ID (instead of peer.ID) because
// each inet.Network has different peerstore
nets map[peerID]*peernet
nets map[peer.ID]*peernet
// links make it possible to connect two peers.
// think of links as the physical medium.
// usually only one, but there could be multiple
// **links are shared between peers**
links map[peerID]map[peerID]map[*link]struct{}
links map[peer.ID]map[peer.ID]map[*link]struct{}
linkDefaults LinkOptions
@ -34,28 +32,23 @@ type mocknet struct {
func New(ctx context.Context) Mocknet {
return &mocknet{
nets: map[peerID]*peernet{},
links: map[peerID]map[peerID]map[*link]struct{}{},
nets: map[peer.ID]*peernet{},
links: map[peer.ID]map[peer.ID]map[*link]struct{}{},
cg: ctxgroup.WithContext(ctx),
}
}
func (mn *mocknet) GenPeer() (inet.Network, error) {
p, err := testutil.PeerWithNewKeys()
p, err := testutil.RandPeerID()
if err != nil {
return nil, err
}
n, err := mn.AddPeer(p.ID())
n, err := mn.AddPeer(p)
if err != nil {
return nil, err
}
// copy over keys
if err := n.LocalPeer().Update(p); err != nil {
return nil, err
}
return n, nil
}
@ -68,28 +61,16 @@ func (mn *mocknet) AddPeer(p peer.ID) (inet.Network, error) {
mn.cg.AddChildGroup(n.cg)
mn.Lock()
mn.nets[pid(n.peer)] = n
mn.nets[n.peer] = n
mn.Unlock()
return n, nil
}
func (mn *mocknet) Peer(pid peer.ID) peer.Peer {
func (mn *mocknet) Peers() []peer.ID {
mn.RLock()
defer mn.RUnlock()
for _, n := range mn.nets {
if n.peer.ID().Equal(pid) {
return n.peer
}
}
return nil
}
func (mn *mocknet) Peers() []peer.Peer {
mn.RLock()
defer mn.RUnlock()
cp := make([]peer.Peer, 0, len(mn.nets))
cp := make([]peer.ID, 0, len(mn.nets))
for _, n := range mn.nets {
cp = append(cp, n.peer)
}
@ -101,7 +82,7 @@ func (mn *mocknet) Net(pid peer.ID) inet.Network {
defer mn.RUnlock()
for _, n := range mn.nets {
if n.peer.ID().Equal(pid) {
if n.peer == pid {
return n
}
}
@ -152,10 +133,10 @@ func (mn *mocknet) LinkAll() error {
return nil
}
func (mn *mocknet) LinkPeers(p1, p2 peer.Peer) (Link, error) {
func (mn *mocknet) LinkPeers(p1, p2 peer.ID) (Link, error) {
mn.RLock()
n1 := mn.nets[pid(p1)]
n2 := mn.nets[pid(p2)]
n1 := mn.nets[p1]
n2 := mn.nets[p2]
mn.RUnlock()
if n1 == nil {
@ -177,7 +158,7 @@ func (mn *mocknet) validate(n inet.Network) (*peernet, error) {
return nil, fmt.Errorf("Network not supported (use mock package nets only)")
}
if _, found := mn.nets[pid(nr.peer)]; !found {
if _, found := mn.nets[nr.peer]; !found {
return nil, fmt.Errorf("Network not on mocknet. is it from another mocknet?")
}
@ -215,7 +196,7 @@ func (mn *mocknet) Unlink(l2 Link) error {
return nil
}
func (mn *mocknet) UnlinkPeers(p1, p2 peer.Peer) error {
func (mn *mocknet) UnlinkPeers(p1, p2 peer.ID) error {
ls := mn.LinksBetweenPeers(p1, p2)
if ls == nil {
return fmt.Errorf("no link between p1 and p2")
@ -234,19 +215,19 @@ func (mn *mocknet) UnlinkNets(n1, n2 inet.Network) error {
}
// get from the links map. and lazily contruct.
func (mn *mocknet) linksMapGet(p1, p2 peer.Peer) *map[*link]struct{} {
func (mn *mocknet) linksMapGet(p1, p2 peer.ID) *map[*link]struct{} {
l1, found := mn.links[pid(p1)]
l1, found := mn.links[p1]
if !found {
mn.links[pid(p1)] = map[peerID]map[*link]struct{}{}
l1 = mn.links[pid(p1)] // so we make sure it's there.
mn.links[p1] = map[peer.ID]map[*link]struct{}{}
l1 = mn.links[p1] // so we make sure it's there.
}
l2, found := l1[pid(p2)]
l2, found := l1[p2]
if !found {
m := map[*link]struct{}{}
l1[pid(p2)] = m
l2 = l1[pid(p2)]
l1[p2] = m
l2 = l1[p2]
}
return &l2
@ -286,23 +267,23 @@ func (mn *mocknet) ConnectAll() error {
return nil
}
func (mn *mocknet) ConnectPeers(a, b peer.Peer) error {
return mn.Net(a.ID()).DialPeer(mn.cg.Context(), b)
func (mn *mocknet) ConnectPeers(a, b peer.ID) error {
return mn.Net(a).DialPeer(mn.cg.Context(), b)
}
func (mn *mocknet) ConnectNets(a, b inet.Network) error {
return a.DialPeer(mn.cg.Context(), b.LocalPeer())
}
func (mn *mocknet) DisconnectPeers(p1, p2 peer.Peer) error {
return mn.Net(p1.ID()).ClosePeer(p2)
func (mn *mocknet) DisconnectPeers(p1, p2 peer.ID) error {
return mn.Net(p1).ClosePeer(p2)
}
func (mn *mocknet) DisconnectNets(n1, n2 inet.Network) error {
return n1.ClosePeer(n2.LocalPeer())
}
func (mn *mocknet) LinksBetweenPeers(p1, p2 peer.Peer) []Link {
func (mn *mocknet) LinksBetweenPeers(p1, p2 peer.ID) []Link {
mn.RLock()
defer mn.RUnlock()

View File

@ -17,13 +17,13 @@ import (
type peernet struct {
mocknet *mocknet // parent
peer peer.Peer
peer peer.ID
ps peer.Peerstore
// conns are actual live connections between peers.
// many conns could run over each link.
// **conns are NOT shared between peers**
connsByPeer map[peerID]map[*conn]struct{}
connsByPeer map[peer.ID]map[*conn]struct{}
connsByLink map[*link]map[*conn]struct{}
// needed to implement inet.Network
@ -34,15 +34,10 @@ type peernet struct {
}
// newPeernet constructs a new peernet
func newPeernet(ctx context.Context, m *mocknet, id peer.ID) (*peernet, error) {
func newPeernet(ctx context.Context, m *mocknet, p peer.ID) (*peernet, error) {
// create our own entirely, so that peers dont get shuffled across
// network divides. dont share peers.
// create our own entirely, so that peers knowledge doesn't get shared
ps := peer.NewPeerstore()
p, err := ps.FindOrCreate(id)
if err != nil {
return nil, err
}
n := &peernet{
mocknet: m,
@ -51,7 +46,7 @@ func newPeernet(ctx context.Context, m *mocknet, id peer.ID) (*peernet, error) {
mux: inet.Mux{Handlers: inet.StreamHandlerMap{}},
cg: ctxgroup.WithContext(ctx),
connsByPeer: map[peerID]map[*conn]struct{}{},
connsByPeer: map[peer.ID]map[*conn]struct{}{},
connsByLink: map[*link]map[*conn]struct{}{},
}
@ -97,23 +92,16 @@ func (pn *peernet) handleNewStream(s inet.Stream) {
// DialPeer attempts to establish a connection to a given peer.
// Respects the context.
func (pn *peernet) DialPeer(ctx context.Context, p peer.Peer) error {
func (pn *peernet) DialPeer(ctx context.Context, p peer.ID) error {
return pn.connect(p)
}
func (pn *peernet) connect(p peer.Peer) error {
func (pn *peernet) connect(p peer.ID) error {
log.Debugf("%s dialing %s", pn.peer, p)
// cannot trust the peer we get. typical for tests to give us
// a peer from some other peerstore...
p, err := pn.ps.Add(p)
if err != nil {
return err
}
// first, check if we already have live connections
pn.RLock()
cs, found := pn.connsByPeer[pid(p)]
cs, found := pn.connsByPeer[p]
pn.RUnlock()
if found && len(cs) > 0 {
return nil
@ -136,7 +124,7 @@ func (pn *peernet) connect(p peer.Peer) error {
return nil
}
func (pn *peernet) openConn(r peer.Peer, l *link) *conn {
func (pn *peernet) openConn(r peer.ID, l *link) *conn {
lc, rc := l.newConnPair(pn)
log.Debugf("%s opening connection to %s", pn.LocalPeer(), lc.RemotePeer())
pn.addConn(lc)
@ -153,12 +141,12 @@ func (pn *peernet) remoteOpenedConn(c *conn) {
// to given remote peer over given link
func (pn *peernet) addConn(c *conn) {
pn.Lock()
cs, found := pn.connsByPeer[pid(c.RemotePeer())]
cs, found := pn.connsByPeer[c.RemotePeer()]
if !found {
cs = map[*conn]struct{}{}
pn.connsByPeer[pid(c.RemotePeer())] = cs
pn.connsByPeer[c.RemotePeer()] = cs
}
pn.connsByPeer[pid(c.RemotePeer())][c] = struct{}{}
pn.connsByPeer[c.RemotePeer()][c] = struct{}{}
cs, found = pn.connsByLink[c.link]
if !found {
@ -180,7 +168,7 @@ func (pn *peernet) removeConn(c *conn) {
}
delete(cs, c)
cs, found = pn.connsByPeer[pid(c.remote)]
cs, found = pn.connsByPeer[c.remote]
if !found {
panic("attempting to remove a conn that doesnt exist")
}
@ -193,16 +181,16 @@ func (pn *peernet) CtxGroup() ctxgroup.ContextGroup {
}
// LocalPeer the network's LocalPeer
func (pn *peernet) LocalPeer() peer.Peer {
func (pn *peernet) LocalPeer() peer.ID {
return pn.peer
}
// Peers returns the connected peers
func (pn *peernet) Peers() []peer.Peer {
func (pn *peernet) Peers() []peer.ID {
pn.RLock()
defer pn.RUnlock()
peers := make([]peer.Peer, 0, len(pn.connsByPeer))
peers := make([]peer.ID, 0, len(pn.connsByPeer))
for _, cs := range pn.connsByPeer {
for c := range cs {
peers = append(peers, c.remote)
@ -226,11 +214,11 @@ func (pn *peernet) Conns() []inet.Conn {
return out
}
func (pn *peernet) ConnsToPeer(p peer.Peer) []inet.Conn {
func (pn *peernet) ConnsToPeer(p peer.ID) []inet.Conn {
pn.RLock()
defer pn.RUnlock()
cs, found := pn.connsByPeer[pid(p)]
cs, found := pn.connsByPeer[p]
if !found || len(cs) == 0 {
return nil
}
@ -243,9 +231,9 @@ func (pn *peernet) ConnsToPeer(p peer.Peer) []inet.Conn {
}
// ClosePeer connections to peer
func (pn *peernet) ClosePeer(p peer.Peer) error {
func (pn *peernet) ClosePeer(p peer.ID) error {
pn.RLock()
cs, found := pn.connsByPeer[pid(p)]
cs, found := pn.connsByPeer[p]
pn.RUnlock()
if !found {
return nil
@ -278,11 +266,11 @@ func (pn *peernet) InterfaceListenAddresses() ([]ma.Multiaddr, error) {
// Connectedness returns a state signaling connection capabilities
// For now only returns Connecter || NotConnected. Expand into more later.
func (pn *peernet) Connectedness(p peer.Peer) inet.Connectedness {
func (pn *peernet) Connectedness(p peer.ID) inet.Connectedness {
pn.Lock()
defer pn.Unlock()
cs, found := pn.connsByPeer[pid(p)]
cs, found := pn.connsByPeer[p]
if found && len(cs) > 0 {
return inet.Connected
}
@ -292,11 +280,11 @@ func (pn *peernet) Connectedness(p peer.Peer) inet.Connectedness {
// NewStream returns a new stream to given peer p.
// If there is no connection to p, attempts to create one.
// If ProtocolID is "", writes no header.
func (pn *peernet) NewStream(pr inet.ProtocolID, p peer.Peer) (inet.Stream, error) {
func (pn *peernet) NewStream(pr inet.ProtocolID, p peer.ID) (inet.Stream, error) {
pn.Lock()
defer pn.Unlock()
cs, found := pn.connsByPeer[pid(p)]
cs, found := pn.connsByPeer[p]
if !found || len(cs) < 1 {
return nil, fmt.Errorf("no connection to peer")
}
@ -321,7 +309,3 @@ func (pn *peernet) NewStream(pr inet.ProtocolID, p peer.Peer) (inet.Stream, erro
func (pn *peernet) SetHandler(p inet.ProtocolID, h inet.StreamHandler) {
pn.mux.SetHandler(p, h)
}
func pid(p peer.Peer) peerID {
return peerID(p.ID())
}

View File

@ -14,51 +14,48 @@ import (
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
)
func randPeer(t *testing.T) peer.ID {
p, err := testutil.RandPeerID()
if err != nil {
t.Fatal(err)
}
return p
}
func TestNetworkSetup(t *testing.T) {
ctx := context.Background()
p1 := testutil.RandPeer()
p2 := testutil.RandPeer()
p3 := testutil.RandPeer()
p1 := randPeer(t)
p2 := randPeer(t)
p3 := randPeer(t)
mn := New(ctx)
// peers := []peer.Peer{p1, p2, p3}
// peers := []peer.ID{p1, p2, p3}
// add peers to mock net
n1, err := mn.AddPeer(p1.ID())
n1, err := mn.AddPeer(p1)
if err != nil {
t.Fatal(err)
}
n2, err := mn.AddPeer(p2.ID())
n2, err := mn.AddPeer(p2)
if err != nil {
t.Fatal(err)
}
n3, err := mn.AddPeer(p3.ID())
n3, err := mn.AddPeer(p3)
if err != nil {
t.Fatal(err)
}
// check peers and net
if !mn.Peer(p1.ID()).ID().Equal(p1.ID()) {
t.Error("peer for p1.ID != p1.ID")
}
if !mn.Peer(p2.ID()).ID().Equal(p2.ID()) {
t.Error("peer for p2.ID != p2.ID")
}
if !mn.Peer(p3.ID()).ID().Equal(p3.ID()) {
t.Error("peer for p3.ID != p3.ID")
}
if mn.Net(p1.ID()) != n1 {
if mn.Net(p1) != n1 {
t.Error("net for p1.ID != n1")
}
if mn.Net(p2.ID()) != n2 {
if mn.Net(p2) != n2 {
t.Error("net for p2.ID != n1")
}
if mn.Net(p3.ID()) != n3 {
if mn.Net(p3) != n3 {
t.Error("net for p3.ID != n1")
}
@ -380,13 +377,13 @@ func TestAdding(t *testing.T) {
mn := New(context.Background())
p1 := testutil.RandPeer()
p2 := testutil.RandPeer()
p3 := testutil.RandPeer()
peers := []peer.Peer{p1, p2, p3}
p1 := randPeer(t)
p2 := randPeer(t)
p3 := randPeer(t)
peers := []peer.ID{p1, p2, p3}
for _, p := range peers {
if _, err := mn.AddPeer(p.ID()); err != nil {
if _, err := mn.AddPeer(p); err != nil {
t.Error(err)
}
}
@ -401,9 +398,9 @@ func TestAdding(t *testing.T) {
}
// set the new stream handler on p2
n2 := mn.Net(p2.ID())
n2 := mn.Net(p2)
if n2 == nil {
t.Fatalf("no network for %s", p2.ID())
t.Fatalf("no network for %s", p2)
}
n2.SetHandler(inet.ProtocolBitswap, func(s inet.Stream) {
go func() {
@ -429,9 +426,9 @@ func TestAdding(t *testing.T) {
}
// talk to p2
n1 := mn.Net(p1.ID())
n1 := mn.Net(p1)
if n1 == nil {
t.Fatalf("no network for %s", p1.ID())
t.Fatalf("no network for %s", p1)
}
s, err := n1.NewStream(inet.ProtocolBitswap, p2)