Skip to content
This repository has been archived by the owner on Sep 6, 2022. It is now read-only.

Adding QualityTransport interfaces. #121

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions go.sum
Expand Up @@ -89,6 +89,7 @@ github.com/multiformats/go-multihash v0.0.13 h1:06x+mk/zj1FoMsgNejLpy6QTvJqlSt/B
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
github.com/multiformats/go-varint v0.0.1 h1:TR/0rdQtnNxuN2IhiB639xC3tWM4IUi7DkTBVTdGW/M=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg=
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
Expand Down
10 changes: 10 additions & 0 deletions network/conn.go
Expand Up @@ -2,6 +2,7 @@ package network

import (
"io"
"time"

ic "github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
Expand All @@ -27,8 +28,17 @@ type Conn interface {

// Stat stores metadata pertaining to this conn.
Stat() Stat

// OnBetter is an callback when a better connection is found.
// OnBetter is threadsafe, it can be called even once the event raised and the
// callback we be yield.
OnBetter(OnBetterHandler)
}

// OnBetterHandler are args to pass to Conn.OnBetter The time is the deadline
// before a hard close (fixed time not duration).
type OnBetterHandler func(time.Time)

// ConnSecurity is the interface that one can mix into a connection interface to
// give it the security methods.
type ConnSecurity interface {
Expand Down
106 changes: 100 additions & 6 deletions transport/transport.go
Expand Up @@ -28,6 +28,9 @@ var AcceptTimeout = 60 * time.Second
// capabilities required by libp2p: stream multiplexing, encryption and
// peer authentication.
//
// DEPREACATED try to use QCapableConn instead, using this will result in
// wrong transport choice when trying to pick a good one.
//
// These capabilities may be natively provided by the transport, or they
// may be shimmed via the "connection upgrade" process, which converts a
// "raw" network connection into one that supports such capabilities by
Expand All @@ -36,12 +39,65 @@ var AcceptTimeout = 60 * time.Second
// CapableConn provides accessors for the local and remote multiaddrs used to
// establish the connection and an accessor for the underlying Transport.
type CapableConn interface {
BaseCapableConn

// Transport returns the transport to which this connection belongs.
Transport() Transport
}

// Quality is an estimation of how bad the connection will be.
// It must be short and fast to run.
// Lower is the returned score, better we expect the connection to be.
// Don't implement a pinging/monitoring algorithm quality must be deterministic.
//
// To see where to place your transport on the scale take a look at this (note:
// a proto with a Quality twice bigger is not twice slower or twice worst, it is
// just worst, like the place on a leaderboard):
// - TCP, 2^31, multiplexed stated continuous protocol (stream have fight for a
// place in the underlying protocol)
// - QUIC, 2^30, async stated discontinuous protocol (stream doesn't have to
// fight but there is time taken to open the connection and stream)
// - Circuit, router underlying connection quality + the number of hops * 8
// (that consider that all router are equal but there is really no better than
// pinging/monitoring to know that) + 2^16 (base circuit value).
//
// Its also not needed to follow that closely, thing can be added if a proto add
// some overhead :
// - WS tcp score + 50
// - WSS ws score + 150
//
// If conn is on a private network Quality() must divide score by 2^8 (shift
// right by 8).
// If conn is on the loopback Quality() must divide score by 2^16 (shift right
// by 16).
//
// QCapableConn embed CapableConn but with `Quality() uint32` support.
type QCapableConn interface {
BaseCapableConn

// Quality returns the Quality we can expect from the connection to this peer.
// That must be deterministic and fast.
Quality() uint32

// Transport returns the transport to which this connection belongs.
Transport() QTransport
}

// CapableConnBase is used to build `CapableConn` and `QCapableConn`
type BaseCapableConn interface {
mux.MuxedConn
network.ConnSecurity
network.ConnMultiaddrs
}

// Transport returns the transport to which this connection belongs.
Transport() Transport
// Score is used by transport to returns expectation about connection, might be
// different than what the connection actualy return but that DEPREACATED.
// (that will cause weird cancel issue)
type Score struct {
// Score of the future connection.
Quality uint32
// Number of file descriptor expected to be open.
Fd uint8
}

// Transport represents any device by which you can connect to and accept
Expand All @@ -55,11 +111,36 @@ type CapableConn interface {
// stream multiplexing and connection security (encryption and authentication).
//
// For a conceptual overview, see https://docs.libp2p.io/concepts/transport/
//
// DEPREACATED try to use QTransport instead, using this will result in
// wrong transport choice when trying to pick a good one.
type Transport interface {
BaseTransport

// Dial dials a remote peer. It should try to reuse local listener
// addresses if possible but it may choose not to.
Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (CapableConn, error)

// Listen listens on the passed multiaddr.
Listen(laddr ma.Multiaddr) (Listener, error)
}

type QTransport interface {
BaseTransport

// Dial dials a remote peer. It should try to reuse local listener
// addresses if possible but it may choose not to.
Dial(ctx context.Context, raddr ma.Multiaddr, p peer.ID) (QCapableConn, error)

// Listen listens on the passed multiaddr.
Listen(laddr ma.Multiaddr) (QListener, error)

// Score returns the Quality we can expect from the connection to this peer.
// That must be deterministic and fast.
Score(raddr ma.Multiaddr, p peer.ID) (Score, error)
}

type BaseTransport interface {
// CanDial returns true if this transport knows how to dial the given
// multiaddr.
//
Expand All @@ -68,9 +149,6 @@ type Transport interface {
// out addresses that we can't dial.
CanDial(addr ma.Multiaddr) bool

// Listen listens on the passed multiaddr.
Listen(laddr ma.Multiaddr) (Listener, error)

// Protocol returns the set of protocols handled by this transport.
//
// See the Network interface for an explanation of how this is used.
Expand All @@ -88,7 +166,20 @@ type Transport interface {
// package, and also exposes a Multiaddr method as opposed to a regular Addr
// method
type Listener interface {
BaseListener

Accept() (CapableConn, error)
}

// QListener is like listener but produce QCapableConn instead of CapableConn.
type QListener interface {
BaseListener

Accept() (QCapableConn, error)
}

// BaseListener is used to build `Lister` and `QListener`
type BaseListener interface {
Close() error
Addr() net.Addr
Multiaddr() ma.Multiaddr
Expand All @@ -109,5 +200,8 @@ type TransportNetwork interface {
// local multiaddr and pick the *last* protocol registered with a proxy
// transport, if any. Otherwise, it'll pick the transport registered to
// handle the last protocol in the multiaddr.
AddTransport(t Transport) error
//
// Even if BaseTransport are accepted its needed to be able to cast to
// Transport or QTransport.
AddTransport(t BaseTransport) error
}