Commit 51fd99e3 authored by Jeromy's avatar Jeromy
Browse files

extract from 0.4.0

parent 5a0162c7
......@@ -8,14 +8,14 @@ import (
"sync"
"time"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
nat "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/fd/go-nat"
goprocess "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
periodic "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/periodic"
notifier "github.com/ipfs/go-ipfs/thirdparty/notifier"
logging "github.com/ipfs/go-ipfs/vendor/go-log-v1.0.0"
ma "github.com/jbenet/go-multiaddr"
manet "github.com/jbenet/go-multiaddr-net"
nat "github.com/fd/go-nat"
goprocess "github.com/jbenet/goprocess"
periodic "github.com/jbenet/goprocess/periodic"
notifier "thirdparty/notifier"
logging "QmWRypnfEwrgH4k93KEHN5hng7VjKYkWmzDYRuTZeh2Mgh/go-log"
)
var (
......@@ -83,7 +83,7 @@ func (nat *NAT) Process() goprocess.Process {
}
// Notifier is an object that assists NAT in notifying listeners.
// It is implemented using github.com/ipfs/go-ipfs/thirdparty/notifier
// It is implemented using thirdparty/notifier
type Notifier struct {
n notifier.Notifier
}
......
......@@ -6,16 +6,15 @@ import (
"net"
"time"
msgio "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-msgio"
mpool "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-msgio/mpool"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
u "github.com/ipfs/go-ipfs/util"
logging "github.com/ipfs/go-ipfs/vendor/go-log-v1.0.0"
mpool "github.com/jbenet/go-msgio/mpool"
ma "github.com/jbenet/go-multiaddr"
manet "github.com/jbenet/go-multiaddr-net"
context "golang.org/x/net/context"
ic "github.com/ipfs/go-libp2p/p2p/crypto"
peer "github.com/ipfs/go-libp2p/p2p/peer"
lgbl "github.com/ipfs/go-libp2p/util/eventlog/loggables"
u "util"
lgbl "util/eventlog/loggables"
logging "QmWRypnfEwrgH4k93KEHN5hng7VjKYkWmzDYRuTZeh2Mgh/go-log"
)
var log = logging.Logger("conn")
......@@ -32,7 +31,6 @@ type singleConn struct {
local peer.ID
remote peer.ID
maconn manet.Conn
msgrw msgio.ReadWriteCloser
event io.Closer
}
......@@ -44,7 +42,6 @@ func newSingleConn(ctx context.Context, local, remote peer.ID, maconn manet.Conn
local: local,
remote: remote,
maconn: maconn,
msgrw: msgio.NewReadWriter(maconn),
event: log.EventBegin(ctx, "connLifetime", ml),
}
......@@ -62,7 +59,7 @@ func (c *singleConn) Close() error {
}()
// close underlying connection
return c.msgrw.Close()
return c.maconn.Close()
}
// ID is an identifier unique to this connection.
......@@ -123,31 +120,12 @@ func (c *singleConn) RemotePeer() peer.ID {
// Read reads data, net.Conn style
func (c *singleConn) Read(buf []byte) (int, error) {
return c.msgrw.Read(buf)
return c.maconn.Read(buf)
}
// Write writes data, net.Conn style
func (c *singleConn) Write(buf []byte) (int, error) {
return c.msgrw.Write(buf)
}
func (c *singleConn) NextMsgLen() (int, error) {
return c.msgrw.NextMsgLen()
}
// ReadMsg reads data, net.Conn style
func (c *singleConn) ReadMsg() ([]byte, error) {
return c.msgrw.ReadMsg()
}
// WriteMsg writes data, net.Conn style
func (c *singleConn) WriteMsg(buf []byte) error {
return c.msgrw.WriteMsg(buf)
}
// ReleaseMsg releases a buffer
func (c *singleConn) ReleaseMsg(m []byte) {
c.msgrw.ReleaseMsg(m)
return c.maconn.Write(buf)
}
// ID returns the ID of a given Conn.
......
......@@ -8,17 +8,25 @@ import (
"testing"
"time"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
travis "github.com/ipfs/go-ipfs/util/testutil/ci/travis"
msgio "github.com/jbenet/go-msgio"
context "golang.org/x/net/context"
travis "util/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 := c1.WriteMsg(m1); err != nil {
if err := mc1.WriteMsg(m1); err != nil {
t.Fatal(err)
}
m2, err := c2.ReadMsg()
m2, err := mc2.ReadMsg()
if err != nil {
t.Fatal(err)
}
......@@ -28,11 +36,14 @@ func testOneSendRecv(t *testing.T, c1, c2 Conn) {
}
func testNotOneSendRecv(t *testing.T, c1, c2 Conn) {
mc1 := msgioWrap(c1)
mc2 := msgioWrap(c2)
m1 := []byte("hello")
if err := c1.WriteMsg(m1); err == nil {
if err := mc1.WriteMsg(m1); err == nil {
t.Fatal("write should have failed", err)
}
_, err := c2.ReadMsg()
_, err := mc2.ReadMsg()
if err == nil {
t.Fatal("read should have failed", err)
}
......@@ -72,10 +83,13 @@ func TestCloseLeak(t *testing.T) {
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))
c1.WriteMsg(b1)
b2, err := c2.ReadMsg()
mc1.WriteMsg(b1)
b2, err := mc2.ReadMsg()
if err != nil {
panic(err)
}
......@@ -84,8 +98,8 @@ func TestCloseLeak(t *testing.T) {
}
b2 = []byte(fmt.Sprintf("boop%d", i))
c2.WriteMsg(b2)
b1, err = c1.ReadMsg()
mc2.WriteMsg(b2)
b1, err = mc1.ReadMsg()
if err != nil {
panic(err)
}
......@@ -114,9 +128,11 @@ func TestCloseLeak(t *testing.T) {
wg.Wait()
// done!
<-time.After(time.Millisecond * 150)
if runtime.NumGoroutine() > 20 {
// panic("uncomment me to debug")
t.Fatal("leaking goroutines:", runtime.NumGoroutine())
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)
}
}
......@@ -3,23 +3,32 @@ package conn
import (
"fmt"
"math/rand"
"net"
"strings"
"syscall"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
reuseport "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-reuseport"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
lgbl "github.com/ipfs/go-libp2p/util/eventlog/loggables"
ma "github.com/jbenet/go-multiaddr"
manet "github.com/jbenet/go-multiaddr-net"
context "golang.org/x/net/context"
lgbl "util/eventlog/loggables"
ci "github.com/ipfs/go-libp2p/p2p/crypto"
addrutil "github.com/ipfs/go-libp2p/p2p/net/swarm/addr"
transport "github.com/ipfs/go-libp2p/p2p/net/transport"
peer "github.com/ipfs/go-libp2p/p2p/peer"
)
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,
}
}
// String returns the string rep of d.
func (d *Dialer) String() string {
return fmt.Sprintf("<Dialer %s %s ...>", d.LocalPeer, d.LocalAddrs[0])
return fmt.Sprintf("<Dialer %s ...>", d.LocalPeer)
}
// Dial connects to a peer over a particular address
......@@ -95,112 +104,34 @@ func (d *Dialer) Dial(ctx context.Context, raddr ma.Multiaddr, remote peer.ID) (
return connOut, nil
}
// rawConnDial dials the underlying net.Conn + manet.Conns
func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote peer.ID) (manet.Conn, error) {
// before doing anything, check we're going to be able to dial.
// we may not support the given address.
if _, _, err := manet.DialArgs(raddr); err != nil {
return nil, err
}
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)
}
// get local addr to use.
laddr := pickLocalAddr(d.LocalAddrs, raddr)
logdial := lgbl.Dial("conn", d.LocalPeer, remote, laddr, raddr)
defer log.EventBegin(ctx, "connDialRawConn", logdial).Done()
// make a copy of the manet.Dialer, we may need to change its timeout.
madialer := d.Dialer
if laddr != nil && reuseportIsAvailable() {
// we're perhaps going to dial twice. half the timeout, so we can afford to.
// otherwise our context would expire right after the first dial.
madialer.Dialer.Timeout = (madialer.Dialer.Timeout / 2)
// dial using reuseport.Dialer, because we're probably reusing addrs.
// this is optimistic, as the reuseDial may fail to bind the port.
rpev := log.EventBegin(ctx, "connDialReusePort", logdial)
if nconn, retry, reuseErr := reuseDial(madialer.Dialer, laddr, raddr); reuseErr == nil {
// if it worked, wrap the raw net.Conn with our manet.Conn
logdial["reuseport"] = "success"
rpev.Done()
return manet.WrapNetConn(nconn)
} else if !retry {
// reuseDial is sure this is a legitimate dial failure, not a reuseport failure.
logdial["reuseport"] = "failure"
logdial["error"] = reuseErr
rpev.Done()
return nil, reuseErr
} else {
// this is a failure to reuse port. log it.
logdial["reuseport"] = "retry"
logdial["error"] = reuseErr
rpev.Done()
}
}
defer log.EventBegin(ctx, "connDialManet", logdial).Done()
return madialer.Dial(raddr)
func (d *Dialer) AddDialer(pd transport.Dialer) {
d.Dialers = append(d.Dialers, pd)
}
func reuseDial(dialer net.Dialer, laddr, raddr ma.Multiaddr) (conn net.Conn, retry bool, err error) {
if laddr == nil {
// if we're given no local address no sense in using reuseport to dial, dial out as usual.
return nil, true, reuseport.ErrReuseFailed
}
// give reuse.Dialer the manet.Dialer's Dialer.
// (wow, Dialer should've so been an interface...)
rd := reuseport.Dialer{dialer}
// get the local net.Addr manually
rd.D.LocalAddr, err = manet.ToNetAddr(laddr)
if err != nil {
return nil, true, err // something wrong with laddr. retry without.
}
// get the raddr dial args for rd.dial
network, netraddr, err := manet.DialArgs(raddr)
if err != nil {
return nil, true, err // something wrong with laddr. retry without.
// 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
}
}
// rd.Dial gets us a net.Conn with SO_REUSEPORT and SO_REUSEADDR set.
conn, err = rd.Dial(network, netraddr)
return conn, reuseErrShouldRetry(err), err // hey! it worked!
return nil
}
// reuseErrShouldRetry diagnoses whether to retry after a reuse error.
// if we failed to bind, we should retry. if bind worked and this is a
// real dial error (remote end didnt answer) then we should not retry.
func reuseErrShouldRetry(err error) bool {
if err == nil {
return false // hey, it worked! no need to retry.
}
// if it's a network timeout error, it's a legitimate failure.
if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
return false
// 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)
}
errno, ok := err.(syscall.Errno)
if !ok { // not an errno? who knows what this is. retry.
return true
sd := d.subDialerForAddr(raddr)
if sd == nil {
return nil, fmt.Errorf("no dialer for %s", raddr)
}
switch errno {
case syscall.EADDRINUSE, syscall.EADDRNOTAVAIL:
return true // failure to bind. retry.
case syscall.ECONNREFUSED:
return false // real dial error
default:
return true // optimistically default to retry.
}
return sd.Dial(raddr)
}
func pickLocalAddr(laddrs []ma.Multiaddr, raddr ma.Multiaddr) (laddr ma.Multiaddr) {
......
......@@ -8,9 +8,13 @@ import (
"testing"
"time"
tu "github.com/ipfs/go-ipfs/util/testutil"
ic "github.com/ipfs/go-libp2p/p2p/crypto"
transport "github.com/ipfs/go-libp2p/p2p/net/transport"
peer "github.com/ipfs/go-libp2p/p2p/peer"
tu "util/testutil"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
ma "github.com/jbenet/go-multiaddr"
context "golang.org/x/net/context"
)
func echoListen(ctx context.Context, listener Listener) {
......@@ -49,6 +53,25 @@ func setupSingleConn(t *testing.T, ctx context.Context) (a, b Conn, p1, p2 tu.Pe
return setupConn(t, ctx, false)
}
func Listen(ctx context.Context, addr ma.Multiaddr, local peer.ID, sk ic.PrivKey) (Listener, error) {
list, err := transport.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 := transport.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)
......@@ -71,6 +94,8 @@ func setupConn(t *testing.T, ctx context.Context, secure bool) (a, b Conn, p1, p
PrivateKey: key2,
}
d2.AddDialer(dialer(t, p2.Addr))
var c2 Conn
done := make(chan error)
......@@ -152,6 +177,7 @@ func testDialer(t *testing.T, secure bool) {
LocalPeer: p2.ID,
PrivateKey: key2,
}
d2.AddDialer(dialer(t, p2.Addr))
go echoListen(ctx, l1)
......@@ -161,10 +187,10 @@ func testDialer(t *testing.T, secure bool) {
}
// fmt.Println("sending")
c.WriteMsg([]byte("beep"))
c.WriteMsg([]byte("boop"))
out, err := c.ReadMsg()
mc := msgioWrap(c)
mc.WriteMsg([]byte("beep"))
mc.WriteMsg([]byte("boop"))
out, err := mc.ReadMsg()
if err != nil {
t.Fatal(err)
}
......@@ -175,7 +201,7 @@ func testDialer(t *testing.T, secure bool) {
t.Error("unexpected conn output", data)
}
out, err = c.ReadMsg()
out, err = mc.ReadMsg()
if err != nil {
t.Fatal(err)
}
......@@ -227,6 +253,7 @@ func testDialerCloseEarly(t *testing.T, secure bool) {
LocalPeer: p2.ID,
// PrivateKey: key2, -- 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)
......@@ -253,7 +280,7 @@ func testDialerCloseEarly(t *testing.T, secure bool) {
c, err := d2.Dial(ctx, p1.Addr, p1.ID)
if err != nil {
errs <- err
t.Fatal(err)
}
c.Close() // close it early.
......
......@@ -5,14 +5,13 @@ import (
"net"
"time"
key "github.com/ipfs/go-ipfs/blocks/key"
ic "github.com/ipfs/go-libp2p/p2p/crypto"
filter "github.com/ipfs/go-libp2p/p2p/net/filter"
transport "github.com/ipfs/go-libp2p/p2p/net/transport"
peer "github.com/ipfs/go-libp2p/p2p/peer"
msgio "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-msgio"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
ma "github.com/jbenet/go-multiaddr"
key "github.com/whyrusleeping/go-key"
)
// Map maps Keys (Peer.IDs) to Connections.
......@@ -46,30 +45,30 @@ type Conn interface {
SetReadDeadline(t time.Time) error
SetWriteDeadline(t time.Time) error
msgio.Reader
msgio.Writer
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 {
// Dialer is an optional manet.Dialer to use.
Dialer manet.Dialer
// LocalPeer is the identity of the local Peer.
LocalPeer peer.ID
// LocalAddrs is a set of local addresses to use.
LocalAddrs []ma.Multiaddr
//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 func(manet.Conn) manet.Conn
Wrapper WrapFunc
}
// Listener is an object that can accept connections. It matches net.Listener
......
......@@ -5,25 +5,24 @@ import (
"io"
"net"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
reuseport "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-reuseport"
tec "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-temp-err-catcher"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
goprocessctx "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
ma "github.com/jbenet/go-multiaddr"
tec "github.com/jbenet/go-temp-err-catcher"
"github.com/jbenet/goprocess"
goprocessctx "github.com/jbenet/goprocess/context"
context "golang.org/x/net/context"
ic "github.com/ipfs/go-libp2p/p2p/crypto"
filter "github.com/ipfs/go-libp2p/p2p/net/filter"
transport "github.com/ipfs/go-libp2p/p2p/net/transport"
peer "github.com/ipfs/go-libp2p/p2p/peer"
)
// ConnWrapper is any function that wraps a raw multiaddr connection
type ConnWrapper func(manet.Conn) manet.Conn
type ConnWrapper func(transport.Conn) transport.Conn
// listener is an object that can accept connections. It implements Listener
type listener struct {
manet.Listener
transport.Listener
local peer.ID // LocalPeer is the identity of the local Peer
privk ic.PrivKey // private key to use to initialize secure conns
......@@ -147,13 +146,7 @@ func (l *listener) Loggable() map[string]interface{} {
}
}
// Listen listens on the particular multiaddr, with given peer and peerstore.
func Listen(ctx context.Context, addr ma.Multiaddr, local peer.ID, sk ic.PrivKey) (Listener, error) {
ml, err := manetListen(addr)
if err != nil {
return nil, err
}
func WrapTransportListener(ctx context.Context, ml transport.Listener, local peer.ID, sk ic.PrivKey) (Listener, error) {
l := &listener{
Listener: ml,
local: local,
......@@ -175,23 +168,3 @@ type ListenerConnWrapper interface {
func (l *listener) SetConnWrapper(cw ConnWrapper) {
l.wrapper = cw
}
func manetListen(addr ma.Multiaddr) (manet.Listener, error) {
network, naddr, err := manet.DialArgs(addr)
if err != nil {
return nil, err
}
if reuseportIsAvailable() {
nl, err := reuseport.Listen(network, naddr)
if err == nil {
// hey, it worked!
return manet.WrapNetListener(nl)
}
// reuseport is available, but we failed to listen. log debug, and retry normally.
log.Debugf("reuseport available, but failed to listen: %s %s, %s", network, naddr, err)
}
// either reuseport not available, or it failed. try normally.
return manet.Listen(addr)
}
......@@ -5,8 +5,8 @@ import (
"net"
"time"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
ma "github.com/jbenet/go-multiaddr"
context "golang.org/x/net/context"
ic "github.com/ipfs/go-libp2p/p2p/crypto"
secio "github.com/ipfs/go-libp2p/p2p/crypto/secio"
......@@ -119,20 +119,6 @@ func (c *secureConn) Write(buf []byte) (int, error) {
return c.secure.ReadWriter().Write(buf)
}
func (c *secureConn) NextMsgLen() (int, error) {
return c.secure.ReadWriter().NextMsgLen()
}
// ReadMsg reads data, net.Conn style
func (c *secureConn) ReadMsg() ([]byte, error) {
return c.secure.ReadWriter().ReadMsg()
}
// WriteMsg writes data, net.Conn style
func (c *secureConn) WriteMsg(buf []byte) error {
return c.secure.ReadWriter().WriteMsg(buf)
}
// ReleaseMsg releases a buffer
func (c *secureConn) ReleaseMsg(m []byte) {
c.secure.ReadWriter().ReleaseMsg(m)
......
......@@ -7,10 +7,10 @@ import (
"testing"
"time"
travis "github.com/ipfs/go-ipfs/util/testutil/ci/travis"
ic "github.com/ipfs/go-libp2p/p2p/crypto"
travis "util/testutil/ci/travis"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
context "golang.org/x/net/context"
)
func upgradeToSecureConn(t *testing.T, ctx context.Context, sk ic.PrivKey, c Conn) (Conn, error) {
......@@ -105,7 +105,7 @@ func TestSecureCancelHandshake(t *testing.T) {
done := make(chan error)
go secureHandshake(t, ctx, p1.PrivKey, c1, done)
<-time.After(time.Millisecond)
time.Sleep(time.Millisecond)
cancel() // cancel ctx
go secureHandshake(t, ctx, p2.PrivKey, c2, done)
......@@ -145,13 +145,16 @@ func TestSecureCloseLeak(t *testing.T) {
}
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")
c1.WriteMsg(b1)
b2, err := c2.ReadMsg()
mc1.WriteMsg(b1)
b2, err := mc2.ReadMsg()
if err != nil {
panic(err)
}
......@@ -160,8 +163,8 @@ func TestSecureCloseLeak(t *testing.T) {
}
b2 = []byte("beep")
c2.WriteMsg(b2)
b1, err = c1.ReadMsg()
mc2.WriteMsg(b2)
b1, err = mc1.ReadMsg()
if err != nil {
panic(err)
}
......@@ -169,7 +172,7 @@ func TestSecureCloseLeak(t *testing.T) {
panic("bytes not equal")
}
<-time.After(time.Microsecond * 5)
time.Sleep(time.Microsecond * 5)
}
}
......@@ -196,13 +199,14 @@ func TestSecureCloseLeak(t *testing.T) {
}(c1, c2)
}
log.Debugf("Waiting...\n")
log.Debugf("Waiting...")
wg.Wait()
// done!
<-time.After(time.Millisecond * 150)
if runtime.NumGoroutine() > 20 {
time.Sleep(time.Millisecond * 150)
ngr := runtime.NumGoroutine()
if ngr > 25 {
// panic("uncomment me to debug")
t.Fatal("leaking goroutines:", runtime.NumGoroutine())
t.Fatal("leaking goroutines:", ngr)
}
}
......@@ -3,12 +3,14 @@ package filter
import (
"net"
"strings"
"sync"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
ma "github.com/jbenet/go-multiaddr"
manet "github.com/jbenet/go-multiaddr-net"
)
type Filters struct {
mu sync.RWMutex
filters map[string]*net.IPNet
}
......@@ -19,6 +21,8 @@ func NewFilters() *Filters {
}
func (fs *Filters) AddDialFilter(f *net.IPNet) {
fs.mu.Lock()
defer fs.mu.Unlock()
fs.filters[f.String()] = f
}
......@@ -31,6 +35,8 @@ func (f *Filters) AddrBlocked(a ma.Multiaddr) bool {
ipstr := strings.Split(addr, ":")[0]
ip := net.ParseIP(ipstr)
f.mu.RLock()
defer f.mu.RUnlock()
for _, ft := range f.filters {
if ft.Contains(ip) {
return true
......@@ -41,6 +47,8 @@ func (f *Filters) AddrBlocked(a ma.Multiaddr) bool {
func (f *Filters) Filters() []*net.IPNet {
var out []*net.IPNet
f.mu.RLock()
defer f.mu.RUnlock()
for _, ff := range f.filters {
out = append(out, ff)
}
......@@ -48,5 +56,7 @@ func (f *Filters) Filters() []*net.IPNet {
}
func (f *Filters) Remove(ff *net.IPNet) {
f.mu.Lock()
defer f.mu.Unlock()
delete(f.filters, ff.String())
}
......@@ -6,9 +6,9 @@ import (
conn "github.com/ipfs/go-libp2p/p2p/net/conn"
peer "github.com/ipfs/go-libp2p/p2p/peer"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
ma "github.com/jbenet/go-multiaddr"
"github.com/jbenet/goprocess"
context "golang.org/x/net/context"
)
// MessageSizeMax is a soft (recommended) maximum for network messages.
......
......@@ -14,7 +14,7 @@ import (
"io"
"time"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
ma "github.com/jbenet/go-multiaddr"
)
type Mocknet interface {
......
package mocknet
import (
logging "github.com/ipfs/go-ipfs/vendor/go-log-v1.0.0"
logging "QmWRypnfEwrgH4k93KEHN5hng7VjKYkWmzDYRuTZeh2Mgh/go-log"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
context "golang.org/x/net/context"
)
var log = logging.Logger("mocknet")
......
......@@ -8,7 +8,8 @@ import (
inet "github.com/ipfs/go-libp2p/p2p/net"
peer "github.com/ipfs/go-libp2p/p2p/peer"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
ma "github.com/jbenet/go-multiaddr"
process "github.com/jbenet/goprocess"
)
// conn represents one side's perspective of a
......@@ -28,11 +29,31 @@ type conn struct {
link *link
rconn *conn // counterpart
streams list.List
proc process.Process
sync.RWMutex
}
func newConn(ln, rn *peernet, l *link) *conn {
c := &conn{net: ln, link: l}
c.local = ln.peer
c.remote = rn.peer
c.localAddr = ln.ps.Addrs(ln.peer)[0]
c.remoteAddr = rn.ps.Addrs(rn.peer)[0]
c.localPrivKey = ln.ps.PrivKey(ln.peer)
c.remotePubKey = rn.ps.PubKey(rn.peer)
c.proc = process.WithTeardown(c.teardown)
return c
}
func (c *conn) Close() error {
return c.proc.Close()
}
func (c *conn) teardown() error {
for _, s := range c.allStreams() {
s.Close()
}
......
......@@ -33,22 +33,8 @@ func (l *link) newConnPair(dialer *peernet) (*conn, *conn) {
l.RLock()
defer l.RUnlock()
mkconn := func(ln, rn *peernet) *conn {
c := &conn{net: ln, link: l}
c.local = ln.peer
c.remote = rn.peer
c.localAddr = ln.ps.Addrs(ln.peer)[0]
c.remoteAddr = rn.ps.Addrs(rn.peer)[0]
c.localPrivKey = ln.ps.PrivKey(ln.peer)
c.remotePubKey = rn.ps.PubKey(rn.peer)
return c
}
c1 := mkconn(l.nets[0], l.nets[1])
c2 := mkconn(l.nets[1], l.nets[0])
c1 := newConn(l.nets[0], l.nets[1], l)
c2 := newConn(l.nets[1], l.nets[0], l)
c1.rconn = c2
c2.rconn = c1
......
......@@ -5,18 +5,18 @@ import (
"sort"
"sync"
testutil "github.com/ipfs/go-ipfs/util/testutil"
ic "github.com/ipfs/go-libp2p/p2p/crypto"
host "github.com/ipfs/go-libp2p/p2p/host"
bhost "github.com/ipfs/go-libp2p/p2p/host/basic"
inet "github.com/ipfs/go-libp2p/p2p/net"
peer "github.com/ipfs/go-libp2p/p2p/peer"
p2putil "github.com/ipfs/go-libp2p/p2p/test/util"
testutil "util/testutil"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
goprocessctx "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
ma "github.com/jbenet/go-multiaddr"
"github.com/jbenet/goprocess"
goprocessctx "github.com/jbenet/goprocess/context"
context "golang.org/x/net/context"
)
// mocknet implements mocknet.Mocknet
......@@ -34,7 +34,7 @@ type mocknet struct {
proc goprocess.Process // for Context closing
ctx context.Context
sync.RWMutex
sync.Mutex
}
func New(ctx context.Context) Mocknet {
......@@ -95,8 +95,8 @@ func (mn *mocknet) AddPeerWithPeerstore(p peer.ID, ps peer.Peerstore) (host.Host
}
func (mn *mocknet) Peers() []peer.ID {
mn.RLock()
defer mn.RUnlock()
mn.Lock()
defer mn.Unlock()
cp := make([]peer.ID, 0, len(mn.nets))
for _, n := range mn.nets {
......@@ -107,22 +107,22 @@ func (mn *mocknet) Peers() []peer.ID {
}
func (mn *mocknet) Host(pid peer.ID) host.Host {
mn.RLock()
mn.Lock()
host := mn.hosts[pid]
mn.RUnlock()
mn.Unlock()
return host
}
func (mn *mocknet) Net(pid peer.ID) inet.Network {
mn.RLock()
mn.Lock()
n := mn.nets[pid]
mn.RUnlock()
mn.Unlock()
return n
}
func (mn *mocknet) Hosts() []host.Host {
mn.RLock()
defer mn.RUnlock()
mn.Lock()
defer mn.Unlock()
cp := make([]host.Host, 0, len(mn.hosts))
for _, h := range mn.hosts {
......@@ -134,8 +134,8 @@ func (mn *mocknet) Hosts() []host.Host {
}
func (mn *mocknet) Nets() []inet.Network {
mn.RLock()
defer mn.RUnlock()
mn.Lock()
defer mn.Unlock()
cp := make([]inet.Network, 0, len(mn.nets))
for _, n := range mn.nets {
......@@ -148,8 +148,8 @@ func (mn *mocknet) Nets() []inet.Network {
// Links returns a copy of the internal link state map.
// (wow, much map. so data structure. how compose. ahhh pointer)
func (mn *mocknet) Links() LinkMap {
mn.RLock()
defer mn.RUnlock()
mn.Lock()
defer mn.Unlock()
links := map[string]map[string]map[Link]struct{}{}
for p1, lm := range mn.links {
......@@ -179,10 +179,10 @@ func (mn *mocknet) LinkAll() error {
}
func (mn *mocknet) LinkPeers(p1, p2 peer.ID) (Link, error) {
mn.RLock()
mn.Lock()
n1 := mn.nets[p1]
n2 := mn.nets[p2]
mn.RUnlock()
mn.Unlock()
if n1 == nil {
return nil, fmt.Errorf("network for p1 not in mocknet")
......@@ -211,11 +211,11 @@ func (mn *mocknet) validate(n inet.Network) (*peernet, error) {
}
func (mn *mocknet) LinkNets(n1, n2 inet.Network) (Link, error) {
mn.RLock()
mn.Lock()
n1r, err1 := mn.validate(n1)
n2r, err2 := mn.validate(n2)
ld := mn.linkDefaults
mn.RUnlock()
mn.Unlock()
if err1 != nil {
return nil, err1
......@@ -260,7 +260,7 @@ func (mn *mocknet) UnlinkNets(n1, n2 inet.Network) error {
}
// get from the links map. and lazily contruct.
func (mn *mocknet) linksMapGet(p1, p2 peer.ID) *map[*link]struct{} {
func (mn *mocknet) linksMapGet(p1, p2 peer.ID) map[*link]struct{} {
l1, found := mn.links[p1]
if !found {
......@@ -275,7 +275,7 @@ func (mn *mocknet) linksMapGet(p1, p2 peer.ID) *map[*link]struct{} {
l2 = l1[p2]
}
return &l2
return l2
}
func (mn *mocknet) addLink(l *link) {
......@@ -283,8 +283,8 @@ func (mn *mocknet) addLink(l *link) {
defer mn.Unlock()
n1, n2 := l.nets[0], l.nets[1]
(*mn.linksMapGet(n1.peer, n2.peer))[l] = struct{}{}
(*mn.linksMapGet(n2.peer, n1.peer))[l] = struct{}{}
mn.linksMapGet(n1.peer, n2.peer)[l] = struct{}{}
mn.linksMapGet(n2.peer, n1.peer)[l] = struct{}{}
}
func (mn *mocknet) removeLink(l *link) {
......@@ -292,8 +292,8 @@ func (mn *mocknet) removeLink(l *link) {
defer mn.Unlock()
n1, n2 := l.nets[0], l.nets[1]
delete(*mn.linksMapGet(n1.peer, n2.peer), l)
delete(*mn.linksMapGet(n2.peer, n1.peer), l)
delete(mn.linksMapGet(n1.peer, n2.peer), l)
delete(mn.linksMapGet(n2.peer, n1.peer), l)
}
func (mn *mocknet) ConnectAllButSelf() error {
......@@ -329,10 +329,10 @@ func (mn *mocknet) DisconnectNets(n1, n2 inet.Network) error {
}
func (mn *mocknet) LinksBetweenPeers(p1, p2 peer.ID) []Link {
mn.RLock()
defer mn.RUnlock()
mn.Lock()
defer mn.Unlock()
ls2 := *mn.linksMapGet(p1, p2)
ls2 := mn.linksMapGet(p1, p2)
cp := make([]Link, 0, len(ls2))
for l := range ls2 {
cp = append(cp, l)
......@@ -351,8 +351,8 @@ func (mn *mocknet) SetLinkDefaults(o LinkOptions) {
}
func (mn *mocknet) LinkDefaults() LinkOptions {
mn.RLock()
defer mn.RUnlock()
mn.Lock()
defer mn.Unlock()
return mn.linkDefaults
}
......
......@@ -4,8 +4,8 @@ import (
"testing"
"time"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
ma "github.com/jbenet/go-multiaddr"
context "golang.org/x/net/context"
inet "github.com/ipfs/go-libp2p/p2p/net"
peer "github.com/ipfs/go-libp2p/p2p/peer"
)
......
......@@ -8,10 +8,10 @@ import (
inet "github.com/ipfs/go-libp2p/p2p/net"
peer "github.com/ipfs/go-libp2p/p2p/peer"
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
goprocessctx "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess/context"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
ma "github.com/jbenet/go-multiaddr"
"github.com/jbenet/goprocess"
goprocessctx "github.com/jbenet/goprocess/context"
context "golang.org/x/net/context"
)
// peernet implements inet.Network
......
......@@ -5,7 +5,7 @@ import (
"io"
"time"
process "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/goprocess"
process "github.com/jbenet/goprocess"
inet "github.com/ipfs/go-libp2p/p2p/net"
)
......
......@@ -9,13 +9,13 @@ import (
"testing"
"time"
testutil "github.com/ipfs/go-ipfs/util/testutil"
inet "github.com/ipfs/go-libp2p/p2p/net"
peer "github.com/ipfs/go-libp2p/p2p/peer"
protocol "github.com/ipfs/go-libp2p/p2p/protocol"
testutil "util/testutil"
detectrace "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-detect-race"
context "github.com/ipfs/go-ipfs/Godeps/_workspace/src/golang.org/x/net/context"
detectrace "github.com/jbenet/go-detect-race"
context "golang.org/x/net/context"
)
func randPeer(t *testing.T) peer.ID {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment