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
p2p
go-p2p-swarm
Commits
34b2b471
Unverified
Commit
34b2b471
authored
May 15, 2020
by
Aarsh Shah
Committed by
GitHub
May 15, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
implement connection gating support: intercept peer, address dials, upgraded conns (#201)
parent
5c7c5897
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
263 additions
and
110 deletions
+263
-110
addrs.go
addrs.go
+2
-2
go.mod
go.mod
+6
-6
go.sum
go.sum
+15
-4
swarm.go
swarm.go
+51
-36
swarm_dial.go
swarm_dial.go
+14
-3
swarm_listen.go
swarm_listen.go
+1
-0
swarm_test.go
swarm_test.go
+96
-50
testing/testing.go
testing/testing.go
+78
-9
No files found.
addrs.go
View file @
34b2b471
package
swarm
import
(
ma
filter
"github.com/
libp2p/go-maddr-filte
r"
ma
"github.com/
multiformats/go-multiadd
r"
mamask
"github.com/whyrusleeping/multiaddr-filter"
)
// http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
var
lowTimeoutFilters
=
ma
filter
.
NewFilters
()
var
lowTimeoutFilters
=
ma
.
NewFilters
()
func
init
()
{
for
_
,
p
:=
range
[]
string
{
...
...
go.mod
View file @
34b2b471
...
...
@@ -5,19 +5,19 @@ require (
github.com/jbenet/goprocess
v0.1.4
github.com/libp2p/go-addr-util
v0.0.2
github.com/libp2p/go-conn-security-multistream
v0.2.0
github.com/libp2p/go-libp2p-core
v0.5.
2
github.com/libp2p/go-libp2p-core
v0.5.
5
github.com/libp2p/go-libp2p-loggables
v0.1.0
github.com/libp2p/go-libp2p-peerstore
v0.2.
3
github.com/libp2p/go-libp2p-peerstore
v0.2.
4
github.com/libp2p/go-libp2p-secio
v0.2.2
github.com/libp2p/go-libp2p-testing
v0.1.1
github.com/libp2p/go-libp2p-transport-upgrader
v0.
2
.0
github.com/libp2p/go-libp2p-transport-upgrader
v0.
3
.0
github.com/libp2p/go-libp2p-yamux
v0.2.7
github.com/libp2p/go-maddr-filter
v0.0.5
github.com/libp2p/go-stream-muxer-multistream
v0.3.0
github.com/libp2p/go-tcp-transport
v0.2.0
github.com/multiformats/go-multiaddr
v0.2.
1
github.com/multiformats/go-multiaddr
v0.2.
2
github.com/multiformats/go-multiaddr-fmt
v0.1.0
github.com/multiformats/go-multiaddr-net
v0.1.4
github.com/multiformats/go-multiaddr-net
v0.1.5
github.com/stretchr/testify
v1.4.0
github.com/whyrusleeping/multiaddr-filter
v0.0.0-20160516205228-e903e4adabd7
golang.org/x/crypto
v0.0.0-20191011191535-87dc89f01550 // indirect
)
...
...
go.sum
View file @
34b2b471
...
...
@@ -95,6 +95,8 @@ github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscw
github.com/jbenet/go-cienv
v0.1.0/go.mod h1:
TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
github.com/jbenet/go-temp-err-catcher
v0.0.0-20150120210811-aac704a3f4f2 h1:
vhC1OXXiT9R2pczegwz6moDvuRpggaroAXhPIseh57A=
github.com/jbenet/go-temp-err-catcher
v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:
8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs=
github.com/jbenet/go-temp-err-catcher
v0.1.0 h1:
zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
github.com/jbenet/go-temp-err-catcher
v0.1.0/go.mod h1:
0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
github.com/jbenet/goprocess
v0.0.0-20160826012719-b497e2f366b8/go.mod h1:
Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
github.com/jbenet/goprocess
v0.1.3 h1:
YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr10=
github.com/jbenet/goprocess
v0.1.3/go.mod h1:
5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
...
...
@@ -137,16 +139,17 @@ github.com/libp2p/go-libp2p-core v0.5.0 h1:FBQ1fpq2Fo/ClyjojVJ5AKXlKhvNc/B6U0O+7
github.com/libp2p/go-libp2p-core
v0.5.0/go.mod h1:
49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0=
github.com/libp2p/go-libp2p-core
v0.5.1 h1:
6Cu7WljPQtGY2krBlMoD8L/zH3tMUsCbqNFH7cZwCoI=
github.com/libp2p/go-libp2p-core
v0.5.1/go.mod h1:
uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y=
github.com/libp2p/go-libp2p-core
v0.5.2 h1:
hevsCcdLiazurKBoeNn64aPYTVOPdY4phaEGeLtHOAs=
github.com/libp2p/go-libp2p-core
v0.5.2/go.mod h1:
uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y=
github.com/libp2p/go-libp2p-core
v0.5.4/go.mod h1:
uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y=
github.com/libp2p/go-libp2p-core
v0.5.5 h1:
/yiFUZDoBWqvpWeHHJ1iA8SOs5obT1/+UdNfckwD57M=
github.com/libp2p/go-libp2p-core
v0.5.5/go.mod h1:
vj3awlOr9+GMZJFH9s4mpt9RHHgGqeHCopzbYKZdRjM=
github.com/libp2p/go-libp2p-loggables
v0.1.0 h1:
h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8=
github.com/libp2p/go-libp2p-loggables
v0.1.0/go.mod h1:
EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90=
github.com/libp2p/go-libp2p-mplex
v0.2.1 h1:
E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8iGvirYI=
github.com/libp2p/go-libp2p-mplex
v0.2.1/go.mod h1:
SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE=
github.com/libp2p/go-libp2p-mplex
v0.2.3 h1:
2zijwaJvpdesST2MXpI5w9wWFRgYtMcpRX7rrw0jmOo=
github.com/libp2p/go-libp2p-mplex
v0.2.3/go.mod h1:
CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek=
github.com/libp2p/go-libp2p-peerstore
v0.2.
3
h1:
MofRq2l3c15vQpEygTetV+zRRrncz+ktiXW7H2EKoEQ
=
github.com/libp2p/go-libp2p-peerstore
v0.2.
3
/go.mod h1:
K8ljLdFn590GMttg/luh4caB/3g0vKuY01psze0upRw
=
github.com/libp2p/go-libp2p-peerstore
v0.2.
4
h1:
jU9S4jYN30kdzTpDAR7SlHUD+meDUjTODh4waLWF1ws
=
github.com/libp2p/go-libp2p-peerstore
v0.2.
4
/go.mod h1:
ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s
=
github.com/libp2p/go-libp2p-pnet
v0.2.0 h1:
J6htxttBipJujEjz1y0a5+eYoiPcFHhSYHH6na5f0/k=
github.com/libp2p/go-libp2p-pnet
v0.2.0/go.mod h1:
Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA=
github.com/libp2p/go-libp2p-secio
v0.2.2 h1:
rLLPvShPQAcY6eNurKNZq3eZjPWfU9kXF2eI9jIYdrg=
...
...
@@ -156,6 +159,8 @@ github.com/libp2p/go-libp2p-testing v0.1.1 h1:U03z3HnGI7Ni8Xx6ONVZvUFOAzWYmolWf5
github.com/libp2p/go-libp2p-testing
v0.1.1/go.mod h1:
xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0=
github.com/libp2p/go-libp2p-transport-upgrader
v0.2.0 h1:
5EhPgQhXZNyfL22ERZTUoVp9UVVbNowWNVtELQaKCHk=
github.com/libp2p/go-libp2p-transport-upgrader
v0.2.0/go.mod h1:
mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns=
github.com/libp2p/go-libp2p-transport-upgrader
v0.3.0 h1:
q3ULhsknEQ34eVDhv4YwKS8iet69ffs9+Fir6a7weN4=
github.com/libp2p/go-libp2p-transport-upgrader
v0.3.0/go.mod h1:
i+SKzbRnvXdVbU3D1dwydnTmKRPXiAR/fyvi1dXuL4o=
github.com/libp2p/go-libp2p-yamux
v0.2.7 h1:
vzKu0NVtxvEIDGCv6mjKRcK0gipSgaXmJZ6jFv0d/dk=
github.com/libp2p/go-libp2p-yamux
v0.2.7/go.mod h1:
X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhLEn0XhIoZ5viCwU=
github.com/libp2p/go-maddr-filter
v0.0.5 h1:
CW3AgbMO6vUvT4kf87y4N+0P8KUl2aqLYhrGyDUbLSg=
...
...
@@ -170,6 +175,8 @@ github.com/libp2p/go-netroute v0.1.2 h1:UHhB35chwgvcRI392znJA3RCBtZ3MpE3ahNCN5MR
github.com/libp2p/go-netroute
v0.1.2/go.mod h1:
jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk=
github.com/libp2p/go-openssl
v0.0.4 h1:
d27YZvLoTyMhIN4njrkr8zMDOM4lfpHIp6A+TK9fovg=
github.com/libp2p/go-openssl
v0.0.4/go.mod h1:
unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-openssl
v0.0.5 h1:
pQkejVhF0xp08D4CQUcw8t+BFJeXowja6RVcb5p++EA=
github.com/libp2p/go-openssl
v0.0.5/go.mod h1:
unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
github.com/libp2p/go-reuseport
v0.0.1 h1:
7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw=
github.com/libp2p/go-reuseport
v0.0.1/go.mod h1:
jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA=
github.com/libp2p/go-reuseport-transport
v0.0.3 h1:
zzOeXnTooCkRvoH+bSXEfXhn76+LAiwoneM0gnXjF2M=
...
...
@@ -222,6 +229,8 @@ github.com/multiformats/go-multiaddr v0.2.0 h1:lR52sFwcTCuQb6bTfnXF6zA2XfyYvyd+5
github.com/multiformats/go-multiaddr
v0.2.0/go.mod h1:
0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
github.com/multiformats/go-multiaddr
v0.2.1 h1:
SgG/cw5vqyB5QQe5FPe2TqggU9WtrA9X4nZw7LlVqOI=
github.com/multiformats/go-multiaddr
v0.2.1/go.mod h1:
s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE=
github.com/multiformats/go-multiaddr
v0.2.2 h1:
XZLDTszBIJe6m0zF6ITBrEcZR73OPUhCBBS9rYAuUzI=
github.com/multiformats/go-multiaddr
v0.2.2/go.mod h1:
NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y=
github.com/multiformats/go-multiaddr-fmt
v0.1.0 h1:
WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
github.com/multiformats/go-multiaddr-fmt
v0.1.0/go.mod h1:
hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
github.com/multiformats/go-multiaddr-net
v0.1.2 h1:
P7zcBH9FRETdPkDrylcXVjQLQ2t1JQtNItZULWNWgeg=
...
...
@@ -230,6 +239,8 @@ github.com/multiformats/go-multiaddr-net v0.1.3 h1:q/IYAvoPKuRzGeERn3uacWgm0LIWk
github.com/multiformats/go-multiaddr-net
v0.1.3/go.mod h1:
ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA=
github.com/multiformats/go-multiaddr-net
v0.1.4 h1:
g6gwydsfADqFvrHoMkS0n9Ok9CG6F7ytOH/bJDkhIOY=
github.com/multiformats/go-multiaddr-net
v0.1.4/go.mod h1:
ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA=
github.com/multiformats/go-multiaddr-net
v0.1.5 h1:
QoRKvu0xHN1FCFJcMQLbG/yQE2z441L5urvG3+qyz7g=
github.com/multiformats/go-multiaddr-net
v0.1.5/go.mod h1:
ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA=
github.com/multiformats/go-multibase
v0.0.1 h1:
PN9/v21eLywrFWdFNsFKaU04kLJzuYzmrJR+ubhT9qA=
github.com/multiformats/go-multibase
v0.0.1/go.mod h1:
bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
github.com/multiformats/go-multihash
v0.0.1/go.mod h1:
w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
...
...
swarm.go
View file @
34b2b471
...
...
@@ -9,6 +9,7 @@ import (
"sync/atomic"
"time"
"github.com/libp2p/go-libp2p-core/connmgr"
"github.com/libp2p/go-libp2p-core/metrics"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
...
...
@@ -19,9 +20,7 @@ import (
"github.com/jbenet/goprocess"
goprocessctx
"github.com/jbenet/goprocess/context"
filter
"github.com/libp2p/go-maddr-filter"
ma
"github.com/multiformats/go-multiaddr"
mafilter
"github.com/whyrusleeping/multiaddr-filter"
)
// DialTimeoutLocal is the maximum duration a Dial to local network address
...
...
@@ -87,22 +86,24 @@ type Swarm struct {
dsync
*
DialSync
backf
DialBackoff
limiter
*
dialLimiter
// filters for addresses that shouldnt be dialed (or accepted)
Filters
*
filter
.
Filters
gater
connmgr
.
ConnectionGater
proc
goprocess
.
Process
ctx
context
.
Context
bwc
metrics
.
Reporter
}
// NewSwarm constructs a Swarm
func
NewSwarm
(
ctx
context
.
Context
,
local
peer
.
ID
,
peers
peerstore
.
Peerstore
,
bwc
metrics
.
Reporter
)
*
Swarm
{
// NewSwarm constructs a Swarm.
//
// NOTE: go-libp2p will be moving to dependency injection soon. The variadic
// `extra` interface{} parameter facilitates the future migration. Supported
// elements are:
// - connmgr.ConnectionGater
func
NewSwarm
(
ctx
context
.
Context
,
local
peer
.
ID
,
peers
peerstore
.
Peerstore
,
bwc
metrics
.
Reporter
,
extra
...
interface
{})
*
Swarm
{
s
:=
&
Swarm
{
local
:
local
,
peers
:
peers
,
bwc
:
bwc
,
Filters
:
filter
.
NewFilters
(),
local
:
local
,
peers
:
peers
,
bwc
:
bwc
,
}
s
.
conns
.
m
=
make
(
map
[
peer
.
ID
][]
*
Conn
)
...
...
@@ -110,6 +111,13 @@ func NewSwarm(ctx context.Context, local peer.ID, peers peerstore.Peerstore, bwc
s
.
transports
.
m
=
make
(
map
[
int
]
transport
.
Transport
)
s
.
notifs
.
m
=
make
(
map
[
network
.
Notifiee
]
struct
{})
for
_
,
i
:=
range
extra
{
switch
v
:=
i
.
(
type
)
{
case
connmgr
.
ConnectionGater
:
s
.
gater
=
v
}
}
s
.
dsync
=
NewDialSync
(
s
.
doDial
)
s
.
limiter
=
newDialLimiter
(
s
.
dialAddr
)
s
.
proc
=
goprocessctx
.
WithContext
(
ctx
)
...
...
@@ -168,33 +176,46 @@ func (s *Swarm) teardown() error {
return
nil
}
// AddAddrFilter adds a multiaddr filter to the set of filters the swarm will use to determine which
// addresses not to dial to.
func
(
s
*
Swarm
)
AddAddrFilter
(
f
string
)
error
{
m
,
err
:=
mafilter
.
NewMask
(
f
)
if
err
!=
nil
{
return
err
}
s
.
Filters
.
AddDialFilter
(
m
)
return
nil
}
// Process returns the Process of the swarm
func
(
s
*
Swarm
)
Process
()
goprocess
.
Process
{
return
s
.
proc
}
func
(
s
*
Swarm
)
addConn
(
tc
transport
.
CapableConn
,
dir
network
.
Direction
)
(
*
Conn
,
error
)
{
// The underlying transport (or the dialer) *should* filter it's own
// connections but we should double check anyways.
raddr
:=
tc
.
RemoteMultiaddr
()
if
s
.
Filters
.
AddrBlocked
(
raddr
)
{
tc
.
Close
()
return
nil
,
ErrAddrFiltered
var
(
p
=
tc
.
RemotePeer
()
addr
=
tc
.
RemoteMultiaddr
()
)
if
s
.
gater
!=
nil
{
if
allow
:=
s
.
gater
.
InterceptAddrDial
(
p
,
addr
);
!
allow
{
err
:=
tc
.
Close
()
if
err
!=
nil
{
log
.
Warnf
(
"failed to close connection with peer %s and addr %s; err: %s"
,
p
.
Pretty
(),
addr
,
err
)
}
return
nil
,
ErrAddrFiltered
}
}
p
:=
tc
.
RemotePeer
()
stat
:=
network
.
Stat
{
Direction
:
dir
}
c
:=
&
Conn
{
conn
:
tc
,
swarm
:
s
,
stat
:
stat
,
}
// we ONLY check upgraded connections here so we can send them a Disconnect message.
// If we do this in the Upgrader, we will not be able to do this.
if
s
.
gater
!=
nil
{
if
allow
,
_
:=
s
.
gater
.
InterceptUpgraded
(
c
);
!
allow
{
// TODO Send disconnect with reason here
err
:=
tc
.
Close
()
if
err
!=
nil
{
log
.
Warnf
(
"failed to close connection with peer %s and addr %s; err: %s"
,
p
.
Pretty
(),
addr
,
err
)
}
return
nil
,
ErrGaterDisallowedConnection
}
}
// Add the public key.
if
pk
:=
tc
.
RemotePublicKey
();
pk
!=
nil
{
...
...
@@ -214,12 +235,6 @@ func (s *Swarm) addConn(tc transport.CapableConn, dir network.Direction) (*Conn,
}
// Wrap and register the connection.
stat
:=
network
.
Stat
{
Direction
:
dir
}
c
:=
&
Conn
{
conn
:
tc
,
swarm
:
s
,
stat
:
stat
,
}
c
.
streams
.
m
=
make
(
map
[
*
Stream
]
struct
{})
s
.
conns
.
m
[
p
]
=
append
(
s
.
conns
.
m
[
p
],
c
)
...
...
swarm_dial.go
View file @
34b2b471
...
...
@@ -50,6 +50,10 @@ var (
// ErrNoGoodAddresses is returned when we find addresses for a peer but
// can't use any of them.
ErrNoGoodAddresses
=
errors
.
New
(
"no good addresses"
)
// ErrGaterDisallowedConnection is returned when the gater prevents us from
// forming a connection with a peer.
ErrGaterDisallowedConnection
=
errors
.
New
(
"gater disallows connection to peer"
)
)
// DialAttempts governs how many times a goroutine will try to dial a given peer.
...
...
@@ -218,6 +222,11 @@ func (db *DialBackoff) cleanup() {
// This allows us to use various transport protocols, do NAT traversal/relay,
// etc. to achieve connection.
func
(
s
*
Swarm
)
DialPeer
(
ctx
context
.
Context
,
p
peer
.
ID
)
(
network
.
Conn
,
error
)
{
if
s
.
gater
!=
nil
&&
!
s
.
gater
.
InterceptPeerDial
(
p
)
{
log
.
Debugf
(
"gater disallowed outbound connection to peer %s"
,
p
.
Pretty
())
return
nil
,
&
DialError
{
Peer
:
p
,
Cause
:
ErrGaterDisallowedConnection
}
}
return
s
.
dialPeer
(
ctx
,
p
)
}
...
...
@@ -339,7 +348,7 @@ func (s *Swarm) dial(ctx context.Context, p peer.ID) (*Conn, error) {
if
len
(
peerAddrs
)
==
0
{
return
nil
,
&
DialError
{
Peer
:
p
,
Cause
:
ErrNoAddresses
}
}
goodAddrs
:=
s
.
filterKnownUndialables
(
peerAddrs
)
goodAddrs
:=
s
.
filterKnownUndialables
(
p
,
peerAddrs
)
if
len
(
goodAddrs
)
==
0
{
return
nil
,
&
DialError
{
Peer
:
p
,
Cause
:
ErrNoGoodAddresses
}
}
...
...
@@ -393,7 +402,7 @@ func (s *Swarm) dial(ctx context.Context, p peer.ID) (*Conn, error) {
// IPv6 link-local addresses, addresses without a dial-capable transport,
// and addresses that we know to be our own.
// This is an optimization to avoid wasting time on dials that we know are going to fail.
func
(
s
*
Swarm
)
filterKnownUndialables
(
addrs
[]
ma
.
Multiaddr
)
[]
ma
.
Multiaddr
{
func
(
s
*
Swarm
)
filterKnownUndialables
(
p
peer
.
ID
,
addrs
[]
ma
.
Multiaddr
)
[]
ma
.
Multiaddr
{
lisAddrs
,
_
:=
s
.
InterfaceListenAddresses
()
var
ourAddrs
[]
ma
.
Multiaddr
for
_
,
addr
:=
range
lisAddrs
{
...
...
@@ -409,7 +418,9 @@ func (s *Swarm) filterKnownUndialables(addrs []ma.Multiaddr) []ma.Multiaddr {
s
.
canDial
,
// TODO: Consider allowing link-local addresses
addrutil
.
AddrOverNonLocalIP
,
addrutil
.
FilterNeg
(
s
.
Filters
.
AddrBlocked
),
func
(
addr
ma
.
Multiaddr
)
bool
{
return
s
.
gater
==
nil
||
s
.
gater
.
InterceptAddrDial
(
p
,
addr
)
},
)
}
...
...
swarm_listen.go
View file @
34b2b471
...
...
@@ -89,6 +89,7 @@ func (s *Swarm) AddListenAddr(a ma.Multiaddr) error {
}
return
}
log
.
Debugf
(
"swarm listener accepted connection: %s"
,
c
)
s
.
refs
.
Add
(
1
)
go
func
()
{
...
...
swarm_test.go
View file @
34b2b471
...
...
@@ -5,20 +5,21 @@ import (
"context"
"fmt"
"io"
"net"
"sync"
"testing"
"time"
logging
"github.com/
ipfs/go-log
"
"github.com/
libp2p/go-libp2p-core/control
"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/peerstore"
ma
"github.com/multiformats/go-multiaddr"
.
"github.com/libp2p/go-libp2p-swarm"
.
"github.com/libp2p/go-libp2p-swarm/testing"
logging
"github.com/ipfs/go-log"
ma
"github.com/multiformats/go-multiaddr"
"github.com/stretchr/testify/require"
)
var
log
=
logging
.
Logger
(
"swarm_test"
)
...
...
@@ -280,60 +281,105 @@ func TestConnHandler(t *testing.T) {
}
}
func
Test
AddrBlock
ing
(
t
*
testing
.
T
)
{
func
Test
ConnectionGat
ing
(
t
*
testing
.
T
)
{
ctx
:=
context
.
Background
()
swarms
:=
makeSwarms
(
ctx
,
t
,
2
)
swarms
[
0
]
.
SetConnHandler
(
func
(
conn
network
.
Conn
)
{
t
.
Errorf
(
"no connections should happen! -- %s"
,
conn
)
})
_
,
block
,
err
:=
net
.
ParseCIDR
(
"127.0.0.1/8"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
swarms
[
1
]
.
Filters
.
AddDialFilter
(
block
)
swarms
[
1
]
.
Peerstore
()
.
AddAddr
(
swarms
[
0
]
.
LocalPeer
(),
swarms
[
0
]
.
ListenAddresses
()[
0
],
peerstore
.
PermanentAddrTTL
)
_
,
err
=
swarms
[
1
]
.
DialPeer
(
ctx
,
swarms
[
0
]
.
LocalPeer
())
if
err
==
nil
{
t
.
Fatal
(
"dial should have failed"
)
}
swarms
[
0
]
.
Peerstore
()
.
AddAddr
(
swarms
[
1
]
.
LocalPeer
(),
swarms
[
1
]
.
ListenAddresses
()[
0
],
peerstore
.
PermanentAddrTTL
)
_
,
err
=
swarms
[
0
]
.
DialPeer
(
ctx
,
swarms
[
1
]
.
LocalPeer
())
if
err
==
nil
{
t
.
Fatal
(
"dial should have failed"
)
tcs
:=
map
[
string
]
struct
{
p1Gater
func
(
gater
*
MockConnectionGater
)
*
MockConnectionGater
p2Gater
func
(
gater
*
MockConnectionGater
)
*
MockConnectionGater
p1ConnectednessToP2
network
.
Connectedness
p2ConnectednessToP1
network
.
Connectedness
isP1OutboundErr
bool
}{
"no gating"
:
{
p1ConnectednessToP2
:
network
.
Connected
,
p2ConnectednessToP1
:
network
.
Connected
,
isP1OutboundErr
:
false
,
},
"p1 gates outbound peer dial"
:
{
p1Gater
:
func
(
c
*
MockConnectionGater
)
*
MockConnectionGater
{
c
.
PeerDial
=
func
(
p
peer
.
ID
)
bool
{
return
false
}
return
c
},
p1ConnectednessToP2
:
network
.
NotConnected
,
p2ConnectednessToP1
:
network
.
NotConnected
,
isP1OutboundErr
:
true
,
},
"p1 gates outbound addr dialing"
:
{
p1Gater
:
func
(
c
*
MockConnectionGater
)
*
MockConnectionGater
{
c
.
Dial
=
func
(
p
peer
.
ID
,
addr
ma
.
Multiaddr
)
bool
{
return
false
}
return
c
},
p1ConnectednessToP2
:
network
.
NotConnected
,
p2ConnectednessToP1
:
network
.
NotConnected
,
isP1OutboundErr
:
true
,
},
"p2 gates inbound peer dial before securing"
:
{
p2Gater
:
func
(
c
*
MockConnectionGater
)
*
MockConnectionGater
{
c
.
Accept
=
func
(
c
network
.
ConnMultiaddrs
)
bool
{
return
false
}
return
c
},
p1ConnectednessToP2
:
network
.
NotConnected
,
p2ConnectednessToP1
:
network
.
NotConnected
,
isP1OutboundErr
:
true
,
},
"p2 gates inbound peer dial before multiplexing"
:
{
p1Gater
:
func
(
c
*
MockConnectionGater
)
*
MockConnectionGater
{
c
.
Secured
=
func
(
network
.
Direction
,
peer
.
ID
,
network
.
ConnMultiaddrs
)
bool
{
return
false
}
return
c
},
p1ConnectednessToP2
:
network
.
NotConnected
,
p2ConnectednessToP1
:
network
.
NotConnected
,
isP1OutboundErr
:
true
,
},
"p2 gates inbound peer dial after upgrading"
:
{
p1Gater
:
func
(
c
*
MockConnectionGater
)
*
MockConnectionGater
{
c
.
Upgraded
=
func
(
c
network
.
Conn
)
(
bool
,
control
.
DisconnectReason
)
{
return
false
,
0
}
return
c
},
p1ConnectednessToP2
:
network
.
NotConnected
,
p2ConnectednessToP1
:
network
.
NotConnected
,
isP1OutboundErr
:
true
,
},
"p2 gates outbound dials"
:
{
p2Gater
:
func
(
c
*
MockConnectionGater
)
*
MockConnectionGater
{
c
.
PeerDial
=
func
(
p
peer
.
ID
)
bool
{
return
false
}
return
c
},
p1ConnectednessToP2
:
network
.
Connected
,
p2ConnectednessToP1
:
network
.
Connected
,
isP1OutboundErr
:
false
,
},
}
}
func
TestFilterBounds
(
t
*
testing
.
T
)
{
ctx
:=
context
.
Background
()
swarms
:=
makeSwarms
(
ctx
,
t
,
2
)
for
n
,
tc
:=
range
tcs
{
t
.
Run
(
n
,
func
(
t
*
testing
.
T
)
{
p1Gater
:=
DefaultMockConnectionGater
()
p2Gater
:=
DefaultMockConnectionGater
()
if
tc
.
p1Gater
!=
nil
{
p1Gater
=
tc
.
p1Gater
(
p1Gater
)
}
if
tc
.
p2Gater
!=
nil
{
p2Gater
=
tc
.
p2Gater
(
p2Gater
)
}
conns
:=
make
(
chan
struct
{},
8
)
swarms
[
0
]
.
SetConnHandler
(
func
(
conn
network
.
Conn
)
{
conns
<-
struct
{}{}
})
sw1
:=
GenSwarm
(
t
,
ctx
,
OptConnGater
(
p1Gater
))
sw2
:=
GenSwarm
(
t
,
ctx
,
OptConnGater
(
p2Gater
))
// Address that we wont be dialing from
_
,
block
,
err
:=
net
.
ParseCIDR
(
"192.0.0.1/8"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
p1
:=
sw1
.
LocalPeer
()
p2
:=
sw2
.
LocalPeer
(
)
sw1
.
Peerstore
()
.
AddAddr
(
p2
,
sw2
.
ListenAddresses
()[
0
],
peerstore
.
PermanentAddrTTL
)
// 1 -> 2
_
,
err
:=
sw1
.
DialPeer
(
ctx
,
p2
)
// set filter on both sides, shouldnt matter
swarms
[
1
]
.
Filters
.
AddDialFilter
(
block
)
swarms
[
0
]
.
Filters
.
AddDialFilter
(
block
)
require
.
Equal
(
t
,
tc
.
isP1OutboundErr
,
err
!=
nil
,
n
)
require
.
Equal
(
t
,
tc
.
p1ConnectednessToP2
,
sw1
.
Connectedness
(
p2
),
n
)
connectSwarms
(
t
,
ctx
,
swarms
)
require
.
Eventually
(
t
,
func
()
bool
{
return
tc
.
p2ConnectednessToP1
==
sw2
.
Connectedness
(
p1
)
},
2
*
time
.
Second
,
100
*
time
.
Millisecond
,
n
)
})
select
{
case
<-
time
.
After
(
time
.
Second
)
:
t
.
Fatal
(
"should have gotten connection"
)
case
<-
conns
:
t
.
Log
(
"got connect"
)
}
}
...
...
testing/testing.go
View file @
34b2b471
...
...
@@ -4,26 +4,31 @@ import (
"context"
"testing"
"github.com/libp2p/go-libp2p-core/connmgr"
"github.com/libp2p/go-libp2p-core/control"
"github.com/libp2p/go-libp2p-core/metrics"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/libp2p/go-libp2p-core/peerstore"
"github.com/libp2p/go-libp2p-testing/net"
"github.com/libp2p/go-tcp-transport"
goprocess
"github.com/jbenet/goprocess"
csms
"github.com/libp2p/go-conn-security-multistream"
pstoremem
"github.com/libp2p/go-libp2p-peerstore/pstoremem"
secio
"github.com/libp2p/go-libp2p-secio"
swarm
"github.com/libp2p/go-libp2p-swarm"
"github.com/libp2p/go-libp2p-testing/net"
tptu
"github.com/libp2p/go-libp2p-transport-upgrader"
yamux
"github.com/libp2p/go-libp2p-yamux"
msmux
"github.com/libp2p/go-stream-muxer-multistream"
"github.com/libp2p/go-tcp-transport"
swarm
"github.com/libp2p/go-libp2p-swarm"
goprocess
"github.com/jbenet/goprocess"
ma
"github.com/multiformats/go-multiaddr"
)
type
config
struct
{
disableReuseport
bool
dialOnly
bool
connectionGater
connmgr
.
ConnectionGater
}
// Option is an option that can be passed when constructing a test swarm.
...
...
@@ -39,6 +44,13 @@ var OptDialOnly Option = func(_ *testing.T, c *config) {
c
.
dialOnly
=
true
}
// OptConnGater configures the given connection gater on the test
func
OptConnGater
(
cg
connmgr
.
ConnectionGater
)
Option
{
return
func
(
_
*
testing
.
T
,
c
*
config
)
{
c
.
connectionGater
=
cg
}
}
// GenUpgrader creates a new connection upgrader for use with this swarm.
func
GenUpgrader
(
n
*
swarm
.
Swarm
)
*
tptu
.
Upgrader
{
id
:=
n
.
LocalPeer
()
...
...
@@ -53,9 +65,8 @@ func GenUpgrader(n *swarm.Swarm) *tptu.Upgrader {
stMuxer
.
AddTransport
(
"/yamux/1.0.0"
,
yamux
.
DefaultTransport
)
return
&
tptu
.
Upgrader
{
Secure
:
secMuxer
,
Muxer
:
stMuxer
,
Filters
:
n
.
Filters
,
Secure
:
secMuxer
,
Muxer
:
stMuxer
,
}
}
...
...
@@ -72,12 +83,16 @@ func GenSwarm(t *testing.T, ctx context.Context, opts ...Option) *swarm.Swarm {
ps
:=
pstoremem
.
NewPeerstore
()
ps
.
AddPubKey
(
p
.
ID
,
p
.
PubKey
)
ps
.
AddPrivKey
(
p
.
ID
,
p
.
PrivKey
)
s
:=
swarm
.
NewSwarm
(
ctx
,
p
.
ID
,
ps
,
metrics
.
NewBandwidthCounter
())
s
:=
swarm
.
NewSwarm
(
ctx
,
p
.
ID
,
ps
,
metrics
.
NewBandwidthCounter
(),
cfg
.
connectionGater
)
// Call AddChildNoWait because we can't call AddChild after the process
// may have been closed (e.g., if the context was canceled).
s
.
Process
()
.
AddChildNoWait
(
goprocess
.
WithTeardown
(
ps
.
Close
))
tcpTransport
:=
tcp
.
NewTCPTransport
(
GenUpgrader
(
s
))
upgrader
:=
GenUpgrader
(
s
)
upgrader
.
ConnGater
=
cfg
.
connectionGater
tcpTransport
:=
tcp
.
NewTCPTransport
(
upgrader
)
tcpTransport
.
DisableReuseport
=
cfg
.
disableReuseport
if
err
:=
s
.
AddTransport
(
tcpTransport
);
err
!=
nil
{
...
...
@@ -101,3 +116,57 @@ func DivulgeAddresses(a, b network.Network) {
addrs
:=
a
.
Peerstore
()
.
Addrs
(
id
)
b
.
Peerstore
()
.
AddAddrs
(
id
,
addrs
,
peerstore
.
PermanentAddrTTL
)
}
// MockConnectionGater is a mock connection gater to be used by the tests.
type
MockConnectionGater
struct
{
Dial
func
(
p
peer
.
ID
,
addr
ma
.
Multiaddr
)
bool
PeerDial
func
(
p
peer
.
ID
)
bool
Accept
func
(
c
network
.
ConnMultiaddrs
)
bool
Secured
func
(
network
.
Direction
,
peer
.
ID
,
network
.
ConnMultiaddrs
)
bool
Upgraded
func
(
c
network
.
Conn
)
(
bool
,
control
.
DisconnectReason
)
}
func
DefaultMockConnectionGater
()
*
MockConnectionGater
{
m
:=
&
MockConnectionGater
{}
m
.
Dial
=
func
(
p
peer
.
ID
,
addr
ma
.
Multiaddr
)
bool
{
return
true
}
m
.
PeerDial
=
func
(
p
peer
.
ID
)
bool
{
return
true
}
m
.
Accept
=
func
(
c
network
.
ConnMultiaddrs
)
bool
{
return
true
}
m
.
Secured
=
func
(
network
.
Direction
,
peer
.
ID
,
network
.
ConnMultiaddrs
)
bool
{
return
true
}
m
.
Upgraded
=
func
(
c
network
.
Conn
)
(
bool
,
control
.
DisconnectReason
)
{
return
true
,
0
}
return
m
}
func
(
m
*
MockConnectionGater
)
InterceptAddrDial
(
p
peer
.
ID
,
addr
ma
.
Multiaddr
)
(
allow
bool
)
{
return
m
.
Dial
(
p
,
addr
)
}
func
(
m
*
MockConnectionGater
)
InterceptPeerDial
(
p
peer
.
ID
)
(
allow
bool
)
{
return
m
.
PeerDial
(
p
)
}
func
(
m
*
MockConnectionGater
)
InterceptAccept
(
c
network
.
ConnMultiaddrs
)
(
allow
bool
)
{
return
m
.
Accept
(
c
)
}
func
(
m
*
MockConnectionGater
)
InterceptSecured
(
d
network
.
Direction
,
p
peer
.
ID
,
c
network
.
ConnMultiaddrs
)
(
allow
bool
)
{
return
m
.
Secured
(
d
,
p
,
c
)
}
func
(
m
*
MockConnectionGater
)
InterceptUpgraded
(
tc
network
.
Conn
)
(
allow
bool
,
reason
control
.
DisconnectReason
)
{
return
m
.
Upgraded
(
tc
)
}
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