Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-unixfs
Commits
334f9d21
Commit
334f9d21
authored
Jan 19, 2015
by
Juan Batiz-Benet
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
p2p/net/conn: use reuseport
parent
911a3c90
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
91 additions
and
27 deletions
+91
-27
p2p/net/conn/dial.go
p2p/net/conn/dial.go
+76
-26
p2p/net/conn/listen.go
p2p/net/conn/listen.go
+15
-1
No files found.
p2p/net/conn/dial.go
View file @
334f9d21
...
...
@@ -2,11 +2,14 @@ package conn
import
(
"fmt"
"math/rand"
"net"
"strings"
context
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
ma
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
manet
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
reuseport
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-reuseport"
peer
"github.com/jbenet/go-ipfs/p2p/peer"
debugerror
"github.com/jbenet/go-ipfs/util/debugerror"
...
...
@@ -22,32 +25,7 @@ func (d *Dialer) String() string {
// Example: d.DialAddr(ctx, peer.Addresses()[0], peer)
func
(
d
*
Dialer
)
Dial
(
ctx
context
.
Context
,
raddr
ma
.
Multiaddr
,
remote
peer
.
ID
)
(
Conn
,
error
)
{
_
,
_
,
err
:=
manet
.
DialArgs
(
raddr
)
if
err
!=
nil
{
return
nil
,
err
}
if
strings
.
HasPrefix
(
raddr
.
String
(),
"/ip4/0.0.0.0"
)
{
return
nil
,
debugerror
.
Errorf
(
"Attempted to connect to zero address: %s"
,
raddr
)
}
if
len
(
d
.
LocalAddrs
)
>
0
{
laddrs
:=
manet
.
AddrMatch
(
raddr
,
d
.
LocalAddrs
)
if
len
(
laddrs
)
<
1
{
return
nil
,
debugerror
.
Errorf
(
"No local address matches %s %s"
,
raddr
,
d
.
LocalAddrs
)
}
// 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.
// laddr := laddrs[rand.Intn(len(laddrs))]
// TODO: try to get reusing addr/ports to work.
// d.Dialer.LocalAddr = laddr
}
log
.
Debugf
(
"%s dialing %s %s"
,
d
.
LocalPeer
,
remote
,
raddr
)
maconn
,
err
:=
d
.
Dialer
.
Dial
(
raddr
)
maconn
,
err
:=
d
.
rawConnDial
(
ctx
,
raddr
,
remote
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -92,6 +70,78 @@ func (d *Dialer) Dial(ctx context.Context, raddr ma.Multiaddr, remote peer.ID) (
return
connOut
,
errOut
}
// 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.
_
,
_
,
err
:=
manet
.
DialArgs
(
raddr
)
if
err
!=
nil
{
return
nil
,
err
}
if
strings
.
HasPrefix
(
raddr
.
String
(),
"/ip4/0.0.0.0"
)
{
return
nil
,
debugerror
.
Errorf
(
"Attempted to connect to zero address: %s"
,
raddr
)
}
// get local addr to use.
laddr
:=
pickLocalAddr
(
d
.
LocalAddrs
,
raddr
)
log
.
Debugf
(
"%s dialing %s -- %s --> %s"
,
d
.
LocalPeer
,
remote
,
laddr
,
raddr
)
if
laddr
!=
nil
{
// dial using reuseport.Dialer, because we're probably reusing addrs.
// this is optimistic, as the reuseDial may fail to bind the port.
log
.
Debugf
(
"trying to reuse: %s"
,
laddr
)
if
nconn
,
err
:=
d
.
reuseDial
(
laddr
,
raddr
);
err
==
nil
{
// if it worked, wrap the raw net.Conn with our manet.Conn
log
.
Debugf
(
"reuse worked! %s %s %s"
,
laddr
,
nconn
.
RemoteAddr
(),
nconn
)
return
manet
.
WrapNetConn
(
nconn
)
}
// if not, we fall back to regular Dial without a local addr specified.
}
// no local addr, or failed to reuse. just dial straight with a new port.
return
d
.
Dialer
.
Dial
(
raddr
)
}
func
(
d
*
Dialer
)
reuseDial
(
laddr
,
raddr
ma
.
Multiaddr
)
(
net
.
Conn
,
error
)
{
// give reuse.Dialer the manet.Dialer's Dialer.
// (wow, Dialer should've so been an interface...)
rd
:=
reuseport
.
Dialer
{
d
.
Dialer
.
Dialer
}
// get the local net.Addr manually
var
err
error
rd
.
D
.
LocalAddr
,
err
=
manet
.
ToNetAddr
(
laddr
)
if
err
!=
nil
{
return
nil
,
err
}
// get the raddr dial args for rd.dial
network
,
netraddr
,
err
:=
manet
.
DialArgs
(
raddr
)
if
err
!=
nil
{
return
nil
,
err
}
// rd.Dial gets us a net.Conn with SO_REUSEPORT and SO_REUSEADDR set.
return
rd
.
Dial
(
network
,
netraddr
)
}
func
pickLocalAddr
(
laddrs
[]
ma
.
Multiaddr
,
raddr
ma
.
Multiaddr
)
(
laddr
ma
.
Multiaddr
)
{
if
len
(
laddrs
)
<
1
{
return
nil
}
laddrs
=
manet
.
AddrMatch
(
raddr
,
laddrs
)
if
len
(
laddrs
)
<
1
{
return
nil
}
// 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
()
...
...
p2p/net/conn/listen.go
View file @
334f9d21
...
...
@@ -9,7 +9,9 @@ import (
ctxgroup
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
ma
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
manet
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
reuseport
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-reuseport"
tec
"github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-temp-err-catcher"
ic
"github.com/jbenet/go-ipfs/p2p/crypto"
peer
"github.com/jbenet/go-ipfs/p2p/peer"
)
...
...
@@ -123,11 +125,23 @@ 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
:=
manet
.
Listen
(
addr
)
network
,
naddr
,
err
:=
manet
.
DialArgs
(
addr
)
if
err
!=
nil
{
return
nil
,
err
}
// _ := reuseport.Listen
// ml, err := manet.Listen(addr)
nl
,
err
:=
reuseport
.
Listen
(
network
,
naddr
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"Failed to listen on %s: %s"
,
addr
,
err
)
}
ml
,
err
:=
manet
.
WrapNetListener
(
nl
)
if
err
!=
nil
{
return
nil
,
err
}
l
:=
&
listener
{
Listener
:
ml
,
local
:
local
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment