This repository has been archived by the owner on Sep 9, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 16
p2p-circuit v2 #125
Merged
Merged
p2p-circuit v2 #125
Changes from all commits
Commits
Show all changes
66 commits
Select commit
Hold shift + click to select a range
9957868
v2 client scaffolding
vyzo 07c94b2
gomod: go-libp2p-core and go-libp2p-transport-upgrader feature depend…
vyzo 00f66ac
Conn implements network.ConnStat
vyzo 2a4f0fe
add reservation stub
vyzo d65387b
utilities
vyzo 2158d4e
dial scaffolding and v1 compat dialing
vyzo 4cf0099
stream handling scaffolding and v1 incoming connection handling
vyzo 08e8616
implement hop tagging
vyzo 5775e43
export timeout variables
vyzo 3a20a7d
v2 protobuf
vyzo 67cdcee
v2 client protocol implementation
vyzo 8abf64d
implement Reserve
vyzo 5fa453e
go get go-libp2p-swarm@feat/transient-conns
vyzo 7ebd713
implement client.New
vyzo 7cd275a
rework pb status codes
vyzo 7805167
client responds with UNEXPECTED_MESSAGE when it's actually an unexpec…
vyzo e4a463f
relay scaffolding, reservation implementation
vyzo 66e3654
implement relaying
vyzo 5e1217a
implement missing details
vyzo ff9fdfc
add options for resources/limit
vyzo cbe4fcb
gc idle conn counts
vyzo e36365e
fix clown shoes in cancellation check
vyzo 1fbd2d4
end to end relay test
vyzo 71d18fd
untag peers with expired reservations
vyzo c679386
add time limit test
vyzo 20bdb29
better debug log for accepted conns
vyzo d9dd2e8
add data limit test
vyzo 529b09f
add v2-v1 compatibility tests
vyzo c278b2c
godocs
vyzo 017982a
add WithACL relay option
vyzo 2dda598
only return public relay addrs in reservation record
vyzo 96e502e
remove the refresh restriction madness
vyzo 6eaf6e1
set default limit Data to 128K
vyzo 92c0e0b
fix typo in AllowReserve godoc
vyzo 1f294d2
fix some small issues
vyzo 13a9ed7
fix tests
vyzo 6c7540c
address review comments
vyzo 3087bec
humor aarsh and add initializers for slices
vyzo b47c119
comment nitpicks
vyzo 82f3808
fix bug in slice pre-allocations
vyzo 57b0a29
add deadline to connectV1
vyzo 6fed031
make Relay.Close thread-safe
vyzo 7e8bef0
untag peers with reservations when closing the relay
vyzo 49e9649
gomod: get go-libp2p-asn-util
vyzo 5b7a615
add IP/ASN reservation constraints
vyzo 6389453
gomod: update deps
vyzo 148d307
fix e2e test
vyzo 68d07f5
increase default limit duration to 2min
vyzo 526fc92
update protocol for vouched relay addrs; provide absolute expiration …
vyzo 6d34d5b
update for reservation changes
vyzo 16d5616
add voucher to the reservation pb
vyzo 1cec70e
TODO about reservation vouchers
vyzo 4ec7298
deduplicate protocol ID definitions between relay and client
vyzo c7b3913
add reservation vouchers
vyzo 533abb2
emit and consume reservation vouchers
vyzo a3d765a
improve limit data test
vyzo 75b4777
deduplicate concurrent relay dials to the samke peer
vyzo 470c088
improve dialer deduplication
vyzo 2333151
add a short timeout to dialing the relay in order to aid deduplication
vyzo 84c6610
gomod: fix go1.16 madness
vyzo 30b71a3
spec compliance: don't include p2p-circuit in reservation addrs
vyzo ffa309e
spec compliance: refuse reservation and connection attempts over rela…
vyzo 12eefbc
test shim: add empty file in test directory
vyzo b4d0d1a
spec compliance: update protobuf
vyzo e1bbd83
spec compliance: use libp2p envelopes for reservation vouchers
vyzo 97ec1d6
fix staticcheck
marten-seemann File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package client | ||
|
||
import ( | ||
"context" | ||
"sync" | ||
|
||
"github.com/libp2p/go-libp2p-circuit/v2/proto" | ||
|
||
"github.com/libp2p/go-libp2p-core/host" | ||
"github.com/libp2p/go-libp2p-core/peer" | ||
|
||
logging "github.com/ipfs/go-log" | ||
tptu "github.com/libp2p/go-libp2p-transport-upgrader" | ||
) | ||
|
||
var log = logging.Logger("p2p-circuit") | ||
|
||
// Client implements the client-side of the p2p-circuit/v2 protocol: | ||
// - it implements dialing through v2 relays | ||
// - it listens for incoming connections through v2 relays. | ||
// | ||
// For backwards compatibility with v1 relays and older nodes, the client will | ||
// also accept relay connections through v1 relays and fallback dial peers using p2p-circuit/v1. | ||
// This allows us to use the v2 code as drop in replacement for v1 in a host without breaking | ||
// existing code and interoperability with older nodes. | ||
type Client struct { | ||
ctx context.Context | ||
host host.Host | ||
upgrader *tptu.Upgrader | ||
|
||
incoming chan accept | ||
|
||
mx sync.Mutex | ||
activeDials map[peer.ID]*completion | ||
hopCount map[peer.ID]int | ||
} | ||
|
||
type accept struct { | ||
conn *Conn | ||
writeResponse func() error | ||
} | ||
|
||
type completion struct { | ||
ch chan struct{} | ||
relay peer.ID | ||
err error | ||
} | ||
|
||
// New constructs a new p2p-circuit/v2 client, attached to the given host and using the given | ||
// upgrader to perform connection upgrades. | ||
func New(ctx context.Context, h host.Host, upgrader *tptu.Upgrader) (*Client, error) { | ||
return &Client{ | ||
ctx: ctx, | ||
host: h, | ||
upgrader: upgrader, | ||
incoming: make(chan accept), | ||
activeDials: make(map[peer.ID]*completion), | ||
hopCount: make(map[peer.ID]int), | ||
}, nil | ||
} | ||
|
||
// Start registers the circuit (client) protocol stream handlers | ||
func (c *Client) Start() { | ||
c.host.SetStreamHandler(proto.ProtoIDv1, c.handleStreamV1) | ||
c.host.SetStreamHandler(proto.ProtoIDv2Stop, c.handleStreamV2) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
package client | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"time" | ||
|
||
"github.com/libp2p/go-libp2p-core/network" | ||
"github.com/libp2p/go-libp2p-core/peer" | ||
|
||
ma "github.com/multiformats/go-multiaddr" | ||
manet "github.com/multiformats/go-multiaddr/net" | ||
) | ||
|
||
// HopTagWeight is the connection manager weight for connections carrying relay hop streams | ||
var HopTagWeight = 5 | ||
|
||
type statLimitDuration struct{} | ||
type statLimitData struct{} | ||
|
||
var ( | ||
StatLimitDuration = statLimitDuration{} | ||
StatLimitData = statLimitData{} | ||
) | ||
|
||
type Conn struct { | ||
stream network.Stream | ||
remote peer.AddrInfo | ||
stat network.Stat | ||
|
||
client *Client | ||
} | ||
|
||
type NetAddr struct { | ||
Relay string | ||
Remote string | ||
} | ||
|
||
var _ net.Addr = (*NetAddr)(nil) | ||
|
||
func (n *NetAddr) Network() string { | ||
return "libp2p-circuit-relay" | ||
} | ||
|
||
func (n *NetAddr) String() string { | ||
return fmt.Sprintf("relay[%s-%s]", n.Remote, n.Relay) | ||
} | ||
|
||
// Conn interface | ||
var _ manet.Conn = (*Conn)(nil) | ||
|
||
func (c *Conn) Close() error { | ||
c.untagHop() | ||
return c.stream.Reset() | ||
} | ||
|
||
func (c *Conn) Read(buf []byte) (int, error) { | ||
return c.stream.Read(buf) | ||
} | ||
|
||
func (c *Conn) Write(buf []byte) (int, error) { | ||
return c.stream.Write(buf) | ||
} | ||
|
||
func (c *Conn) SetDeadline(t time.Time) error { | ||
return c.stream.SetDeadline(t) | ||
} | ||
|
||
func (c *Conn) SetReadDeadline(t time.Time) error { | ||
return c.stream.SetReadDeadline(t) | ||
} | ||
|
||
func (c *Conn) SetWriteDeadline(t time.Time) error { | ||
return c.stream.SetWriteDeadline(t) | ||
} | ||
|
||
// TODO: is it okay to cast c.Conn().RemotePeer() into a multiaddr? might be "user input" | ||
func (c *Conn) RemoteMultiaddr() ma.Multiaddr { | ||
// TODO: We should be able to do this directly without converting to/from a string. | ||
relayAddr, err := ma.NewComponent( | ||
ma.ProtocolWithCode(ma.P_P2P).Name, | ||
c.stream.Conn().RemotePeer().Pretty(), | ||
) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return ma.Join(c.stream.Conn().RemoteMultiaddr(), relayAddr, circuitAddr) | ||
} | ||
|
||
func (c *Conn) LocalMultiaddr() ma.Multiaddr { | ||
return c.stream.Conn().LocalMultiaddr() | ||
} | ||
|
||
func (c *Conn) LocalAddr() net.Addr { | ||
na, err := manet.ToNetAddr(c.stream.Conn().LocalMultiaddr()) | ||
if err != nil { | ||
log.Error("failed to convert local multiaddr to net addr:", err) | ||
return nil | ||
} | ||
return na | ||
} | ||
|
||
func (c *Conn) RemoteAddr() net.Addr { | ||
return &NetAddr{ | ||
Relay: c.stream.Conn().RemotePeer().Pretty(), | ||
Remote: c.remote.ID.Pretty(), | ||
} | ||
} | ||
|
||
// ConnStat interface | ||
var _ network.ConnStat = (*Conn)(nil) | ||
|
||
func (c *Conn) Stat() network.Stat { | ||
return c.stat | ||
} | ||
|
||
// tagHop tags the underlying relay connection so that it can be (somewhat) protected from the | ||
// connection manager as it is an important connection that proxies other connections. | ||
// This is handled here so that the user code doesnt need to bother with this and avoid | ||
// clown shoes situations where a high value peer connection is behind a relayed connection and it is | ||
// implicitly because the connection manager closed the underlying relay connection. | ||
func (c *Conn) tagHop() { | ||
vyzo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
c.client.mx.Lock() | ||
defer c.client.mx.Unlock() | ||
|
||
p := c.stream.Conn().RemotePeer() | ||
c.client.hopCount[p]++ | ||
if c.client.hopCount[p] == 1 { | ||
c.client.host.ConnManager().TagPeer(p, "relay-hop-stream", HopTagWeight) | ||
} | ||
} | ||
|
||
// untagHop removes the relay-hop-stream tag if necessary; it is invoked when a relayed connection | ||
// is closed. | ||
func (c *Conn) untagHop() { | ||
c.client.mx.Lock() | ||
defer c.client.mx.Unlock() | ||
|
||
p := c.stream.Conn().RemotePeer() | ||
c.client.hopCount[p]-- | ||
if c.client.hopCount[p] == 0 { | ||
c.client.host.ConnManager().UntagPeer(p, "relay-hop-stream") | ||
delete(c.client.hopCount, p) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please can we add a unit test for this one function ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ugh.... maybe, I am not inclined to do it right now.