From 0f3ffb2d075d9e0138d3150c39379faf8fbae482 Mon Sep 17 00:00:00 2001 From: Jeromy Date: Tue, 4 Oct 2016 12:33:25 -0700 Subject: [PATCH] extract conn, addr-util, and testutil --- examples/hosts/main.go | 6 +- p2p/net/conn/conn.go | 145 ------- p2p/net/conn/conn_test.go | 138 ------ p2p/net/conn/dial.go | 219 ---------- p2p/net/conn/dial_test.go | 649 ---------------------------- p2p/net/conn/interface.go | 99 ----- p2p/net/conn/listen.go | 235 ---------- p2p/net/conn/secure_conn.go | 124 ------ p2p/net/conn/secure_conn_test.go | 211 --------- p2p/net/interface.go | 2 +- p2p/net/mock/mock_net.go | 4 +- p2p/net/mock/mock_test.go | 8 +- p2p/net/swarm/addr/addr.go | 284 ------------ p2p/net/swarm/addr/addr_test.go | 227 ---------- p2p/net/swarm/addr/filter.go | 31 -- p2p/net/swarm/dial_test.go | 9 +- p2p/net/swarm/limiter.go | 5 +- p2p/net/swarm/limiter_test.go | 3 +- p2p/net/swarm/simul_test.go | 5 +- p2p/net/swarm/swarm.go | 4 +- p2p/net/swarm/swarm_addr.go | 5 +- p2p/net/swarm/swarm_addr_test.go | 6 +- p2p/net/swarm/swarm_conn.go | 4 +- p2p/net/swarm/swarm_dial.go | 4 +- p2p/net/swarm/swarm_listen.go | 7 +- p2p/net/swarm/swarm_test.go | 4 +- p2p/test/util/key.go | 2 +- p2p/test/util/util.go | 6 +- package.json | 18 + testutil/ci/ci.go | 52 --- testutil/ci/jenkins/jenkins.go | 58 --- testutil/ci/jenkins/jenkins_test.go | 16 - testutil/ci/travis/travis.go | 57 --- testutil/ci/travis/travis_test.go | 13 - testutil/gen.go | 156 ------- testutil/identity.go | 55 --- testutil/latency_config.go | 48 -- testutil/rand.go | 36 -- 38 files changed, 58 insertions(+), 2897 deletions(-) delete mode 100644 p2p/net/conn/conn.go delete mode 100644 p2p/net/conn/conn_test.go delete mode 100644 p2p/net/conn/dial.go delete mode 100644 p2p/net/conn/dial_test.go delete mode 100644 p2p/net/conn/interface.go delete mode 100644 p2p/net/conn/listen.go delete mode 100644 p2p/net/conn/secure_conn.go delete mode 100644 p2p/net/conn/secure_conn_test.go delete mode 100644 p2p/net/swarm/addr/addr.go delete mode 100644 p2p/net/swarm/addr/addr_test.go delete mode 100644 p2p/net/swarm/addr/filter.go delete mode 100644 testutil/ci/ci.go delete mode 100644 testutil/ci/jenkins/jenkins.go delete mode 100644 testutil/ci/jenkins/jenkins_test.go delete mode 100644 testutil/ci/travis/travis.go delete mode 100644 testutil/ci/travis/travis_test.go delete mode 100644 testutil/gen.go delete mode 100644 testutil/identity.go delete mode 100644 testutil/latency_config.go delete mode 100644 testutil/rand.go diff --git a/examples/hosts/main.go b/examples/hosts/main.go index 1edeb4a834..e73191b4e9 100644 --- a/examples/hosts/main.go +++ b/examples/hosts/main.go @@ -8,16 +8,16 @@ import ( "log" "strings" - peer "github.com/ipfs/go-libp2p-peer" - pstore "github.com/ipfs/go-libp2p-peerstore" host "github.com/libp2p/go-libp2p/p2p/host" bhost "github.com/libp2p/go-libp2p/p2p/host/basic" inet "github.com/libp2p/go-libp2p/p2p/net" net "github.com/libp2p/go-libp2p/p2p/net" swarm "github.com/libp2p/go-libp2p/p2p/net/swarm" - testutil "github.com/libp2p/go-libp2p/testutil" + peer "github.com/ipfs/go-libp2p-peer" + pstore "github.com/ipfs/go-libp2p-peerstore" ma "github.com/jbenet/go-multiaddr" + testutil "github.com/libp2p/go-testutil" ) // create a 'Host' with a random peer to listen on the given address diff --git a/p2p/net/conn/conn.go b/p2p/net/conn/conn.go deleted file mode 100644 index 8ed7991cd5..0000000000 --- a/p2p/net/conn/conn.go +++ /dev/null @@ -1,145 +0,0 @@ -package conn - -import ( - "context" - "fmt" - "io" - "net" - "time" - - u "github.com/ipfs/go-ipfs-util" - ic "github.com/ipfs/go-libp2p-crypto" - lgbl "github.com/ipfs/go-libp2p-loggables" - peer "github.com/ipfs/go-libp2p-peer" - logging "github.com/ipfs/go-log" - mpool "github.com/jbenet/go-msgio/mpool" - ma "github.com/jbenet/go-multiaddr" - manet "github.com/jbenet/go-multiaddr-net" -) - -var log = logging.Logger("conn") - -// ReleaseBuffer puts the given byte array back into the buffer pool, -// first verifying that it is the correct size -func ReleaseBuffer(b []byte) { - log.Debugf("Releasing buffer! (cap,size = %d, %d)", cap(b), len(b)) - mpool.ByteSlicePool.Put(uint32(cap(b)), b) -} - -// singleConn represents a single connection to another Peer (IPFS Node). -type singleConn struct { - local peer.ID - remote peer.ID - maconn manet.Conn - event io.Closer -} - -// newConn constructs a new connection -func newSingleConn(ctx context.Context, local, remote peer.ID, maconn manet.Conn) (Conn, error) { - ml := lgbl.Dial("conn", local, remote, maconn.LocalMultiaddr(), maconn.RemoteMultiaddr()) - - conn := &singleConn{ - local: local, - remote: remote, - maconn: maconn, - event: log.EventBegin(ctx, "connLifetime", ml), - } - - log.Debugf("newSingleConn %p: %v to %v", conn, local, remote) - return conn, nil -} - -// close is the internal close function, called by ContextCloser.Close -func (c *singleConn) Close() error { - defer func() { - if c.event != nil { - c.event.Close() - c.event = nil - } - }() - - // close underlying connection - return c.maconn.Close() -} - -// ID is an identifier unique to this connection. -func (c *singleConn) ID() string { - return ID(c) -} - -func (c *singleConn) String() string { - return String(c, "singleConn") -} - -func (c *singleConn) LocalAddr() net.Addr { - return c.maconn.LocalAddr() -} - -func (c *singleConn) RemoteAddr() net.Addr { - return c.maconn.RemoteAddr() -} - -func (c *singleConn) LocalPrivateKey() ic.PrivKey { - return nil -} - -func (c *singleConn) RemotePublicKey() ic.PubKey { - return nil -} - -func (c *singleConn) SetDeadline(t time.Time) error { - return c.maconn.SetDeadline(t) -} -func (c *singleConn) SetReadDeadline(t time.Time) error { - return c.maconn.SetReadDeadline(t) -} - -func (c *singleConn) SetWriteDeadline(t time.Time) error { - return c.maconn.SetWriteDeadline(t) -} - -// LocalMultiaddr is the Multiaddr on this side -func (c *singleConn) LocalMultiaddr() ma.Multiaddr { - return c.maconn.LocalMultiaddr() -} - -// RemoteMultiaddr is the Multiaddr on the remote side -func (c *singleConn) RemoteMultiaddr() ma.Multiaddr { - return c.maconn.RemoteMultiaddr() -} - -// LocalPeer is the Peer on this side -func (c *singleConn) LocalPeer() peer.ID { - return c.local -} - -// RemotePeer is the Peer on the remote side -func (c *singleConn) RemotePeer() peer.ID { - return c.remote -} - -// Read reads data, net.Conn style -func (c *singleConn) Read(buf []byte) (int, error) { - return c.maconn.Read(buf) -} - -// Write writes data, net.Conn style -func (c *singleConn) Write(buf []byte) (int, error) { - return c.maconn.Write(buf) -} - -// ID returns the ID of a given Conn. -func ID(c Conn) string { - l := fmt.Sprintf("%s/%s", c.LocalMultiaddr(), c.LocalPeer().Pretty()) - r := fmt.Sprintf("%s/%s", c.RemoteMultiaddr(), c.RemotePeer().Pretty()) - lh := u.Hash([]byte(l)) - rh := u.Hash([]byte(r)) - ch := u.XOR(lh, rh) - return peer.ID(ch).Pretty() -} - -// String returns the user-friendly String representation of a conn -func String(c Conn, typ string) string { - return fmt.Sprintf("%s (%s) <-- %s %p --> (%s) %s", - c.LocalPeer(), c.LocalMultiaddr(), typ, c, c.RemoteMultiaddr(), c.RemotePeer()) -} diff --git a/p2p/net/conn/conn_test.go b/p2p/net/conn/conn_test.go deleted file mode 100644 index 3d1f9752f5..0000000000 --- a/p2p/net/conn/conn_test.go +++ /dev/null @@ -1,138 +0,0 @@ -package conn - -import ( - "bytes" - "fmt" - "runtime" - "sync" - "testing" - "time" - - "context" - msgio "github.com/jbenet/go-msgio" - travis "github.com/libp2p/go-libp2p/testutil/ci/travis" -) - -func msgioWrap(c Conn) msgio.ReadWriter { - return msgio.NewReadWriter(c) -} - -func testOneSendRecv(t *testing.T, c1, c2 Conn) { - mc1 := msgioWrap(c1) - mc2 := msgioWrap(c2) - - log.Debugf("testOneSendRecv from %s to %s", c1.LocalPeer(), c2.LocalPeer()) - m1 := []byte("hello") - if err := mc1.WriteMsg(m1); err != nil { - t.Fatal(err) - } - m2, err := mc2.ReadMsg() - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(m1, m2) { - t.Fatal("failed to send: %s %s", m1, m2) - } -} - -func testNotOneSendRecv(t *testing.T, c1, c2 Conn) { - mc1 := msgioWrap(c1) - mc2 := msgioWrap(c2) - - m1 := []byte("hello") - if err := mc1.WriteMsg(m1); err == nil { - t.Fatal("write should have failed", err) - } - _, err := mc2.ReadMsg() - if err == nil { - t.Fatal("read should have failed", err) - } -} - -func TestClose(t *testing.T) { - // t.Skip("Skipping in favor of another test") - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - c1, c2, _, _ := setupSingleConn(t, ctx) - - testOneSendRecv(t, c1, c2) - testOneSendRecv(t, c2, c1) - - c1.Close() - testNotOneSendRecv(t, c1, c2) - - c2.Close() - testNotOneSendRecv(t, c2, c1) - testNotOneSendRecv(t, c1, c2) -} - -func TestCloseLeak(t *testing.T) { - // t.Skip("Skipping in favor of another test") - if testing.Short() { - t.SkipNow() - } - - if travis.IsRunning() { - t.Skip("this doesn't work well on travis") - } - - var wg sync.WaitGroup - - runPair := func(num int) { - ctx, cancel := context.WithCancel(context.Background()) - c1, c2, _, _ := setupSingleConn(t, ctx) - - mc1 := msgioWrap(c1) - mc2 := msgioWrap(c2) - - for i := 0; i < num; i++ { - b1 := []byte(fmt.Sprintf("beep%d", i)) - mc1.WriteMsg(b1) - b2, err := mc2.ReadMsg() - if err != nil { - panic(err) - } - if !bytes.Equal(b1, b2) { - panic(fmt.Errorf("bytes not equal: %s != %s", b1, b2)) - } - - b2 = []byte(fmt.Sprintf("boop%d", i)) - mc2.WriteMsg(b2) - b1, err = mc1.ReadMsg() - if err != nil { - panic(err) - } - if !bytes.Equal(b1, b2) { - panic(fmt.Errorf("bytes not equal: %s != %s", b1, b2)) - } - - <-time.After(time.Microsecond * 5) - } - - c1.Close() - c2.Close() - cancel() // close the listener - wg.Done() - } - - var cons = 5 - var msgs = 50 - log.Debugf("Running %d connections * %d msgs.\n", cons, msgs) - for i := 0; i < cons; i++ { - wg.Add(1) - go runPair(msgs) - } - - log.Debugf("Waiting...\n") - wg.Wait() - // done! - - time.Sleep(time.Millisecond * 150) - ngr := runtime.NumGoroutine() - if ngr > 25 { - // note, this is really innacurate - //panic("uncomment me to debug") - t.Fatal("leaking goroutines:", ngr) - } -} diff --git a/p2p/net/conn/dial.go b/p2p/net/conn/dial.go deleted file mode 100644 index cae9fa216d..0000000000 --- a/p2p/net/conn/dial.go +++ /dev/null @@ -1,219 +0,0 @@ -package conn - -import ( - "fmt" - "math/rand" - "strings" - "time" - - "context" - ci "github.com/ipfs/go-libp2p-crypto" - lgbl "github.com/ipfs/go-libp2p-loggables" - peer "github.com/ipfs/go-libp2p-peer" - ma "github.com/jbenet/go-multiaddr" - manet "github.com/jbenet/go-multiaddr-net" - transport "github.com/libp2p/go-libp2p-transport" - addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr" - msmux "github.com/whyrusleeping/go-multistream" -) - -type WrapFunc func(transport.Conn) transport.Conn - -func NewDialer(p peer.ID, pk ci.PrivKey, wrap WrapFunc) *Dialer { - return &Dialer{ - LocalPeer: p, - PrivateKey: pk, - Wrapper: wrap, - fallback: new(transport.FallbackDialer), - } -} - -// String returns the string rep of d. -func (d *Dialer) String() string { - return fmt.Sprintf("", d.LocalPeer) -} - -// Dial connects to a peer over a particular address -// Ensures raddr is part of peer.Addresses() -// Example: d.DialAddr(ctx, peer.Addresses()[0], peer) -func (d *Dialer) Dial(ctx context.Context, raddr ma.Multiaddr, remote peer.ID) (Conn, error) { - logdial := lgbl.Dial("conn", d.LocalPeer, remote, nil, raddr) - logdial["encrypted"] = (d.PrivateKey != nil) // log wether this will be an encrypted dial or not. - defer log.EventBegin(ctx, "connDial", logdial).Done() - - var connOut Conn - var errOut error - done := make(chan struct{}) - - // do it async to ensure we respect don contexteone - go func() { - defer func() { - select { - case done <- struct{}{}: - case <-ctx.Done(): - } - }() - - maconn, err := d.rawConnDial(ctx, raddr, remote) - if err != nil { - errOut = err - return - } - - if d.Wrapper != nil { - maconn = d.Wrapper(maconn) - } - - cryptoProtoChoice := SecioTag - if !EncryptConnections || d.PrivateKey == nil { - cryptoProtoChoice = NoEncryptionTag - } - - maconn.SetReadDeadline(time.Now().Add(NegotiateReadTimeout)) - - err = msmux.SelectProtoOrFail(cryptoProtoChoice, maconn) - if err != nil { - errOut = err - return - } - - maconn.SetReadDeadline(time.Time{}) - - c, err := newSingleConn(ctx, d.LocalPeer, remote, maconn) - if err != nil { - maconn.Close() - errOut = err - return - } - - if d.PrivateKey == nil || !EncryptConnections { - log.Warning("dialer %s dialing INSECURELY %s at %s!", d, remote, raddr) - connOut = c - return - } - - c2, err := newSecureConn(ctx, d.PrivateKey, c) - if err != nil { - errOut = err - c.Close() - return - } - - connOut = c2 - }() - - select { - case <-ctx.Done(): - logdial["error"] = ctx.Err() - logdial["dial"] = "failure" - return nil, ctx.Err() - case <-done: - // whew, finished. - } - - if errOut != nil { - logdial["error"] = errOut - logdial["dial"] = "failure" - return nil, errOut - } - - logdial["dial"] = "success" - return connOut, nil -} - -func (d *Dialer) AddDialer(pd transport.Dialer) { - d.Dialers = append(d.Dialers, pd) -} - -// returns dialer that can dial the given address -func (d *Dialer) subDialerForAddr(raddr ma.Multiaddr) transport.Dialer { - for _, pd := range d.Dialers { - if pd.Matches(raddr) { - return pd - } - } - - if d.fallback.Matches(raddr) { - return d.fallback - } - - return nil -} - -// rawConnDial dials the underlying net.Conn + manet.Conns -func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote peer.ID) (transport.Conn, error) { - if strings.HasPrefix(raddr.String(), "/ip4/0.0.0.0") { - log.Event(ctx, "connDialZeroAddr", lgbl.Dial("conn", d.LocalPeer, remote, nil, raddr)) - return nil, fmt.Errorf("Attempted to connect to zero address: %s", raddr) - } - - sd := d.subDialerForAddr(raddr) - if sd == nil { - return nil, fmt.Errorf("no dialer for %s", raddr) - } - - return sd.DialContext(ctx, raddr) -} - -func pickLocalAddr(laddrs []ma.Multiaddr, raddr ma.Multiaddr) (laddr ma.Multiaddr) { - if len(laddrs) < 1 { - return nil - } - - // make sure that we ONLY use local addrs that match the remote addr. - laddrs = manet.AddrMatch(raddr, laddrs) - if len(laddrs) < 1 { - return nil - } - - // make sure that we ONLY use local addrs that CAN dial the remote addr. - // filter out all the local addrs that aren't capable - raddrIPLayer := ma.Split(raddr)[0] - raddrIsLoopback := manet.IsIPLoopback(raddrIPLayer) - raddrIsLinkLocal := manet.IsIP6LinkLocal(raddrIPLayer) - laddrs = addrutil.FilterAddrs(laddrs, func(a ma.Multiaddr) bool { - laddrIPLayer := ma.Split(a)[0] - laddrIsLoopback := manet.IsIPLoopback(laddrIPLayer) - laddrIsLinkLocal := manet.IsIP6LinkLocal(laddrIPLayer) - if laddrIsLoopback { // our loopback addrs can only dial loopbacks. - return raddrIsLoopback - } - if laddrIsLinkLocal { - return raddrIsLinkLocal // out linklocal addrs can only dial link locals. - } - return true - }) - - // TODO pick with a good heuristic - // we use a random one for now to prevent bad addresses from making nodes unreachable - // with a random selection, multiple tries may work. - return laddrs[rand.Intn(len(laddrs))] -} - -// MultiaddrProtocolsMatch returns whether two multiaddrs match in protocol stacks. -func MultiaddrProtocolsMatch(a, b ma.Multiaddr) bool { - ap := a.Protocols() - bp := b.Protocols() - - if len(ap) != len(bp) { - return false - } - - for i, api := range ap { - if api.Code != bp[i].Code { - return false - } - } - - return true -} - -// MultiaddrNetMatch returns the first Multiaddr found to match network. -func MultiaddrNetMatch(tgt ma.Multiaddr, srcs []ma.Multiaddr) ma.Multiaddr { - for _, a := range srcs { - if MultiaddrProtocolsMatch(tgt, a) { - return a - } - } - return nil -} diff --git a/p2p/net/conn/dial_test.go b/p2p/net/conn/dial_test.go deleted file mode 100644 index 970fbc7e07..0000000000 --- a/p2p/net/conn/dial_test.go +++ /dev/null @@ -1,649 +0,0 @@ -package conn - -import ( - "bytes" - "fmt" - "io" - "net" - "runtime" - "strings" - "sync" - "testing" - "time" - - ic "github.com/ipfs/go-libp2p-crypto" - peer "github.com/ipfs/go-libp2p-peer" - transport "github.com/libp2p/go-libp2p-transport" - tu "github.com/libp2p/go-libp2p/testutil" - tcpt "github.com/libp2p/go-tcp-transport" - - "context" - ma "github.com/jbenet/go-multiaddr" - msmux "github.com/whyrusleeping/go-multistream" - grc "github.com/whyrusleeping/gorocheck" -) - -func goroFilter(r *grc.Goroutine) bool { - return strings.Contains(r.Function, "go-log.") || strings.Contains(r.Stack[0], "testing.(*T).Run") -} - -func echoListen(ctx context.Context, listener Listener) { - for { - c, err := listener.Accept() - if err != nil { - - select { - case <-ctx.Done(): - return - default: - } - - if ne, ok := err.(net.Error); ok && ne.Temporary() { - <-time.After(time.Microsecond * 10) - continue - } - - log.Debugf("echoListen: listener appears to be closing") - return - } - - go echo(c.(Conn)) - } -} - -func echo(c Conn) { - io.Copy(c, c) -} - -func setupSecureConn(t *testing.T, ctx context.Context) (a, b Conn, p1, p2 tu.PeerNetParams) { - return setupConn(t, ctx, true) -} - -func setupSingleConn(t *testing.T, ctx context.Context) (a, b Conn, p1, p2 tu.PeerNetParams) { - return setupConn(t, ctx, false) -} - -func Listen(ctx context.Context, addr ma.Multiaddr, local peer.ID, sk ic.PrivKey) (Listener, error) { - list, err := tcpt.NewTCPTransport().Listen(addr) - if err != nil { - return nil, err - } - - return WrapTransportListener(ctx, list, local, sk) -} - -func dialer(t *testing.T, a ma.Multiaddr) transport.Dialer { - tpt := tcpt.NewTCPTransport() - tptd, err := tpt.Dialer(a) - if err != nil { - t.Fatal(err) - } - - return tptd -} - -func setupConn(t *testing.T, ctx context.Context, secure bool) (a, b Conn, p1, p2 tu.PeerNetParams) { - - p1 = tu.RandPeerNetParamsOrFatal(t) - p2 = tu.RandPeerNetParamsOrFatal(t) - - key1 := p1.PrivKey - key2 := p2.PrivKey - if !secure { - key1 = nil - key2 = nil - } - l1, err := Listen(ctx, p1.Addr, p1.ID, key1) - if err != nil { - t.Fatal(err) - } - p1.Addr = l1.Multiaddr() // Addr has been determined by kernel. - - d2 := &Dialer{ - LocalPeer: p2.ID, - PrivateKey: key2, - } - - d2.AddDialer(dialer(t, p2.Addr)) - - var c2 Conn - - done := make(chan error) - go func() { - defer close(done) - - var err error - c2, err = d2.Dial(ctx, p1.Addr, p1.ID) - if err != nil { - done <- err - return - } - - // if secure, need to read + write, as that's what triggers the handshake. - if secure { - if err := sayHello(c2); err != nil { - done <- err - } - } - }() - - c1, err := l1.Accept() - if err != nil { - t.Fatal("failed to accept", err) - } - - // if secure, need to read + write, as that's what triggers the handshake. - if secure { - if err := sayHello(c1); err != nil { - done <- err - } - } - - if err := <-done; err != nil { - t.Fatal(err) - } - - return c1.(Conn), c2, p1, p2 -} - -func sayHello(c net.Conn) error { - h := []byte("hello") - if _, err := c.Write(h); err != nil { - return err - } - if _, err := c.Read(h); err != nil { - return err - } - if string(h) != "hello" { - return fmt.Errorf("did not get hello") - } - return nil -} - -func testDialer(t *testing.T, secure bool) { - // t.Skip("Skipping in favor of another test") - - p1 := tu.RandPeerNetParamsOrFatal(t) - p2 := tu.RandPeerNetParamsOrFatal(t) - - key1 := p1.PrivKey - key2 := p2.PrivKey - if !secure { - key1 = nil - key2 = nil - t.Log("testing insecurely") - } else { - t.Log("testing securely") - } - - ctx, cancel := context.WithCancel(context.Background()) - l1, err := Listen(ctx, p1.Addr, p1.ID, key1) - if err != nil { - t.Fatal(err) - } - p1.Addr = l1.Multiaddr() // Addr has been determined by kernel. - - d2 := &Dialer{ - LocalPeer: p2.ID, - PrivateKey: key2, - } - d2.AddDialer(dialer(t, p2.Addr)) - - go echoListen(ctx, l1) - - c, err := d2.Dial(ctx, p1.Addr, p1.ID) - if err != nil { - t.Fatal("error dialing peer", err) - } - - // fmt.Println("sending") - mc := msgioWrap(c) - mc.WriteMsg([]byte("beep")) - mc.WriteMsg([]byte("boop")) - out, err := mc.ReadMsg() - if err != nil { - t.Fatal(err) - } - - // fmt.Println("recving", string(out)) - data := string(out) - if data != "beep" { - t.Error("unexpected conn output", data) - } - - out, err = mc.ReadMsg() - if err != nil { - t.Fatal(err) - } - - data = string(out) - if string(out) != "boop" { - t.Error("unexpected conn output", data) - } - - // fmt.Println("closing") - c.Close() - l1.Close() - cancel() -} - -func TestDialerInsecure(t *testing.T) { - // t.Skip("Skipping in favor of another test") - testDialer(t, false) -} - -func TestDialerSecure(t *testing.T) { - // t.Skip("Skipping in favor of another test") - testDialer(t, true) -} - -func testDialerCloseEarly(t *testing.T, secure bool) { - // t.Skip("Skipping in favor of another test") - - p1 := tu.RandPeerNetParamsOrFatal(t) - p2 := tu.RandPeerNetParamsOrFatal(t) - - key1 := p1.PrivKey - if !secure { - key1 = nil - t.Log("testing insecurely") - } else { - t.Log("testing securely") - } - - ctx, cancel := context.WithCancel(context.Background()) - l1, err := Listen(ctx, p1.Addr, p1.ID, key1) - if err != nil { - t.Fatal(err) - } - p1.Addr = l1.Multiaddr() // Addr has been determined by kernel. - - // lol nesting - d2 := &Dialer{ - LocalPeer: p2.ID, - PrivateKey: p2.PrivKey, //-- dont give it key. we'll just close the conn. - } - d2.AddDialer(dialer(t, p2.Addr)) - - errs := make(chan error, 100) - done := make(chan struct{}, 1) - gotclosed := make(chan struct{}, 1) - go func() { - defer func() { done <- struct{}{} }() - - c, err := l1.Accept() - if err != nil { - if strings.Contains(err.Error(), "closed") { - gotclosed <- struct{}{} - return - } - errs <- err - } - - if _, err := c.Write([]byte("hello")); err != nil { - gotclosed <- struct{}{} - return - } - - errs <- fmt.Errorf("wrote to conn") - }() - - c, err := d2.Dial(ctx, p1.Addr, p1.ID) - if err != nil { - t.Fatal(err) - } - c.Close() // close it early. - - readerrs := func() { - for { - select { - case e := <-errs: - t.Error(e) - default: - return - } - } - } - readerrs() - - l1.Close() - <-done - cancel() - readerrs() - close(errs) - - select { - case <-gotclosed: - default: - t.Error("did not get closed") - } -} - -// we dont do a handshake with singleConn, so cant "close early." -// func TestDialerCloseEarlyInsecure(t *testing.T) { -// // t.Skip("Skipping in favor of another test") -// testDialerCloseEarly(t, false) -// } - -func TestDialerCloseEarlySecure(t *testing.T) { - // t.Skip("Skipping in favor of another test") - testDialerCloseEarly(t, true) -} - -func TestMultistreamHeader(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - p1 := tu.RandPeerNetParamsOrFatal(t) - - l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey) - if err != nil { - t.Fatal(err) - } - - p1.Addr = l1.Multiaddr() // Addr has been determined by kernel. - - go func() { - _, _ = l1.Accept() - }() - - con, err := net.Dial("tcp", l1.Addr().String()) - if err != nil { - t.Fatal(err) - } - defer con.Close() - - err = msmux.SelectProtoOrFail(SecioTag, con) - if err != nil { - t.Fatal(err) - } -} - -func TestFailedAccept(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - p1 := tu.RandPeerNetParamsOrFatal(t) - - l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey) - if err != nil { - t.Fatal(err) - } - - p1.Addr = l1.Multiaddr() // Addr has been determined by kernel. - - done := make(chan struct{}) - go func() { - defer close(done) - con, err := net.Dial("tcp", l1.Addr().String()) - if err != nil { - t.Error("first dial failed: ", err) - } - - // write some garbage - con.Write(bytes.Repeat([]byte{255}, 1000)) - - con.Close() - - con, err = net.Dial("tcp", l1.Addr().String()) - if err != nil { - t.Error("second dial failed: ", err) - } - defer con.Close() - - err = msmux.SelectProtoOrFail(SecioTag, con) - if err != nil { - t.Error("msmux select failed: ", err) - } - }() - - c, err := l1.Accept() - if err != nil { - t.Fatal("connections after a failed accept should still work: ", err) - } - - c.Close() - <-done -} - -func TestHangingAccept(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - p1 := tu.RandPeerNetParamsOrFatal(t) - - l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey) - if err != nil { - t.Fatal(err) - } - - p1.Addr = l1.Multiaddr() // Addr has been determined by kernel. - - done := make(chan struct{}) - go func() { - defer close(done) - con, err := net.Dial("tcp", l1.Addr().String()) - if err != nil { - t.Error("first dial failed: ", err) - } - // hang this connection - defer con.Close() - - // ensure that the first conn hits first - time.Sleep(time.Millisecond * 50) - - con2, err := net.Dial("tcp", l1.Addr().String()) - if err != nil { - t.Error("second dial failed: ", err) - } - defer con2.Close() - - err = msmux.SelectProtoOrFail(SecioTag, con2) - if err != nil { - t.Error("msmux select failed: ", err) - } - - _, err = con2.Write([]byte("test")) - if err != nil { - t.Error("con write failed: ", err) - } - }() - - c, err := l1.Accept() - if err != nil { - t.Fatal("connections after a failed accept should still work: ", err) - } - - c.Close() - <-done -} - -// This test kicks off N (=300) concurrent dials, which wait d (=20ms) seconds before failing. -// That wait holds up the handshake (multistream AND crypto), which will happen BEFORE -// l1.Accept() returns a connection. This test checks that the handshakes all happen -// concurrently in the listener side, and not sequentially. This ensures that a hanging dial -// will not block the listener from accepting other dials concurrently. -func TestConcurrentAccept(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - p1 := tu.RandPeerNetParamsOrFatal(t) - - l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey) - if err != nil { - t.Fatal(err) - } - - n := 300 - delay := time.Millisecond * 20 - if runtime.GOOS == "darwin" { - n = 100 - } - - p1.Addr = l1.Multiaddr() // Addr has been determined by kernel. - - var wg sync.WaitGroup - for i := 0; i < n; i++ { - wg.Add(1) - go func() { - defer wg.Done() - con, err := net.Dial("tcp", l1.Addr().String()) - if err != nil { - log.Error(err) - t.Error("first dial failed: ", err) - return - } - // hang this connection - defer con.Close() - - time.Sleep(delay) - err = msmux.SelectProtoOrFail(SecioTag, con) - if err != nil { - t.Error(err) - } - }() - } - - before := time.Now() - for i := 0; i < n; i++ { - c, err := l1.Accept() - if err != nil { - t.Fatal("connections after a failed accept should still work: ", err) - } - - c.Close() - } - - limit := delay * time.Duration(n) - took := time.Since(before) - if took > limit { - t.Fatal("took too long!") - } - log.Errorf("took: %s (less than %s)", took, limit) - l1.Close() - wg.Wait() - cancel() - - time.Sleep(time.Millisecond * 100) - - err = grc.CheckForLeaks(goroFilter) - if err != nil { - t.Fatal(err) - } -} - -func TestConnectionTimeouts(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - old := NegotiateReadTimeout - NegotiateReadTimeout = time.Second * 5 - defer func() { NegotiateReadTimeout = old }() - - p1 := tu.RandPeerNetParamsOrFatal(t) - - l1, err := Listen(ctx, p1.Addr, p1.ID, p1.PrivKey) - if err != nil { - t.Fatal(err) - } - - n := 100 - if runtime.GOOS == "darwin" { - n = 50 - } - - p1.Addr = l1.Multiaddr() // Addr has been determined by kernel. - - var wg sync.WaitGroup - for i := 0; i < n; i++ { - wg.Add(1) - go func() { - defer wg.Done() - con, err := net.Dial("tcp", l1.Addr().String()) - if err != nil { - log.Error(err) - t.Error("first dial failed: ", err) - return - } - defer con.Close() - - // hang this connection until timeout - io.ReadFull(con, make([]byte, 1000)) - }() - } - - // wait to make sure the hanging dials have started - time.Sleep(time.Millisecond * 50) - - good_n := 20 - for i := 0; i < good_n; i++ { - wg.Add(1) - go func() { - defer wg.Done() - con, err := net.Dial("tcp", l1.Addr().String()) - if err != nil { - log.Error(err) - t.Error("first dial failed: ", err) - return - } - defer con.Close() - - // dial these ones through - err = msmux.SelectProtoOrFail(SecioTag, con) - if err != nil { - t.Error(err) - } - }() - } - - before := time.Now() - for i := 0; i < good_n; i++ { - c, err := l1.Accept() - if err != nil { - t.Fatal("connections during hung dials should still work: ", err) - } - - c.Close() - } - - took := time.Since(before) - - if took > time.Second*5 { - t.Fatal("hanging dials shouldnt block good dials") - } - - wg.Wait() - - go func() { - con, err := net.Dial("tcp", l1.Addr().String()) - if err != nil { - log.Error(err) - t.Error("first dial failed: ", err) - return - } - defer con.Close() - - // dial these ones through - err = msmux.SelectProtoOrFail(SecioTag, con) - if err != nil { - t.Error(err) - } - }() - - // make sure we can dial in still after a bunch of timeouts - con, err := l1.Accept() - if err != nil { - t.Fatal(err) - } - - con.Close() - l1.Close() - cancel() - - time.Sleep(time.Millisecond * 100) - - err = grc.CheckForLeaks(goroFilter) - if err != nil { - t.Fatal(err) - } -} diff --git a/p2p/net/conn/interface.go b/p2p/net/conn/interface.go deleted file mode 100644 index cc49606bb6..0000000000 --- a/p2p/net/conn/interface.go +++ /dev/null @@ -1,99 +0,0 @@ -package conn - -import ( - "io" - "net" - "time" - - ic "github.com/ipfs/go-libp2p-crypto" - peer "github.com/ipfs/go-libp2p-peer" - ma "github.com/jbenet/go-multiaddr" - transport "github.com/libp2p/go-libp2p-transport" - filter "github.com/libp2p/go-maddr-filter" -) - -type PeerConn interface { - io.Closer - - // LocalPeer (this side) ID, PrivateKey, and Address - LocalPeer() peer.ID - LocalPrivateKey() ic.PrivKey - LocalMultiaddr() ma.Multiaddr - - // RemotePeer ID, PublicKey, and Address - RemotePeer() peer.ID - RemotePublicKey() ic.PubKey - RemoteMultiaddr() ma.Multiaddr -} - -// Conn is a generic message-based Peer-to-Peer connection. -type Conn interface { - PeerConn - - // ID is an identifier unique to this connection. - ID() string - - // can't just say "net.Conn" cause we have duplicate methods. - LocalAddr() net.Addr - RemoteAddr() net.Addr - SetDeadline(t time.Time) error - SetReadDeadline(t time.Time) error - SetWriteDeadline(t time.Time) error - - io.Reader - io.Writer -} - -// Dialer is an object that can open connections. We could have a "convenience" -// Dial function as before, but it would have many arguments, as dialing is -// no longer simple (need a peerstore, a local peer, a context, a network, etc) -type Dialer struct { - // LocalPeer is the identity of the local Peer. - LocalPeer peer.ID - - // LocalAddrs is a set of local addresses to use. - //LocalAddrs []ma.Multiaddr - - // Dialers are the sub-dialers usable by this dialer - // selected in order based on the address being dialed - Dialers []transport.Dialer - - // PrivateKey used to initialize a secure connection. - // Warning: if PrivateKey is nil, connection will not be secured. - PrivateKey ic.PrivKey - - // Wrapper to wrap the raw connection (optional) - Wrapper WrapFunc - - fallback transport.Dialer -} - -// Listener is an object that can accept connections. It matches net.Listener -type Listener interface { - - // Accept waits for and returns the next connection to the listener. - Accept() (net.Conn, error) - - // Addr is the local address - Addr() net.Addr - - // Multiaddr is the local multiaddr address - Multiaddr() ma.Multiaddr - - // LocalPeer is the identity of the local Peer. - LocalPeer() peer.ID - - SetAddrFilters(*filter.Filters) - - // Close closes the listener. - // Any blocked Accept operations will be unblocked and return errors. - Close() error -} - -// EncryptConnections is a global parameter because it should either be -// enabled or _completely disabled_. I.e. a node should only be able to talk -// to proper (encrypted) networks if it is encrypting all its transports. -// Running a node with disabled transport encryption is useful to debug the -// protocols, achieve implementation interop, or for private networks which -// -- for whatever reason -- _must_ run unencrypted. -var EncryptConnections = true diff --git a/p2p/net/conn/listen.go b/p2p/net/conn/listen.go deleted file mode 100644 index 6098ff79c7..0000000000 --- a/p2p/net/conn/listen.go +++ /dev/null @@ -1,235 +0,0 @@ -package conn - -import ( - "context" - "fmt" - "io" - "net" - "sync" - "time" - - ic "github.com/ipfs/go-libp2p-crypto" - peer "github.com/ipfs/go-libp2p-peer" - ma "github.com/jbenet/go-multiaddr" - tec "github.com/jbenet/go-temp-err-catcher" - "github.com/jbenet/goprocess" - goprocessctx "github.com/jbenet/goprocess/context" - transport "github.com/libp2p/go-libp2p-transport" - filter "github.com/libp2p/go-maddr-filter" - msmux "github.com/whyrusleeping/go-multistream" -) - -const ( - SecioTag = "/secio/1.0.0" - NoEncryptionTag = "/plaintext/1.0.0" -) - -var ( - connAcceptBuffer = 32 - NegotiateReadTimeout = time.Second * 60 -) - -// ConnWrapper is any function that wraps a raw multiaddr connection -type ConnWrapper func(transport.Conn) transport.Conn - -// listener is an object that can accept connections. It implements Listener -type listener struct { - transport.Listener - - local peer.ID // LocalPeer is the identity of the local Peer - privk ic.PrivKey // private key to use to initialize secure conns - - filters *filter.Filters - - wrapper ConnWrapper - catcher tec.TempErrCatcher - - proc goprocess.Process - - mux *msmux.MultistreamMuxer - - incoming chan connErr - - ctx context.Context -} - -func (l *listener) teardown() error { - defer log.Debugf("listener closed: %s %s", l.local, l.Multiaddr()) - return l.Listener.Close() -} - -func (l *listener) Close() error { - log.Debugf("listener closing: %s %s", l.local, l.Multiaddr()) - return l.proc.Close() -} - -func (l *listener) String() string { - return fmt.Sprintf("", l.local, l.Multiaddr()) -} - -func (l *listener) SetAddrFilters(fs *filter.Filters) { - l.filters = fs -} - -type connErr struct { - conn transport.Conn - err error -} - -// Accept waits for and returns the next connection to the listener. -// Note that unfortunately this -func (l *listener) Accept() (net.Conn, error) { - for con := range l.incoming { - if con.err != nil { - return nil, con.err - } - - c, err := newSingleConn(l.ctx, l.local, "", con.conn) - if err != nil { - con.conn.Close() - if l.catcher.IsTemporary(err) { - continue - } - return nil, err - } - - if l.privk == nil || !EncryptConnections { - log.Warning("listener %s listening INSECURELY!", l) - return c, nil - } - sc, err := newSecureConn(l.ctx, l.privk, c) - if err != nil { - con.conn.Close() - log.Infof("ignoring conn we failed to secure: %s %s", err, c) - continue - } - return sc, nil - } - return nil, fmt.Errorf("listener is closed") -} - -func (l *listener) Addr() net.Addr { - return l.Listener.Addr() -} - -// Multiaddr is the identity of the local Peer. -// If there is an error converting from net.Addr to ma.Multiaddr, -// the return value will be nil. -func (l *listener) Multiaddr() ma.Multiaddr { - return l.Listener.Multiaddr() -} - -// LocalPeer is the identity of the local Peer. -func (l *listener) LocalPeer() peer.ID { - return l.local -} - -func (l *listener) Loggable() map[string]interface{} { - return map[string]interface{}{ - "listener": map[string]interface{}{ - "peer": l.LocalPeer(), - "address": l.Multiaddr(), - "secure": (l.privk != nil), - }, - } -} - -func (l *listener) handleIncoming() { - var wg sync.WaitGroup - defer func() { - wg.Wait() - close(l.incoming) - }() - - wg.Add(1) - defer wg.Done() - - for { - maconn, err := l.Listener.Accept() - if err != nil { - if l.catcher.IsTemporary(err) { - continue - } - - l.incoming <- connErr{err: err} - return - } - - log.Debugf("listener %s got connection: %s <---> %s", l, maconn.LocalMultiaddr(), maconn.RemoteMultiaddr()) - - if l.filters != nil && l.filters.AddrBlocked(maconn.RemoteMultiaddr()) { - log.Debugf("blocked connection from %s", maconn.RemoteMultiaddr()) - maconn.Close() - continue - } - // If we have a wrapper func, wrap this conn - if l.wrapper != nil { - maconn = l.wrapper(maconn) - } - - wg.Add(1) - go func() { - defer wg.Done() - maconn.SetReadDeadline(time.Now().Add(NegotiateReadTimeout)) - _, _, err = l.mux.Negotiate(maconn) - if err != nil { - log.Info("incoming conn: negotiation of crypto protocol failed: ", err) - maconn.Close() - return - } - - // clear read readline - maconn.SetReadDeadline(time.Time{}) - - l.incoming <- connErr{conn: maconn} - }() - } -} - -func WrapTransportListener(ctx context.Context, ml transport.Listener, local peer.ID, sk ic.PrivKey) (Listener, error) { - l := &listener{ - Listener: ml, - local: local, - privk: sk, - mux: msmux.NewMultistreamMuxer(), - incoming: make(chan connErr, connAcceptBuffer), - ctx: ctx, - } - l.proc = goprocessctx.WithContextAndTeardown(ctx, l.teardown) - l.catcher.IsTemp = func(e error) bool { - // ignore connection breakages up to this point. but log them - if e == io.EOF { - log.Debugf("listener ignoring conn with EOF: %s", e) - return true - } - - te, ok := e.(tec.Temporary) - if ok { - log.Debugf("listener ignoring conn with temporary err: %s", e) - return te.Temporary() - } - return false - } - - if EncryptConnections && sk != nil { - l.mux.AddHandler(SecioTag, nil) - } else { - l.mux.AddHandler(NoEncryptionTag, nil) - } - - go l.handleIncoming() - - log.Debugf("Conn Listener on %s", l.Multiaddr()) - log.Event(ctx, "swarmListen", l) - return l, nil -} - -type ListenerConnWrapper interface { - SetConnWrapper(ConnWrapper) -} - -// SetConnWrapper assigns a maconn ConnWrapper to wrap all incoming -// connections with. MUST be set _before_ calling `Accept()` -func (l *listener) SetConnWrapper(cw ConnWrapper) { - l.wrapper = cw -} diff --git a/p2p/net/conn/secure_conn.go b/p2p/net/conn/secure_conn.go deleted file mode 100644 index f34f471a90..0000000000 --- a/p2p/net/conn/secure_conn.go +++ /dev/null @@ -1,124 +0,0 @@ -package conn - -import ( - "context" - "errors" - "net" - "time" - - ic "github.com/ipfs/go-libp2p-crypto" - peer "github.com/ipfs/go-libp2p-peer" - secio "github.com/ipfs/go-libp2p-secio" - ma "github.com/jbenet/go-multiaddr" -) - -// secureConn wraps another Conn object with an encrypted channel. -type secureConn struct { - insecure Conn // the wrapped conn - secure secio.Session // secure Session -} - -// newConn constructs a new connection -func newSecureConn(ctx context.Context, sk ic.PrivKey, insecure Conn) (Conn, error) { - - if insecure == nil { - return nil, errors.New("insecure is nil") - } - if insecure.LocalPeer() == "" { - return nil, errors.New("insecure.LocalPeer() is nil") - } - if sk == nil { - return nil, errors.New("private key is nil") - } - - // NewSession performs the secure handshake, which takes multiple RTT - sessgen := secio.SessionGenerator{LocalID: insecure.LocalPeer(), PrivateKey: sk} - secure, err := sessgen.NewSession(ctx, insecure) - if err != nil { - return nil, err - } - - conn := &secureConn{ - insecure: insecure, - secure: secure, - } - return conn, nil -} - -func (c *secureConn) Close() error { - return c.secure.Close() -} - -// ID is an identifier unique to this connection. -func (c *secureConn) ID() string { - return ID(c) -} - -func (c *secureConn) String() string { - return String(c, "secureConn") -} - -func (c *secureConn) LocalAddr() net.Addr { - return c.insecure.LocalAddr() -} - -func (c *secureConn) RemoteAddr() net.Addr { - return c.insecure.RemoteAddr() -} - -func (c *secureConn) SetDeadline(t time.Time) error { - return c.insecure.SetDeadline(t) -} - -func (c *secureConn) SetReadDeadline(t time.Time) error { - return c.insecure.SetReadDeadline(t) -} - -func (c *secureConn) SetWriteDeadline(t time.Time) error { - return c.insecure.SetWriteDeadline(t) -} - -// LocalMultiaddr is the Multiaddr on this side -func (c *secureConn) LocalMultiaddr() ma.Multiaddr { - return c.insecure.LocalMultiaddr() -} - -// RemoteMultiaddr is the Multiaddr on the remote side -func (c *secureConn) RemoteMultiaddr() ma.Multiaddr { - return c.insecure.RemoteMultiaddr() -} - -// LocalPeer is the Peer on this side -func (c *secureConn) LocalPeer() peer.ID { - return c.secure.LocalPeer() -} - -// RemotePeer is the Peer on the remote side -func (c *secureConn) RemotePeer() peer.ID { - return c.secure.RemotePeer() -} - -// LocalPrivateKey is the public key of the peer on this side -func (c *secureConn) LocalPrivateKey() ic.PrivKey { - return c.secure.LocalPrivateKey() -} - -// RemotePubKey is the public key of the peer on the remote side -func (c *secureConn) RemotePublicKey() ic.PubKey { - return c.secure.RemotePublicKey() -} - -// Read reads data, net.Conn style -func (c *secureConn) Read(buf []byte) (int, error) { - return c.secure.ReadWriter().Read(buf) -} - -// Write writes data, net.Conn style -func (c *secureConn) Write(buf []byte) (int, error) { - return c.secure.ReadWriter().Write(buf) -} - -// ReleaseMsg releases a buffer -func (c *secureConn) ReleaseMsg(m []byte) { - c.secure.ReadWriter().ReleaseMsg(m) -} diff --git a/p2p/net/conn/secure_conn_test.go b/p2p/net/conn/secure_conn_test.go deleted file mode 100644 index 9c7b220a85..0000000000 --- a/p2p/net/conn/secure_conn_test.go +++ /dev/null @@ -1,211 +0,0 @@ -package conn - -import ( - "bytes" - "context" - "runtime" - "sync" - "testing" - "time" - - ic "github.com/ipfs/go-libp2p-crypto" - travis "github.com/libp2p/go-libp2p/testutil/ci/travis" -) - -func upgradeToSecureConn(t *testing.T, ctx context.Context, sk ic.PrivKey, c Conn) (Conn, error) { - if c, ok := c.(*secureConn); ok { - return c, nil - } - - // shouldn't happen, because dial + listen already return secure conns. - s, err := newSecureConn(ctx, sk, c) - if err != nil { - return nil, err - } - - // need to read + write, as that's what triggers the handshake. - h := []byte("hello") - if _, err := s.Write(h); err != nil { - return nil, err - } - if _, err := s.Read(h); err != nil { - return nil, err - } - return s, nil -} - -func secureHandshake(t *testing.T, ctx context.Context, sk ic.PrivKey, c Conn, done chan error) { - _, err := upgradeToSecureConn(t, ctx, sk, c) - done <- err -} - -func TestSecureSimple(t *testing.T) { - // t.Skip("Skipping in favor of another test") - - numMsgs := 100 - if testing.Short() { - numMsgs = 10 - } - - ctx := context.Background() - c1, c2, p1, p2 := setupSingleConn(t, ctx) - - done := make(chan error) - go secureHandshake(t, ctx, p1.PrivKey, c1, done) - go secureHandshake(t, ctx, p2.PrivKey, c2, done) - - for i := 0; i < 2; i++ { - if err := <-done; err != nil { - t.Fatal(err) - } - } - - for i := 0; i < numMsgs; i++ { - testOneSendRecv(t, c1, c2) - testOneSendRecv(t, c2, c1) - } - - c1.Close() - c2.Close() -} - -func TestSecureClose(t *testing.T) { - // t.Skip("Skipping in favor of another test") - - ctx := context.Background() - c1, c2, p1, p2 := setupSingleConn(t, ctx) - - done := make(chan error) - go secureHandshake(t, ctx, p1.PrivKey, c1, done) - go secureHandshake(t, ctx, p2.PrivKey, c2, done) - - for i := 0; i < 2; i++ { - if err := <-done; err != nil { - t.Fatal(err) - } - } - - testOneSendRecv(t, c1, c2) - - c1.Close() - testNotOneSendRecv(t, c1, c2) - - c2.Close() - testNotOneSendRecv(t, c1, c2) - testNotOneSendRecv(t, c2, c1) - -} - -func TestSecureCancelHandshake(t *testing.T) { - // t.Skip("Skipping in favor of another test") - - ctx, cancel := context.WithCancel(context.Background()) - c1, c2, p1, p2 := setupSingleConn(t, ctx) - - done := make(chan error) - go secureHandshake(t, ctx, p1.PrivKey, c1, done) - time.Sleep(time.Millisecond) - cancel() // cancel ctx - go secureHandshake(t, ctx, p2.PrivKey, c2, done) - - for i := 0; i < 2; i++ { - if err := <-done; err == nil { - t.Error("cancel should've errored out") - } - } -} - -func TestSecureHandshakeFailsWithWrongKeys(t *testing.T) { - // t.Skip("Skipping in favor of another test") - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - c1, c2, p1, p2 := setupSingleConn(t, ctx) - - done := make(chan error) - go secureHandshake(t, ctx, p2.PrivKey, c1, done) - go secureHandshake(t, ctx, p1.PrivKey, c2, done) - - for i := 0; i < 2; i++ { - if err := <-done; err == nil { - t.Fatal("wrong keys should've errored out.") - } - } -} - -func TestSecureCloseLeak(t *testing.T) { - // t.Skip("Skipping in favor of another test") - - if testing.Short() { - t.SkipNow() - } - if travis.IsRunning() { - t.Skip("this doesn't work well on travis") - } - - runPair := func(c1, c2 Conn, num int) { - mc1 := msgioWrap(c1) - mc2 := msgioWrap(c2) - - log.Debugf("runPair %d", num) - - for i := 0; i < num; i++ { - log.Debugf("runPair iteration %d", i) - b1 := []byte("beep") - mc1.WriteMsg(b1) - b2, err := mc2.ReadMsg() - if err != nil { - panic(err) - } - if !bytes.Equal(b1, b2) { - panic("bytes not equal") - } - - b2 = []byte("beep") - mc2.WriteMsg(b2) - b1, err = mc1.ReadMsg() - if err != nil { - panic(err) - } - if !bytes.Equal(b1, b2) { - panic("bytes not equal") - } - - time.Sleep(time.Microsecond * 5) - } - } - - var cons = 5 - var msgs = 50 - log.Debugf("Running %d connections * %d msgs.\n", cons, msgs) - - var wg sync.WaitGroup - for i := 0; i < cons; i++ { - wg.Add(1) - - ctx, cancel := context.WithCancel(context.Background()) - c1, c2, _, _ := setupSecureConn(t, ctx) - go func(c1, c2 Conn) { - - defer func() { - c1.Close() - c2.Close() - cancel() - wg.Done() - }() - - runPair(c1, c2, msgs) - }(c1, c2) - } - - log.Debugf("Waiting...") - wg.Wait() - // done! - - time.Sleep(time.Millisecond * 150) - ngr := runtime.NumGoroutine() - if ngr > 25 { - // panic("uncomment me to debug") - t.Fatal("leaking goroutines:", ngr) - } -} diff --git a/p2p/net/interface.go b/p2p/net/interface.go index fffe0cda54..1b296356d0 100644 --- a/p2p/net/interface.go +++ b/p2p/net/interface.go @@ -8,8 +8,8 @@ import ( pstore "github.com/ipfs/go-libp2p-peerstore" ma "github.com/jbenet/go-multiaddr" "github.com/jbenet/goprocess" + conn "github.com/libp2p/go-libp2p-conn" protocol "github.com/libp2p/go-libp2p-protocol" - conn "github.com/libp2p/go-libp2p/p2p/net/conn" ) // MessageSizeMax is a soft (recommended) maximum for network messages. diff --git a/p2p/net/mock/mock_net.go b/p2p/net/mock/mock_net.go index 565b5c43ec..53cb971a9e 100644 --- a/p2p/net/mock/mock_net.go +++ b/p2p/net/mock/mock_net.go @@ -1,6 +1,7 @@ package mocknet import ( + "context" "fmt" "sort" "sync" @@ -9,15 +10,14 @@ import ( bhost "github.com/libp2p/go-libp2p/p2p/host/basic" inet "github.com/libp2p/go-libp2p/p2p/net" p2putil "github.com/libp2p/go-libp2p/p2p/test/util" - testutil "github.com/libp2p/go-libp2p/testutil" - "context" ic "github.com/ipfs/go-libp2p-crypto" peer "github.com/ipfs/go-libp2p-peer" pstore "github.com/ipfs/go-libp2p-peerstore" ma "github.com/jbenet/go-multiaddr" "github.com/jbenet/goprocess" goprocessctx "github.com/jbenet/goprocess/context" + testutil "github.com/libp2p/go-testutil" ) // mocknet implements mocknet.Mocknet diff --git a/p2p/net/mock/mock_test.go b/p2p/net/mock/mock_test.go index e00cb10acc..cef3a789a5 100644 --- a/p2p/net/mock/mock_test.go +++ b/p2p/net/mock/mock_test.go @@ -2,6 +2,7 @@ package mocknet import ( "bytes" + "context" "io" "math" "math/rand" @@ -9,13 +10,12 @@ import ( "testing" "time" - peer "github.com/ipfs/go-libp2p-peer" - protocol "github.com/libp2p/go-libp2p-protocol" inet "github.com/libp2p/go-libp2p/p2p/net" - testutil "github.com/libp2p/go-libp2p/testutil" - "context" + peer "github.com/ipfs/go-libp2p-peer" detectrace "github.com/jbenet/go-detect-race" + protocol "github.com/libp2p/go-libp2p-protocol" + testutil "github.com/libp2p/go-testutil" ) func randPeer(t *testing.T) peer.ID { diff --git a/p2p/net/swarm/addr/addr.go b/p2p/net/swarm/addr/addr.go deleted file mode 100644 index 4a14c43778..0000000000 --- a/p2p/net/swarm/addr/addr.go +++ /dev/null @@ -1,284 +0,0 @@ -package addrutil - -import ( - "fmt" - - "context" - logging "github.com/ipfs/go-log" - ma "github.com/jbenet/go-multiaddr" - manet "github.com/jbenet/go-multiaddr-net" - - _ "github.com/whyrusleeping/ws-transport" -) - -var log = logging.Logger("github.com/libp2p/go-libp2p/p2p/net/swarm/addr") - -// SupportedTransportStrings is the list of supported transports for the swarm. -// These are strings of encapsulated multiaddr protocols. E.g.: -// /ip4/tcp -var SupportedTransportStrings = []string{ - "/ip4/tcp", - "/ip6/tcp", - "/ip4/udp/utp", - "/ip6/udp/utp", - "/ip4/tcp/ws", - "/ip6/tcp/ws", - // "/ip4/udp/udt", disabled because the lib doesnt work on arm - // "/ip6/udp/udt", disabled because the lib doesnt work on arm -} - -// SupportedTransportProtocols is the list of supported transports for the swarm. -// These are []ma.Protocol lists. Populated at runtime from SupportedTransportStrings -var SupportedTransportProtocols = [][]ma.Protocol{} - -func init() { - // initialize SupportedTransportProtocols - transports := make([][]ma.Protocol, len(SupportedTransportStrings)) - for _, s := range SupportedTransportStrings { - t, err := ma.ProtocolsWithString(s) - if err != nil { - panic(err) // important to fix this in the codebase - } - transports = append(transports, t) - } - SupportedTransportProtocols = transports -} - -// FilterAddrs is a filter that removes certain addresses, according the given filters. -// if all filters return true, the address is kept. -func FilterAddrs(a []ma.Multiaddr, filters ...func(ma.Multiaddr) bool) []ma.Multiaddr { - b := make([]ma.Multiaddr, 0, len(a)) - for _, addr := range a { - good := true - for _, filter := range filters { - good = good && filter(addr) - } - if good { - b = append(b, addr) - } - } - return b -} - -// FilterUsableAddrs removes certain addresses -// from a list. the addresses removed are those known NOT -// to work with our network. Namely, addresses with UTP. -func FilterUsableAddrs(a []ma.Multiaddr) []ma.Multiaddr { - return FilterAddrs(a, AddrUsableFunc) -} - -func AddrUsableFunc(m ma.Multiaddr) bool { - return AddrUsable(m, false) -} - -// AddrOverNonLocalIP returns whether the addr uses a non-local ip link -func AddrOverNonLocalIP(a ma.Multiaddr) bool { - split := ma.Split(a) - if len(split) < 1 { - return false - } - if manet.IsIP6LinkLocal(split[0]) { - return false - } - return true -} - -// AddrUsable returns whether our network can use this addr. -// We only use the transports in SupportedTransportStrings, -// and we do not link local addresses. Loopback is ok -// as we need to be able to connect to multiple ipfs nodes -// in the same machine. -func AddrUsable(a ma.Multiaddr, partial bool) bool { - if a == nil { - return false - } - - if !AddrOverNonLocalIP(a) { - return false - } - - // test the address protocol list is in SupportedTransportProtocols - matches := func(supported, test []ma.Protocol) bool { - if len(test) > len(supported) { - return false - } - - // when partial, it's ok if test < supported. - if !partial && len(supported) != len(test) { - return false - } - - for i := range test { - if supported[i].Code != test[i].Code { - return false - } - } - return true - } - - transport := a.Protocols() - for _, supported := range SupportedTransportProtocols { - if matches(supported, transport) { - return true - } - } - - return false -} - -// ResolveUnspecifiedAddress expands an unspecified ip addresses (/ip4/0.0.0.0, /ip6/::) to -// use the known local interfaces. If ifaceAddr is nil, we request interface addresses -// from the network stack. (this is so you can provide a cached value if resolving many addrs) -func ResolveUnspecifiedAddress(resolve ma.Multiaddr, ifaceAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) { - // split address into its components - split := ma.Split(resolve) - - // if first component (ip) is not unspecified, use it as is. - if !manet.IsIPUnspecified(split[0]) { - return []ma.Multiaddr{resolve}, nil - } - - out := make([]ma.Multiaddr, 0, len(ifaceAddrs)) - for _, ia := range ifaceAddrs { - // must match the first protocol to be resolve. - if ia.Protocols()[0].Code != resolve.Protocols()[0].Code { - continue - } - - split[0] = ia - joined := ma.Join(split...) - out = append(out, joined) - log.Debug("adding resolved addr:", resolve, joined, out) - } - if len(out) < 1 { - return nil, fmt.Errorf("failed to resolve: %s", resolve) - } - return out, nil -} - -// ResolveUnspecifiedAddresses expands unspecified ip addresses (/ip4/0.0.0.0, /ip6/::) to -// use the known local interfaces. -func ResolveUnspecifiedAddresses(unspecAddrs, ifaceAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) { - - // todo optimize: only fetch these if we have a "any" addr. - if len(ifaceAddrs) < 1 { - var err error - ifaceAddrs, err = InterfaceAddresses() - if err != nil { - return nil, err - } - // log.Debug("InterfaceAddresses:", ifaceAddrs) - } - - var outputAddrs []ma.Multiaddr - for _, a := range unspecAddrs { - // unspecified? - resolved, err := ResolveUnspecifiedAddress(a, ifaceAddrs) - if err != nil { - continue // optimistic. if we cant resolve anything, we'll know at the bottom. - } - // log.Debug("resolved:", a, resolved) - outputAddrs = append(outputAddrs, resolved...) - } - - if len(outputAddrs) < 1 { - return nil, fmt.Errorf("failed to specify addrs: %s", unspecAddrs) - } - - log.Event(context.TODO(), "interfaceListenAddresses", func() logging.Loggable { - var addrs []string - for _, addr := range outputAddrs { - addrs = append(addrs, addr.String()) - } - return logging.Metadata{"addresses": addrs} - }()) - - log.Debug("ResolveUnspecifiedAddresses:", unspecAddrs, ifaceAddrs, outputAddrs) - return outputAddrs, nil -} - -// InterfaceAddresses returns a list of addresses associated with local machine -// Note: we do not return link local addresses. IP loopback is ok, because we -// may be connecting to other nodes in the same machine. -func InterfaceAddresses() ([]ma.Multiaddr, error) { - maddrs, err := manet.InterfaceMultiaddrs() - if err != nil { - return nil, err - } - log.Debug("InterfaceAddresses: from manet:", maddrs) - - var out []ma.Multiaddr - for _, a := range maddrs { - if !AddrUsable(a, true) { // partial - // log.Debug("InterfaceAddresses: skipping unusable:", a) - continue - } - - out = append(out, a) - } - - log.Debug("InterfaceAddresses: usable:", out) - return out, nil -} - -// AddrInList returns whether or not an address is part of a list. -// this is useful to check if NAT is happening (or other bugs?) -func AddrInList(addr ma.Multiaddr, list []ma.Multiaddr) bool { - for _, addr2 := range list { - if addr.Equal(addr2) { - return true - } - } - return false -} - -// AddrIsShareableOnWAN returns whether the given address should be shareable on the -// wide area network (wide internet). -func AddrIsShareableOnWAN(addr ma.Multiaddr) bool { - s := ma.Split(addr) - if len(s) < 1 { - return false - } - a := s[0] - if manet.IsIPLoopback(a) || manet.IsIP6LinkLocal(a) || manet.IsIPUnspecified(a) { - return false - } - return manet.IsThinWaist(a) -} - -// WANShareableAddrs filters addresses based on whether they're shareable on WAN -func WANShareableAddrs(inp []ma.Multiaddr) []ma.Multiaddr { - return FilterAddrs(inp, AddrIsShareableOnWAN) -} - -// Subtract filters out all addrs in b from a -func Subtract(a, b []ma.Multiaddr) []ma.Multiaddr { - return FilterAddrs(a, func(m ma.Multiaddr) bool { - for _, bb := range b { - if m.Equal(bb) { - return false - } - } - return true - }) -} - -// CheckNATWarning checks if our observed addresses differ. if so, -// informs the user that certain things might not work yet -func CheckNATWarning(observed, expected ma.Multiaddr, listen []ma.Multiaddr) { - if observed.Equal(expected) { - return - } - - if !AddrInList(observed, listen) { // probably a nat - log.Warningf(natWarning, observed, listen) - } -} - -const natWarning = `Remote peer observed our address to be: %s -The local addresses are: %s -Thus, connection is going through NAT, and other connections may fail. - -IPFS NAT traversal is still under development. Please bug us on github or irc to fix this. -Baby steps: http://jbenet.static.s3.amazonaws.com/271dfcf/baby-steps.gif -` diff --git a/p2p/net/swarm/addr/addr_test.go b/p2p/net/swarm/addr/addr_test.go deleted file mode 100644 index 213b7b9f1a..0000000000 --- a/p2p/net/swarm/addr/addr_test.go +++ /dev/null @@ -1,227 +0,0 @@ -package addrutil - -import ( - "testing" - - ma "github.com/jbenet/go-multiaddr" - manet "github.com/jbenet/go-multiaddr-net" -) - -func newMultiaddr(t *testing.T, s string) ma.Multiaddr { - maddr, err := ma.NewMultiaddr(s) - if err != nil { - t.Fatal(err) - } - return maddr -} - -func TestFilterAddrs(t *testing.T) { - - bad := []ma.Multiaddr{ - newMultiaddr(t, "/ip4/1.2.3.4/udp/1234"), // unreliable - newMultiaddr(t, "/ip4/1.2.3.4/udp/1234/sctp/1234"), // not in manet - newMultiaddr(t, "/ip4/1.2.3.4/udp/1234/udt"), // udt is broken on arm - newMultiaddr(t, "/ip6/fe80::1/tcp/1234"), // link local - newMultiaddr(t, "/ip6/fe80::100/tcp/1234"), // link local - } - - good := []ma.Multiaddr{ - newMultiaddr(t, "/ip4/127.0.0.1/tcp/1234"), - newMultiaddr(t, "/ip6/::1/tcp/1234"), - newMultiaddr(t, "/ip4/1.2.3.4/udp/1234/utp"), - newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/ws"), - } - - goodAndBad := append(good, bad...) - - // test filters - - for _, a := range bad { - if AddrUsable(a, false) { - t.Errorf("addr %s should be unusable", a) - } - } - - for _, a := range good { - if !AddrUsable(a, false) { - t.Errorf("addr %s should be usable", a) - } - } - - subtestAddrsEqual(t, FilterUsableAddrs(bad), []ma.Multiaddr{}) - subtestAddrsEqual(t, FilterUsableAddrs(good), good) - subtestAddrsEqual(t, FilterUsableAddrs(goodAndBad), good) -} - -func subtestAddrsEqual(t *testing.T, a, b []ma.Multiaddr) { - if len(a) != len(b) { - t.Error(t) - } - - in := func(addr ma.Multiaddr, l []ma.Multiaddr) bool { - for _, addr2 := range l { - if addr.Equal(addr2) { - return true - } - } - return false - } - - for _, aa := range a { - if !in(aa, b) { - t.Errorf("%s not in %s", aa, b) - } - } -} - -func TestInterfaceAddrs(t *testing.T) { - addrs, err := InterfaceAddresses() - if err != nil { - t.Fatal(err) - } - - if len(addrs) < 1 { - t.Error("no addresses") - } - - for _, a := range addrs { - if manet.IsIP6LinkLocal(a) { - t.Error("should not return ip link local addresses", a) - } - } - - if len(addrs) < 1 { - t.Error("no good interface addrs") - } -} - -func TestResolvingAddrs(t *testing.T) { - - unspec := []ma.Multiaddr{ - newMultiaddr(t, "/ip4/0.0.0.0/tcp/1234"), - newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234"), - newMultiaddr(t, "/ip6/::/tcp/1234"), - newMultiaddr(t, "/ip6/::100/tcp/1234"), - } - - iface := []ma.Multiaddr{ - newMultiaddr(t, "/ip4/127.0.0.1"), - newMultiaddr(t, "/ip4/10.20.30.40"), - newMultiaddr(t, "/ip6/::1"), - newMultiaddr(t, "/ip6/::f"), - } - - spec := []ma.Multiaddr{ - newMultiaddr(t, "/ip4/127.0.0.1/tcp/1234"), - newMultiaddr(t, "/ip4/10.20.30.40/tcp/1234"), - newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234"), - newMultiaddr(t, "/ip6/::1/tcp/1234"), - newMultiaddr(t, "/ip6/::f/tcp/1234"), - newMultiaddr(t, "/ip6/::100/tcp/1234"), - } - - actual, err := ResolveUnspecifiedAddresses(unspec, iface) - if err != nil { - t.Fatal(err) - } - - for i, a := range actual { - if !a.Equal(spec[i]) { - t.Error(a, " != ", spec[i]) - } - } - - ip4u := []ma.Multiaddr{newMultiaddr(t, "/ip4/0.0.0.0")} - ip4i := []ma.Multiaddr{newMultiaddr(t, "/ip4/1.2.3.4")} - - ip6u := []ma.Multiaddr{newMultiaddr(t, "/ip6/::")} - ip6i := []ma.Multiaddr{newMultiaddr(t, "/ip6/::1")} - - if _, err := ResolveUnspecifiedAddress(ip4u[0], ip6i); err == nil { - t.Fatal("should have failed") - } - if _, err := ResolveUnspecifiedAddress(ip6u[0], ip4i); err == nil { - t.Fatal("should have failed") - } - - if _, err := ResolveUnspecifiedAddresses(ip6u, ip4i); err == nil { - t.Fatal("should have failed") - } - if _, err := ResolveUnspecifiedAddresses(ip4u, ip6i); err == nil { - t.Fatal("should have failed") - } - -} - -func TestWANShareable(t *testing.T) { - - wanok := []ma.Multiaddr{ - newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234"), - newMultiaddr(t, "/ip6/abcd::1/tcp/1234"), - } - - wanbad := []ma.Multiaddr{ - newMultiaddr(t, "/ip4/127.0.0.1/tcp/1234"), - newMultiaddr(t, "/ip4/0.0.0.0/tcp/1234"), - newMultiaddr(t, "/ip6/::1/tcp/1234"), - newMultiaddr(t, "/ip6/::/tcp/1234"), - newMultiaddr(t, "/ip6/fe80::1/tcp/1234"), - newMultiaddr(t, "/ip6/fe80::/tcp/1234"), - } - - for _, a := range wanok { - if !AddrIsShareableOnWAN(a) { - t.Error("should be true", a) - } - } - - for _, a := range wanbad { - if AddrIsShareableOnWAN(a) { - t.Error("should be false", a) - } - } - - wanok2 := WANShareableAddrs(wanok) - if len(wanok) != len(wanok2) { - t.Error("should be the same") - } - - wanbad2 := WANShareableAddrs(wanbad) - if len(wanbad2) != 0 { - t.Error("should be zero") - } -} - -func TestSubtract(t *testing.T) { - - a := []ma.Multiaddr{ - newMultiaddr(t, "/ip4/127.0.0.1/tcp/1234"), - newMultiaddr(t, "/ip4/0.0.0.0/tcp/1234"), - newMultiaddr(t, "/ip6/::1/tcp/1234"), - newMultiaddr(t, "/ip6/::/tcp/1234"), - newMultiaddr(t, "/ip6/fe80::1/tcp/1234"), - newMultiaddr(t, "/ip6/fe80::/tcp/1234"), - } - - b := []ma.Multiaddr{ - newMultiaddr(t, "/ip4/127.0.0.1/tcp/1234"), - newMultiaddr(t, "/ip6/::1/tcp/1234"), - newMultiaddr(t, "/ip6/fe80::1/tcp/1234"), - } - - c1 := []ma.Multiaddr{ - newMultiaddr(t, "/ip4/0.0.0.0/tcp/1234"), - newMultiaddr(t, "/ip6/::/tcp/1234"), - newMultiaddr(t, "/ip6/fe80::/tcp/1234"), - } - - c2 := Subtract(a, b) - if len(c1) != len(c2) { - t.Error("should be the same") - } - for i, ca := range c1 { - if !c2[i].Equal(ca) { - t.Error("should be the same", ca, c2[i]) - } - } -} diff --git a/p2p/net/swarm/addr/filter.go b/p2p/net/swarm/addr/filter.go deleted file mode 100644 index d87ba816a7..0000000000 --- a/p2p/net/swarm/addr/filter.go +++ /dev/null @@ -1,31 +0,0 @@ -package addrutil - -import ( - ma "github.com/jbenet/go-multiaddr" - mafmt "github.com/whyrusleeping/mafmt" -) - -// SubtractFilter returns a filter func that filters all of the given addresses -func SubtractFilter(addrs ...ma.Multiaddr) func(ma.Multiaddr) bool { - addrmap := make(map[string]bool) - for _, a := range addrs { - addrmap[string(a.Bytes())] = true - } - - return func(a ma.Multiaddr) bool { - return !addrmap[string(a.Bytes())] - } -} - -// IsFDCostlyTransport returns true for transports that require a new file -// descriptor per connection created -func IsFDCostlyTransport(a ma.Multiaddr) bool { - return mafmt.TCP.Matches(a) -} - -// FilterNeg returns a negated version of the passed in filter -func FilterNeg(f func(ma.Multiaddr) bool) func(ma.Multiaddr) bool { - return func(a ma.Multiaddr) bool { - return !f(a) - } -} diff --git a/p2p/net/swarm/dial_test.go b/p2p/net/swarm/dial_test.go index ab65b8c59f..8e7b48fc2b 100644 --- a/p2p/net/swarm/dial_test.go +++ b/p2p/net/swarm/dial_test.go @@ -1,20 +1,19 @@ package swarm import ( + "context" "net" "sync" "testing" "time" - addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr" - testutil "github.com/libp2p/go-libp2p/testutil" - ci "github.com/libp2p/go-libp2p/testutil/ci" - - "context" peer "github.com/ipfs/go-libp2p-peer" pstore "github.com/ipfs/go-libp2p-peerstore" ma "github.com/jbenet/go-multiaddr" manet "github.com/jbenet/go-multiaddr-net" + addrutil "github.com/libp2p/go-addr-util" + testutil "github.com/libp2p/go-testutil" + ci "github.com/libp2p/go-testutil/ci" ) func closeSwarms(swarms []*Swarm) { diff --git a/p2p/net/swarm/limiter.go b/p2p/net/swarm/limiter.go index c34954a527..5c8d235b8e 100644 --- a/p2p/net/swarm/limiter.go +++ b/p2p/net/swarm/limiter.go @@ -6,9 +6,8 @@ import ( peer "github.com/ipfs/go-libp2p-peer" ma "github.com/jbenet/go-multiaddr" - - conn "github.com/libp2p/go-libp2p/p2p/net/conn" - addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr" + addrutil "github.com/libp2p/go-addr-util" + conn "github.com/libp2p/go-libp2p-conn" ) type dialResult struct { diff --git a/p2p/net/swarm/limiter_test.go b/p2p/net/swarm/limiter_test.go index 93761a5048..7332c0e06a 100644 --- a/p2p/net/swarm/limiter_test.go +++ b/p2p/net/swarm/limiter_test.go @@ -10,9 +10,8 @@ import ( peer "github.com/ipfs/go-libp2p-peer" ma "github.com/jbenet/go-multiaddr" + conn "github.com/libp2p/go-libp2p-conn" mafmt "github.com/whyrusleeping/mafmt" - - conn "github.com/libp2p/go-libp2p/p2p/net/conn" ) func mustAddr(t *testing.T, s string) ma.Multiaddr { diff --git a/p2p/net/swarm/simul_test.go b/p2p/net/swarm/simul_test.go index bc9cf3ae0f..3518f139e6 100644 --- a/p2p/net/swarm/simul_test.go +++ b/p2p/net/swarm/simul_test.go @@ -1,17 +1,16 @@ package swarm import ( + "context" "runtime" "sync" "testing" "time" - ci "github.com/libp2p/go-libp2p/testutil/ci" - - "context" peer "github.com/ipfs/go-libp2p-peer" pstore "github.com/ipfs/go-libp2p-peerstore" ma "github.com/jbenet/go-multiaddr" + ci "github.com/libp2p/go-testutil/ci" ) func TestSimultOpen(t *testing.T) { diff --git a/p2p/net/swarm/swarm.go b/p2p/net/swarm/swarm.go index 19ccf13eef..9107d7160a 100644 --- a/p2p/net/swarm/swarm.go +++ b/p2p/net/swarm/swarm.go @@ -14,8 +14,6 @@ import ( metrics "github.com/libp2p/go-libp2p/p2p/metrics" mconn "github.com/libp2p/go-libp2p/p2p/metrics/conn" inet "github.com/libp2p/go-libp2p/p2p/net" - conn "github.com/libp2p/go-libp2p/p2p/net/conn" - addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr" ci "github.com/ipfs/go-libp2p-crypto" peer "github.com/ipfs/go-libp2p-peer" @@ -26,6 +24,8 @@ import ( pst "github.com/jbenet/go-stream-muxer" "github.com/jbenet/goprocess" goprocessctx "github.com/jbenet/goprocess/context" + addrutil "github.com/libp2p/go-addr-util" + conn "github.com/libp2p/go-libp2p-conn" transport "github.com/libp2p/go-libp2p-transport" filter "github.com/libp2p/go-maddr-filter" tcpt "github.com/libp2p/go-tcp-transport" diff --git a/p2p/net/swarm/swarm_addr.go b/p2p/net/swarm/swarm_addr.go index 39fbe02afc..87b0829da1 100644 --- a/p2p/net/swarm/swarm_addr.go +++ b/p2p/net/swarm/swarm_addr.go @@ -1,10 +1,9 @@ package swarm import ( - conn "github.com/libp2p/go-libp2p/p2p/net/conn" - addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr" - ma "github.com/jbenet/go-multiaddr" + addrutil "github.com/libp2p/go-addr-util" + conn "github.com/libp2p/go-libp2p-conn" ) // ListenAddresses returns a list of addresses at which this swarm listens. diff --git a/p2p/net/swarm/swarm_addr_test.go b/p2p/net/swarm/swarm_addr_test.go index e221f7bc87..bd48d4f601 100644 --- a/p2p/net/swarm/swarm_addr_test.go +++ b/p2p/net/swarm/swarm_addr_test.go @@ -1,15 +1,15 @@ package swarm import ( + "context" "testing" metrics "github.com/libp2p/go-libp2p/p2p/metrics" - addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr" - testutil "github.com/libp2p/go-libp2p/testutil" - "context" pstore "github.com/ipfs/go-libp2p-peerstore" ma "github.com/jbenet/go-multiaddr" + addrutil "github.com/libp2p/go-addr-util" + testutil "github.com/libp2p/go-testutil" ) func TestFilterAddrs(t *testing.T) { diff --git a/p2p/net/swarm/swarm_conn.go b/p2p/net/swarm/swarm_conn.go index 40f5bdf0ab..30ef800edb 100644 --- a/p2p/net/swarm/swarm_conn.go +++ b/p2p/net/swarm/swarm_conn.go @@ -1,16 +1,16 @@ package swarm import ( + "context" "fmt" inet "github.com/libp2p/go-libp2p/p2p/net" - conn "github.com/libp2p/go-libp2p/p2p/net/conn" - "context" ic "github.com/ipfs/go-libp2p-crypto" peer "github.com/ipfs/go-libp2p-peer" ma "github.com/jbenet/go-multiaddr" ps "github.com/jbenet/go-peerstream" + conn "github.com/libp2p/go-libp2p-conn" ) // Conn is a simple wrapper around a ps.Conn that also exposes diff --git a/p2p/net/swarm/swarm_dial.go b/p2p/net/swarm/swarm_dial.go index 6d1abd3342..29694df73b 100644 --- a/p2p/net/swarm/swarm_dial.go +++ b/p2p/net/swarm/swarm_dial.go @@ -10,8 +10,8 @@ import ( lgbl "github.com/ipfs/go-libp2p-loggables" peer "github.com/ipfs/go-libp2p-peer" ma "github.com/jbenet/go-multiaddr" - conn "github.com/libp2p/go-libp2p/p2p/net/conn" - addrutil "github.com/libp2p/go-libp2p/p2p/net/swarm/addr" + addrutil "github.com/libp2p/go-addr-util" + conn "github.com/libp2p/go-libp2p-conn" ) // Diagram of dial sync: diff --git a/p2p/net/swarm/swarm_listen.go b/p2p/net/swarm/swarm_listen.go index e1b9a876fb..702ef54b7e 100644 --- a/p2p/net/swarm/swarm_listen.go +++ b/p2p/net/swarm/swarm_listen.go @@ -1,16 +1,17 @@ package swarm import ( + "context" "fmt" - "context" + inet "github.com/libp2p/go-libp2p/p2p/net" + lgbl "github.com/ipfs/go-libp2p-loggables" ma "github.com/jbenet/go-multiaddr" ps "github.com/jbenet/go-peerstream" + conn "github.com/libp2p/go-libp2p-conn" transport "github.com/libp2p/go-libp2p-transport" mconn "github.com/libp2p/go-libp2p/p2p/metrics/conn" - inet "github.com/libp2p/go-libp2p/p2p/net" - conn "github.com/libp2p/go-libp2p/p2p/net/conn" ) func (s *Swarm) AddListenAddr(a ma.Multiaddr) error { diff --git a/p2p/net/swarm/swarm_test.go b/p2p/net/swarm/swarm_test.go index b7520dc757..e7099812db 100644 --- a/p2p/net/swarm/swarm_test.go +++ b/p2p/net/swarm/swarm_test.go @@ -2,6 +2,7 @@ package swarm import ( "bytes" + "context" "fmt" "io" "net" @@ -11,12 +12,11 @@ import ( metrics "github.com/libp2p/go-libp2p/p2p/metrics" inet "github.com/libp2p/go-libp2p/p2p/net" - testutil "github.com/libp2p/go-libp2p/testutil" - "context" peer "github.com/ipfs/go-libp2p-peer" pstore "github.com/ipfs/go-libp2p-peerstore" ma "github.com/jbenet/go-multiaddr" + testutil "github.com/libp2p/go-testutil" ) func EchoStreamHandler(stream inet.Stream) { diff --git a/p2p/test/util/key.go b/p2p/test/util/key.go index 71054f2317..99bfb5bec8 100644 --- a/p2p/test/util/key.go +++ b/p2p/test/util/key.go @@ -9,7 +9,7 @@ import ( ic "github.com/ipfs/go-libp2p-crypto" peer "github.com/ipfs/go-libp2p-peer" logging "github.com/ipfs/go-log" - testutil "github.com/libp2p/go-libp2p/testutil" + testutil "github.com/libp2p/go-testutil" ma "github.com/jbenet/go-multiaddr" ) diff --git a/p2p/test/util/util.go b/p2p/test/util/util.go index 02da50f371..917b2e2f12 100644 --- a/p2p/test/util/util.go +++ b/p2p/test/util/util.go @@ -1,17 +1,17 @@ package testutil import ( + "context" "testing" - pstore "github.com/ipfs/go-libp2p-peerstore" bhost "github.com/libp2p/go-libp2p/p2p/host/basic" metrics "github.com/libp2p/go-libp2p/p2p/metrics" inet "github.com/libp2p/go-libp2p/p2p/net" swarm "github.com/libp2p/go-libp2p/p2p/net/swarm" - tu "github.com/libp2p/go-libp2p/testutil" - "context" + pstore "github.com/ipfs/go-libp2p-peerstore" ma "github.com/jbenet/go-multiaddr" + tu "github.com/libp2p/go-testutil" ) func GenSwarmNetwork(t *testing.T, ctx context.Context) *swarm.Network { diff --git a/package.json b/package.json index f289bbe0f9..b76b3d6ea6 100644 --- a/package.json +++ b/package.json @@ -200,6 +200,24 @@ "hash": "QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN", "name": "go-libp2p-protocol", "version": "1.0.0" + }, + { + "author": "whyrusleeping", + "hash": "QmT6RvBdXJ6xfPgEMT7LAmFcTEbs9Ggh2N3fYGfR1xN3HX", + "name": "go-addr-util", + "version": "1.0.0" + }, + { + "author": "whyrusleeping", + "hash": "QmYpVUnnedgGrp6cX2pBii5HRQgcSr778FiKVe7o7nF5Z3", + "name": "go-testutil", + "version": "1.0.2" + }, + { + "author": "whyrusleeping", + "hash": "QmTaW4q1AbqMkpfDLUYzW18nW62GsrnFvtVcvR1pnaURm6", + "name": "go-libp2p-conn", + "version": "1.0.0" } ], "gxVersion": "0.4.0", diff --git a/testutil/ci/ci.go b/testutil/ci/ci.go deleted file mode 100644 index 6539c03005..0000000000 --- a/testutil/ci/ci.go +++ /dev/null @@ -1,52 +0,0 @@ -// Package ci implements some helper functions to use during -// tests. Many times certain facilities are not available, or tests -// must run differently. -package ci - -import ( - "os" - - jenkins "github.com/libp2p/go-libp2p/testutil/ci/jenkins" - travis "github.com/libp2p/go-libp2p/testutil/ci/travis" -) - -// EnvVar is a type to use travis-only env var names with -// the type system. -type EnvVar string - -// Environment variables that TravisCI uses. -const ( - VarCI EnvVar = "CI" - VarNoFuse EnvVar = "TEST_NO_FUSE" - VarVerbose EnvVar = "TEST_VERBOSE" -) - -// IsRunning attempts to determine whether this process is -// running on CI. This is done by checking any of: -// -// CI=true -// travis.IsRunning() -// jenkins.IsRunning() -// -func IsRunning() bool { - if os.Getenv(string(VarCI)) == "true" { - return true - } - - return travis.IsRunning() || jenkins.IsRunning() -} - -// Env returns the value of a CI env variable. -func Env(v EnvVar) string { - return os.Getenv(string(v)) -} - -// Returns whether FUSE is explicitly disabled wiht TEST_NO_FUSE. -func NoFuse() bool { - return os.Getenv(string(VarNoFuse)) == "1" -} - -// Returns whether TEST_VERBOSE is enabled. -func Verbose() bool { - return os.Getenv(string(VarVerbose)) == "1" -} diff --git a/testutil/ci/jenkins/jenkins.go b/testutil/ci/jenkins/jenkins.go deleted file mode 100644 index 5bea216817..0000000000 --- a/testutil/ci/jenkins/jenkins.go +++ /dev/null @@ -1,58 +0,0 @@ -// Package jenkins implements some helper functions to use during -// tests. Many times certain facilities are not available, or tests -// must run differently. -package jenkins - -import ( - "os" - "strings" -) - -// EnvVar is a type to use travis-only env var names with -// the type system. -type EnvVar string - -// Environment variables that Jenkins uses. -const ( - VarBuildNumber EnvVar = "BUILD_NUMBER" - VarBuildId EnvVar = "BUILD_ID" - VarBuildUrl EnvVar = "BUILD_URL" - VarNodeName EnvVar = "NODE_NAME" - VarJobName EnvVar = "JOB_NAME" - VarBuildTag EnvVar = "BUILD_TAG" - VarJenkinsUrl EnvVar = "JENKINS_URL" - VarExecutorNumber EnvVar = "EXECUTOR_NUMBER" - VarJavaHome EnvVar = "JAVA_HOME" - VarWorkspace EnvVar = "WORKSPACE" - VarSvnRevision EnvVar = "SVN_REVISION" - VarCvsBranch EnvVar = "CVS_BRANCH" - VarGitCommit EnvVar = "GIT_COMMIT" - VarGitUrl EnvVar = "GIT_URL" - VarGitBranch EnvVar = "GIT_BRANCH" -) - -// IsRunning attempts to determine whether this process is -// running on Jenkins CI. This is done by checking any of the -// following: -// -// JENKINS_URL is set -// BuildTag has prefix "jenkins-" -// -func IsRunning() bool { - return len(Env(VarJenkinsUrl)) > 0 || strings.HasPrefix(Env(VarBuildTag), "jenkins-") -} - -// Env returns the value of a travis env variable. -func Env(v EnvVar) string { - return os.Getenv(string(v)) -} - -// JobName returns the jenkins JOB_NAME of this build. -func JobName() string { - return Env(VarJobName) -} - -// BuildTag returns the jenkins BUILD_TAG. -func BuildTag() string { - return Env(VarBuildTag) -} diff --git a/testutil/ci/jenkins/jenkins_test.go b/testutil/ci/jenkins/jenkins_test.go deleted file mode 100644 index d37cdf6a5a..0000000000 --- a/testutil/ci/jenkins/jenkins_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package jenkins - -import ( - "os" - "strings" - "testing" -) - -func TestIsRunning(t *testing.T) { - hasPrefix := strings.HasPrefix(os.Getenv("BUILD_TAG"), "jenkins-") - tr := len(os.Getenv("JENKINS_URL")) > 0 || hasPrefix - - if tr != IsRunning() { - t.Error("IsRunning() does not match TRAVIS && CI env var check") - } -} diff --git a/testutil/ci/travis/travis.go b/testutil/ci/travis/travis.go deleted file mode 100644 index 2c72404fc4..0000000000 --- a/testutil/ci/travis/travis.go +++ /dev/null @@ -1,57 +0,0 @@ -// Package travis implements some helper functions to use during -// tests. Many times certain facilities are not available, or tests -// must run differently. -package travis - -import "os" - -// EnvVar is a type to use travis-only env var names with -// the type system. -type EnvVar string - -// Environment variables that TravisCI uses. -const ( - VarCI EnvVar = "CI" - VarTravis EnvVar = "TRAVIS" - VarBranch EnvVar = "TRAVIS_BRANCH" - VarBuildDir EnvVar = "TRAVIS_BUILD_DIR" - VarBuildId EnvVar = "TRAVIS_BUILD_ID" - VarBuildNumber EnvVar = "TRAVIS_BUILD_NUMBER" - VarCommit EnvVar = "TRAVIS_COMMIT" - VarCommitRange EnvVar = "TRAVIS_COMMIT_RANGE" - VarJobId EnvVar = "TRAVIS_JOB_ID" - VarJobNumber EnvVar = "TRAVIS_JOB_NUMBER" - VarPullRequest EnvVar = "TRAVIS_PULL_REQUEST" - VarSecureEnvVars EnvVar = "TRAVIS_SECURE_ENV_VARS" - VarRepoSlug EnvVar = "TRAVIS_REPO_SLUG" - VarOsName EnvVar = "TRAVIS_OS_NAME" - VarTag EnvVar = "TRAVIS_TAG" - VarGoVersion EnvVar = "TRAVIS_GO_VERSION" -) - -// IsRunning attempts to determine whether this process is -// running on Travis-CI. This is done by checking ALL of the -// following env vars are set: -// -// CI=true -// TRAVIS=true -// -// Note: cannot just check CI. -func IsRunning() bool { - return Env(VarCI) == "true" && Env(VarTravis) == "true" -} - -// Env returns the value of a travis env variable. -func Env(v EnvVar) string { - return os.Getenv(string(v)) -} - -// JobId returns the travis JOB_ID of this build. -func JobId() string { - return Env(VarJobId) -} - -// JobNumber returns the travis JOB_NUMBER of this build. -func JobNumber() string { - return Env(VarJobNumber) -} diff --git a/testutil/ci/travis/travis_test.go b/testutil/ci/travis/travis_test.go deleted file mode 100644 index f7b9259518..0000000000 --- a/testutil/ci/travis/travis_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package travis - -import ( - "os" - "testing" -) - -func TestIsRunning(t *testing.T) { - tr := os.Getenv("TRAVIS") == "true" && os.Getenv("CI") == "true" - if tr != IsRunning() { - t.Error("IsRunning() does not match TRAVIS && CI env var check") - } -} diff --git a/testutil/gen.go b/testutil/gen.go deleted file mode 100644 index 246216fffd..0000000000 --- a/testutil/gen.go +++ /dev/null @@ -1,156 +0,0 @@ -package testutil - -import ( - "bytes" - "errors" - "fmt" - "io" - "sync" - "testing" - - u "github.com/ipfs/go-ipfs-util" - ci "github.com/ipfs/go-libp2p-crypto" - peer "github.com/ipfs/go-libp2p-peer" - - ma "github.com/jbenet/go-multiaddr" -) - -// ZeroLocalTCPAddress is the "zero" tcp local multiaddr. This means: -// /ip4/127.0.0.1/tcp/0 -var ZeroLocalTCPAddress ma.Multiaddr - -func init() { - // initialize ZeroLocalTCPAddress - maddr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/0") - if err != nil { - panic(err) - } - ZeroLocalTCPAddress = maddr -} - -func RandTestKeyPair(bits int) (ci.PrivKey, ci.PubKey, error) { - return ci.GenerateKeyPairWithReader(ci.RSA, bits, u.NewTimeSeededRand()) -} - -func SeededTestKeyPair(seed int64) (ci.PrivKey, ci.PubKey, error) { - return ci.GenerateKeyPairWithReader(ci.RSA, 512, u.NewSeededRand(seed)) -} - -// RandPeerID generates random "valid" peer IDs. it does not NEED to generate -// keys because it is as if we lost the key right away. fine to read randomness -// and hash it. to generate proper keys and corresponding PeerID, use: -// sk, pk, _ := testutil.RandKeyPair() -// id, _ := peer.IDFromPublicKey(pk) -func RandPeerID() (peer.ID, error) { - buf := make([]byte, 16) - if _, err := io.ReadFull(u.NewTimeSeededRand(), buf); err != nil { - return "", err - } - h := u.Hash(buf) - return peer.ID(h), nil -} - -func RandPeerIDFatal(t testing.TB) peer.ID { - p, err := RandPeerID() - if err != nil { - t.Fatal(err) - } - return p -} - -// RandLocalTCPAddress returns a random multiaddr. it suppresses errors -// for nice composability-- do check the address isn't nil. -// -// Note: for real network tests, use ZeroLocalTCPAddress so the kernel -// assigns an unused TCP port. otherwise you may get clashes. This -// function remains here so that p2p/net/mock (which does not touch the -// real network) can assign different addresses to peers. -func RandLocalTCPAddress() ma.Multiaddr { - - // chances are it will work out, but it **might** fail if the port is in use - // most ports above 10000 aren't in use by long running processes, so yay. - // (maybe there should be a range of "loopback" ports that are guaranteed - // to be open for the process, but naturally can only talk to self.) - - lastPort.Lock() - if lastPort.port == 0 { - lastPort.port = 10000 + SeededRand.Intn(50000) - } - port := lastPort.port - lastPort.port++ - lastPort.Unlock() - - addr := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", port) - maddr, _ := ma.NewMultiaddr(addr) - return maddr -} - -var lastPort = struct { - port int - sync.Mutex -}{} - -// PeerNetParams is a struct to bundle together the four things -// you need to run a connection with a peer: id, 2keys, and addr. -type PeerNetParams struct { - ID peer.ID - PrivKey ci.PrivKey - PubKey ci.PubKey - Addr ma.Multiaddr -} - -func (p *PeerNetParams) checkKeys() error { - if !p.ID.MatchesPrivateKey(p.PrivKey) { - return errors.New("p.ID does not match p.PrivKey") - } - - if !p.ID.MatchesPublicKey(p.PubKey) { - return errors.New("p.ID does not match p.PubKey") - } - - buf := new(bytes.Buffer) - buf.Write([]byte("hello world. this is me, I swear.")) - b := buf.Bytes() - - sig, err := p.PrivKey.Sign(b) - if err != nil { - return fmt.Errorf("sig signing failed: %s", err) - } - - sigok, err := p.PubKey.Verify(b, sig) - if err != nil { - return fmt.Errorf("sig verify failed: %s", err) - } - if !sigok { - return fmt.Errorf("sig verify failed: sig invalid") - } - - return nil // ok. move along. -} - -func RandPeerNetParamsOrFatal(t *testing.T) PeerNetParams { - p, err := RandPeerNetParams() - if err != nil { - t.Fatal(err) - return PeerNetParams{} // TODO return nil - } - return *p -} - -func RandPeerNetParams() (*PeerNetParams, error) { - var p PeerNetParams - var err error - p.Addr = ZeroLocalTCPAddress - p.PrivKey, p.PubKey, err = RandTestKeyPair(512) - if err != nil { - return nil, err - } - p.ID, err = peer.IDFromPublicKey(p.PubKey) - if err != nil { - return nil, err - } - if err := p.checkKeys(); err != nil { - return nil, err - } - return &p, nil -} diff --git a/testutil/identity.go b/testutil/identity.go deleted file mode 100644 index 72e37b5190..0000000000 --- a/testutil/identity.go +++ /dev/null @@ -1,55 +0,0 @@ -package testutil - -import ( - "testing" - - ci "github.com/ipfs/go-libp2p-crypto" - peer "github.com/ipfs/go-libp2p-peer" - ma "github.com/jbenet/go-multiaddr" -) - -type Identity interface { - Address() ma.Multiaddr - ID() peer.ID - PrivateKey() ci.PrivKey - PublicKey() ci.PubKey -} - -// TODO add a cheaper way to generate identities - -func RandIdentity() (Identity, error) { - p, err := RandPeerNetParams() - if err != nil { - return nil, err - } - return &identity{*p}, nil -} - -func RandIdentityOrFatal(t *testing.T) Identity { - p, err := RandPeerNetParams() - if err != nil { - t.Fatal(err) - } - return &identity{*p} -} - -// identity is a temporary shim to delay binding of PeerNetParams. -type identity struct { - PeerNetParams -} - -func (p *identity) ID() peer.ID { - return p.PeerNetParams.ID -} - -func (p *identity) Address() ma.Multiaddr { - return p.Addr -} - -func (p *identity) PrivateKey() ci.PrivKey { - return p.PrivKey -} - -func (p *identity) PublicKey() ci.PubKey { - return p.PubKey -} diff --git a/testutil/latency_config.go b/testutil/latency_config.go deleted file mode 100644 index 5628d9ed16..0000000000 --- a/testutil/latency_config.go +++ /dev/null @@ -1,48 +0,0 @@ -package testutil - -import "time" - -type LatencyConfig struct { - BlockstoreLatency time.Duration - NetworkLatency time.Duration - RoutingLatency time.Duration -} - -func (c LatencyConfig) AllInstantaneous() LatencyConfig { - // Could use a zero value but whatever. Consistency of interface - c.NetworkLatency = 0 - c.RoutingLatency = 0 - c.BlockstoreLatency = 0 - return c -} - -func (c LatencyConfig) NetworkNYtoSF() LatencyConfig { - c.NetworkLatency = 20 * time.Millisecond - return c -} - -func (c LatencyConfig) NetworkIntraDatacenter2014() LatencyConfig { - c.NetworkLatency = 250 * time.Microsecond - return c -} - -func (c LatencyConfig) BlockstoreFastSSD2014() LatencyConfig { - const iops = 100000 - c.BlockstoreLatency = (1 / iops) * time.Second - return c -} - -func (c LatencyConfig) BlockstoreSlowSSD2014() LatencyConfig { - c.BlockstoreLatency = 150 * time.Microsecond - return c -} - -func (c LatencyConfig) Blockstore7200RPM() LatencyConfig { - c.BlockstoreLatency = 8 * time.Millisecond - return c -} - -func (c LatencyConfig) RoutingSlow() LatencyConfig { - c.RoutingLatency = 200 * time.Millisecond - return c -} diff --git a/testutil/rand.go b/testutil/rand.go deleted file mode 100644 index 9630bc1448..0000000000 --- a/testutil/rand.go +++ /dev/null @@ -1,36 +0,0 @@ -package testutil - -import ( - "math/rand" - "sync" - "time" -) - -var SeededRand *rand.Rand - -func init() { - SeededRand = NewSeededRand(time.Now().UTC().UnixNano()) -} - -func NewSeededRand(seed int64) *rand.Rand { - src := rand.NewSource(seed) - return rand.New(&LockedRandSource{src: src}) -} - -type LockedRandSource struct { - lk sync.Mutex - src rand.Source -} - -func (r *LockedRandSource) Int63() (n int64) { - r.lk.Lock() - n = r.src.Int63() - r.lk.Unlock() - return -} - -func (r *LockedRandSource) Seed(seed int64) { - r.lk.Lock() - r.src.Seed(seed) - r.lk.Unlock() -}