Documentation
¶
Index ¶
- Constants
- Variables
- func AddrPortFrom(addr net.Addr) netip.AddrPort
- type AddrSpace
- type Client
- func (c *Client) Accept(ctx context.Context, addr, token string, header http.Header) (*Conn, *http.Response, error)
- func (c *Client) Dial(ctx context.Context, addr, token string, header http.Header) (*Conn, *http.Response, error)
- func (c *Client) Do(ctx context.Context, method, addr, token string, header http.Header) (*Conn, *http.Response, error)
- type Conn
- type ErrOther
- type Handler
- type Meta
- type Picker
- type Relayer
- func (r *Relayer) Continue(ctx context.Context, dc, ac *Conn) error
- func (r *Relayer) Reject(dc, ac *Conn, statusCode int, reason string) error
- func (r *Relayer) Relay(ctx context.Context, w1, w2 io.WriteCloser, r1, r2 io.Reader) (n1 int64, n2 int64, err error)
- func (r *Relayer) Serve(ctx context.Context, dc, ac *Conn)
- type Server
Examples ¶
Constants ¶
const (
// HTTP methods to establish rdv conns
DIAL, ACCEPT = "DIAL", "ACCEPT"
)
Variables ¶
var ( // ErrBadHandshake is returned from client and server when the http upgrade to rdv failed. ErrBadHandshake = errors.New("bad http handshake") // ErrProtocol is returned upon an error in the rdv header exhange. ErrProtocol = errors.New("rdv protocol error") )
Functions ¶
func AddrPortFrom ¶ added in v0.0.6
Get AddrPort from a TCP- or UDP net.Addr. Returns the zero-value if not supported. Unmaps the ip, unlike net.TCPAddr.AddrPort, see https://github.com/golang/go/issues/53607
Types ¶
type AddrSpace ¶ added in v0.0.3
type AddrSpace uint32
A unicast "address space" of an ip addr, for purposes of rdv connectivity. As a bitmask, this type can also be used as a set of addr spaces.
const ( // Denotes an invalid address space (i.e. not enumerated here) SpaceInvalid AddrSpace = 0 // Public addrs are very common and useful for remote connectivity. // Public IPv6 addrs can also provide local connectivity. SpacePublic4 AddrSpace = 1 << iota SpacePublic6 // Private IPv4 addrs are very common and useful for local connectivity. IPv6 local (ULA) addrs // are less common. SpacePrivate4 SpacePrivate6 // Link-local IPv4 addrs are not common and IPv6 addrs are not recommended due to zones. SpaceLink4 SpaceLink6 // Loopback addresses are mostly useful for testing. SpaceLoopback4 SpaceLoopback6 )
const ( // NoSpaces is the set of no spaces, which can be used to force a relay conn, disabling p2p. NoSpaces AddrSpace = 1 << 31 // PublicSpaces is the set of public ipv4 and ipv6 addrs. PublicSpaces AddrSpace = SpacePublic4 | SpacePublic6 // DefaultSpaces is the set of spaces suitable for p2p WAN & LAN connectivity. DefaultSpaces AddrSpace = SpacePublic4 | SpacePublic6 | SpacePrivate4 | SpacePrivate6 // AllSpaces is the set of all enumerated unicast spaces. AllSpaces AddrSpace = ^NoSpaces )
func AddrSpaceFrom ¶ added in v0.0.6
Returns the address space of the ip address.
func (AddrSpace) Includes ¶ added in v0.0.3
Returns true if the provided space is included in this set of addr spaces
func (AddrSpace) IncludesAddr ¶ added in v0.0.6
Returns true if the provided addr is included in this set of addr spaces
func (AddrSpace) MatchesAddr ¶ added in v0.0.6
Returns true if the provided addr's space is equal to this exact addr space
type Client ¶
type Client struct { // Can be used to allow only a certain set of spaces, such as public IPs only. Defaults to // DefaultSpaces which optimal for both LAN and WAN connectivity. AddrSpaces AddrSpace // Picker used by the dialing side. If nil, defaults to WaitForP2P(time.Second) Picker Picker // Timeout for the full dial/accept process, if provided. Note this may include DNS, TLS, // signaling delay and probing for p2p. We recommend >3s in production. Timeout time.Duration // Custom TLS config to use with the rdv server. TlsConfig *tls.Config // Optional logger to use. Logger *slog.Logger }
Client can dial and accept rdv conns. The zero-value is valid.
Example ¶
client := &Client{} conn, _, err := client.Dial(context.Background(), "http://example.com/", "abc", nil) if err != nil { return } defer conn.Close() // Conn is either a direct p2p, or relayed, TCP-based conn with the other peer
Output:
func (*Client) Accept ¶
func (c *Client) Accept(ctx context.Context, addr, token string, header http.Header) (*Conn, *http.Response, error)
Accept a peer conn, shorthand for Do(ctx, ACCEPT, ...)
func (*Client) Dial ¶
func (c *Client) Dial(ctx context.Context, addr, token string, header http.Header) (*Conn, *http.Response, error)
Dial a peer, shorthand for Do(ctx, DIAL, ...)
func (*Client) Do ¶ added in v0.0.6
func (c *Client) Do(ctx context.Context, method, addr, token string, header http.Header) (*Conn, *http.Response, error)
Connect with another peer through an rdv server endpoint.
- method: must be DIAL or ACCEPT
- addr: http(s) addr of the rdv server endpoint
- token: an arbitrary string for matching the two peers, typically chosen by the dialer
- header: an optional set of http headers included in the request, e.g. for authorization
Returns an ErrBadHandshake error if the server doesn't upgrade the rdv conn properly. A read-only http response is returned if available, whether or not an error occurred.
type Conn ¶
type Conn struct { // Metadata about the rdv conn. *Meta // Reports whether the conn is relayed by an rdv server. Client conns only. IsRelay bool // Read-only http request. Server conns only. Request *http.Request // contains filtered or unexported fields }
Conn is an rdv conn, either p2p or relay, which implements net.Conn.
type ErrOther ¶ added in v0.0.6
ErrOther indicates that a p2p conn was established directly between peers. This is the intended outcome, but considered an error server side, which expects to relay data.
type Handler ¶ added in v0.0.6
Handler serves pairs of (dial- and accept) rdv conns. The context is canceled when the server is closed.
Custom implementations should use a Relayer to conform with the rdv protocol.
type Meta ¶
type Meta struct { // Request data Method, Token string SelfAddrs []netip.AddrPort // Response data ObservedAddr *netip.AddrPort PeerAddrs []netip.AddrPort }
Metadata associated with the rdv http handshake between client and server.
type Picker ¶ added in v0.0.6
Picker decides which conns to use, as they come available. Pick is invoked when peers begin their connection attempts to each other. Implementations must drain the candidates channel and return all conns in order of preference, where conns[0] will be chosen and returned to the user. The channel is closed when a timeout or cancelation occurs upstream, or through the cancel callback.
func PickFirst ¶ added in v0.0.6
func PickFirst() Picker
Returns a picker which completes as soon as any conn is available.
func WaitConstant ¶ added in v0.0.6
Returns a picker that always waits for a specific amount of time. This is useful for debugging and collecting stats.
func WaitForP2P ¶ added in v0.0.6
Returns a picker that completes when a p2p conn is found, or falls back to the relay if the timeout expires. Experimentally, it takes ~2-3 RTT to establish a p2p conn, whereas the relay conn is already present. Thus, "penalizing" the relay conn by 300-3000 ms is recommended as a balance between finding the best connection, while keeping establishment time reasonable.
Remember to set any application-level dial/accept timeouts much higher than this "picking" timeout, since rdv involves several more steps, like dns lookups and tcp/tls establishment.
type Relayer ¶
type Relayer struct { // Specifies a duration of inactivity after which the relay is closed. // If zero, there is no timeout. IdleTimeout time.Duration // The size of copy buffers. By default the [io.Copy] default size is used. BufferSize int }
Relayer handles a pair of rdv conns by relaying data between them. The zero-value can be used.
func (*Relayer) Continue ¶ added in v0.0.6
Sends the http upgrade response to both conns and reads the dialer's CONTINUE command. Returns ErrOther if a p2p conn was established.
func (*Relayer) Relay ¶ added in v0.0.6
func (r *Relayer) Relay(ctx context.Context, w1, w2 io.WriteCloser, r1, r2 io.Reader) (n1 int64, n2 int64, err error)
Copies data from r1 to w1 and from r2 to w2. Both writers are closed upon an IO error, when ctx is canceled, or due to inactivity (see [Relayer.IdleTimeout]). Returns amount of data copied for each pair, and the first error that occurred, often io.EOF. Note that Relayer.Continue must be called beforehand.
In order to monitor or rate-limit conns, use io.TeeReader for r1 and r2.
func (*Relayer) Serve ¶ added in v0.0.6
Serve implements Handler by connecting and relaying data between peers as necessary. Call Relayer.Continue and Relayer.Relay manually for custom behavior, monitoring, rate-limiting, etc.
type Server ¶
type Server struct { // Handler serves relay connections between the two peers. Can be customized to monitor, // rate limit or set idle timeouts. If nil, a zero-value [Relayer] is used. Handler Handler // Amount of time that on peer can wait in the lobby for its partner. Zero means no timeout. LobbyTimeout time.Duration // Function that extracts the observed addr from requests. If nil, r.RemoteAddr is parsed. // // If your server is behind a load balancer, reverse proxy or similar, you may need to configure // forwarding headers and provide a custom function. See the server setup guide for details. ObservedAddrFunc func(r *http.Request) (netip.AddrPort, error) // Optional logger to use. Logger *slog.Logger // contains filtered or unexported fields }
An rdv server, which implements net/http.Handler.
Example ¶
// Run a plain rdv server without other endpoints srv := &Server{} srv.Start() defer srv.Close() http.ListenAndServe(":8080", srv)
Output:
func (*Server) Close ¶ added in v0.0.6
Calls Server.Shutdown and waits for handlers and internal goroutines to finish. Safe to call multiple times.
func (*Server) ServeHTTP ¶
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
Calls Server.Upgrade and logs the error, if any.
func (*Server) Shutdown ¶ added in v0.0.6
func (s *Server) Shutdown()
Evict all clients from lobby and cancels the context passed to handlers. After this, clients are rejected with a 503 error. Suitable for use with http.Server.RegisterOnShutdown. Use Server.Close to wait for all handlers to complete.
func (*Server) Start ¶ added in v0.0.6
func (s *Server) Start()
Start rdv server goroutines which manages upgrades and handler invocations.
func (*Server) Upgrade ¶ added in v0.0.6
Upgrades the request and adds the client to the lobby for matching. Returns an ErrBadHandshake error if the upgrade failed, or net/http.ErrServerClosed if closed. An http error is written to the client if an error occurs.