nethernet

package module
v1.0.18 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 4, 2026 License: MIT Imports: 27 Imported by: 7

README

go-nethernet

go-nethernet is a library that implements a basic version of the NetherNet protocol, which is currently used for Minecraft: Bedrock Edition connections over LAN and Xbox Live.

[!WARNING] This library is still in development and is not yet feature-complete.

Documentation

PkgGoDev

Contact

Discord Banner 2

Documentation

Index

Constants

View Source
const (
	// SignalTypeOffer is signaled by a client to request a connection to the remote host.
	// Signals of SignalTypeOffer typically contain a data for a local description of the connection.
	SignalTypeOffer = "CONNECTREQUEST"

	// SignalTypeAnswer is signaled by a server in response to a SignalTypeOffer.
	// Signals with SignalTypeAnswer typically contain a data for a local description of the host.
	SignalTypeAnswer = "CONNECTRESPONSE"

	// SignalTypeCandidate is signaled by both server and client to notify an ICE candidate to the remote
	// connection. It is typically sent after a SignalTypeOffer or SignalTypeAnswer. Signals with SignalTypeCandidate
	// typically contain a data for the ICE candidate formatted with the standard format used by the C++
	// implementation of WebRTC, otherwise it may be ignored.
	SignalTypeCandidate = "CANDIDATEADD"

	// SignalTypeError is signaled by both server and client to report an error that occurred during the connection.
	// Signals with SignalTypeError typically contain a data of the error code, which is one of the constants
	// defined below.
	SignalTypeError = "CONNECTERROR"
)
View Source
const (
	ErrorCodeNone = iota
	ErrorCodeDestinationNotLoggedIn
	ErrorCodeNegotiationTimeout
	ErrorCodeWrongTransportVersion
	ErrorCodeFailedToCreatePeerConnection
	ErrorCodeICE
	ErrorCodeConnectRequest
	ErrorCodeConnectResponse
	ErrorCodeCandidateAdd
	ErrorCodeInactivityTimeout
	ErrorCodeFailedToCreateOffer
	ErrorCodeFailedToCreateAnswer
	ErrorCodeFailedToSetLocalDescription
	ErrorCodeFailedToSetRemoteDescription
	ErrorCodeNegotiationTimeoutWaitingForResponse
	ErrorCodeNegotiationTimeoutWaitingForAccept
	ErrorCodeIncomingConnectionIgnored
	ErrorCodeSignalingParsingFailure
	ErrorCodeSignalingUnknownError
	ErrorCodeSignalingUnicastMessageDeliveryFailed
	ErrorCodeSignalingBroadcastDeliveryFailed
	ErrorCodeSignalingMessageDeliveryFailed
	ErrorCodeSignalingTurnAuthFailed
	ErrorCodeSignalingFallbackToBestEffortDelivery
	ErrorCodeNoSignalingChannel
	ErrorCodeNotLoggedIn
	ErrorCodeSignalingFailedToSend

	// ErrorCodeIdentityVerificationFailed reports that the remote identity token
	// or its DTLS fingerprint assertion failed validation.
	ErrorCodeIdentityVerificationFailed = 37
)

Variables

View Source
var ErrUnsupported = errors.New("nethernet: unsupported")

Functions

This section is empty.

Types

type Addr

type Addr struct {
	// ConnectionID is a unique ID assigned to a connection. It is generated by the client and
	// used in Signals signaled between clients and servers to uniquely reference a specific connection.
	ConnectionID uint64

	// NetworkID is a unique ID for the NetherNet network.
	NetworkID string

	// Candidates contains a list of ICE candidates. These candidates are either gathered locally or
	// signaled from a remote connection. ICE candidates are used to determine the UDP/TCP addresses
	// for establishing ICE transport and can be used to determine the network address of the connection.
	Candidates []webrtc.ICECandidate

	// SelectedCandidate is the candidate selected to connect with the ICE transport within a Conn.
	// An ICE candidate may be used to determine the UDP/TCP address of the connection. It may be nil
	// if the Conn has been closed, or if the Conn has encountered an error when obtaining the selected
	// ICE candidate pair.
	SelectedCandidate *webrtc.ICECandidate
}

Addr represents a network address that encapsulates both local and remote connection IDs and implements net.Addr.

The Addr provides details for the unique IDs of Conn and ICE Candidates used for establishing network connectivity.

func (*Addr) Network

func (addr *Addr) Network() string

Network returns the network type for the Addr, which is always 'nethernet'.

func (*Addr) String

func (addr *Addr) String() string

String formats the Addr as a string.

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is an implementation of net.Conn for a peer connection between a specific remote NetherNet network/connection. Conn is safe for concurrent use by multiple goroutines except Read and ReadPacket.

A Conn represents a WebRTC peer connection using ICE, DTLS, and SCTP transports and encapsulates two data channels labeled 'ReliableDataChannel' and 'UnreliableDataChannel'. Most methods within Conn utilize the 'ReliableDataChannel', as the functionality of the 'UnreliableDataChannel' is less defined.

A Conn may be established by dialing a remote network ID using Dialer.DialContext (and other aliases), or by accepting connections from a Listener that listens on a local network.

Conn does not use webrtc.PeerConnection, because it needs to build custom sdp.SessionDescription values during negotiation.

Once established and negotiated through either Dialer or Listener, Conn handles messages sent over the 'ReliableDataChannel' (which may be read using Read or ReadPacket), and ensures closure of its WebRTC transports to confirm that all transports within Conn are closed.

func (*Conn) BatchHeader

func (conn *Conn) BatchHeader() []byte

BatchHeader always returns a nil slice as no header is prefixed before packets.

func (*Conn) Close

func (conn *Conn) Close() (err error)

Close closes the 'ReliableDataChannel' and 'UnreliableDataChannel', then closes the SCTP, DTLS, and ICE transports of the Conn. An error may be returned using errors.Join, which contains non-nil errors encountered during closure.

func (*Conn) Context added in v1.0.1

func (conn *Conn) Context() context.Context

Context returns the background context associated with the Conn. The returned context is canceled when the Conn is no longer usable. Its cancellation cause describes the reason the Conn was closed.

func (*Conn) DisableEncryption

func (conn *Conn) DisableEncryption() bool

DisableEncryption always reports true as no encryption should be done on Minecraft connection. Disabling encryption is insecure and may allow attackers to replay Login packets. Servers should perform additional verification (for example, ensuring the player joined the Xbox Live multiplayer session) to confirm the client is legitimately authenticated.

func (*Conn) Latency

func (conn *Conn) Latency() time.Duration

Latency returns the current latency to the remote connection as half the Smoothed Round Trip Time (SRTT) from the statistics of the SCTP transport.

func (*Conn) LocalAddr

func (conn *Conn) LocalAddr() net.Addr

LocalAddr returns an Addr that includes the local network ID of the Conn with locally-gathered ICE candidates.

func (*Conn) PublicKey added in v1.0.15

func (conn *Conn) PublicKey() *ecdsa.PublicKey

PublicKey returns the authenticated public key of the remote peer.

The peer has proven possession of the corresponding private key by signing the SDP fingerprint assertion used to bind its identity to the DTLS certificates of this WebRTC peer connection.

If the connection was established without identity assertion, nil is returned.

func (*Conn) Read

func (conn *Conn) Read(b []byte) (n int, err error)

Read receives a message from the 'ReliableDataChannel'. The bytes of the message data are copied to the given data. An error may be returned if the Conn has been closed by Conn.Close.

func (*Conn) ReadPacket

func (conn *Conn) ReadPacket() ([]byte, error)

ReadPacket receives a message from the 'ReliableDataChannel' and returns the bytes. It is implemented for Minecraft read operations to avoid some bugs related to the Read method in their decoder.

func (*Conn) Receive

func (conn *Conn) Receive(r MessageReliability) ([]byte, error)

Receive receives a packet in fully reconstructed state combined from multiple segments received from the data channel responsible for the MessageReliability. An error may be returned if the Conn has been closed by Conn.Close.

func (*Conn) RemoteAddr

func (conn *Conn) RemoteAddr() net.Addr

RemoteAddr returns an Addr that includes the remote network ID of the Conn with remotely-signaled ICE candidates. Candidates are atomically added when a Signal of type SignalTypeCandidate has been handled.

func (*Conn) Send

func (conn *Conn) Send(data []byte, reliability MessageReliability) (n int, err error)

Send writes the data into the data channel responsible for the given MessageReliability. If the data exceeds 10,000 bytes, it is split into multiple segments. An error may be returned while writing one or more segments or the Conn has been closed by Conn.Close.

func (*Conn) SetDeadline

func (*Conn) SetDeadline(time.Time) error

SetDeadline is a no-op implementation of net.Conn.SetDeadline and returns ErrUnsupported.

func (*Conn) SetReadDeadline

func (*Conn) SetReadDeadline(time.Time) error

SetReadDeadline is a no-op implementation of net.Conn.SetReadDeadline and returns ErrUnsupported.

func (*Conn) SetWriteDeadline

func (*Conn) SetWriteDeadline(time.Time) error

SetWriteDeadline is a no-op implementation of net.Conn.SetWriteDeadline and returns ErrUnsupported.

func (*Conn) Write

func (conn *Conn) Write(b []byte) (n int, err error)

Write writes the data into the 'ReliableDataChannel'. If the data exceeds 10000 bytes, it is split into multiple segments. An error may be returned while writing a segment or if the Conn has been closed by Conn.Close.

type Credentials

type Credentials struct {
	ExpirationInSeconds int         `json:"ExpirationInSeconds"`
	ICEServers          []ICEServer `json:"TurnAuthServers"`
}

Credentials holds the configuration for ICE servers used for gathering local ICE candidates.

type Dialer

type Dialer struct {
	// ConnectionID is the unique ID of a Conn being established. If zero, a random value will be automatically
	// set from [rand.Uint64].
	ConnectionID uint64

	// Log is used for logging messages at various log levels. If nil, the default [slog.Logger] will be automatically
	// set from [slog.Default]. Log will be extended when a Conn is being established by [Dialer] with additional attributes
	// such as the connection ID and network ID, and will have a 'src' attribute set to 'dialer' to mark that the Conn
	// has been negotiated by Dialer.
	Log *slog.Logger

	// API specifies custom configuration for WebRTC transports and data channels. If nil, a new [webrtc.API] will be
	// set from [webrtc.NewAPI]. The [webrtc.SettingEngine] of the API should not allow detaching data channels, as it requires
	// additional steps on the Conn (which cannot be determined by the Conn).
	API *webrtc.API

	// Identity specifies the identity presented to the remote peer during
	// connection negotiation.
	//
	// When set to non-nil, an 'a=identity' attribute is attached to the SDP offer
	// and used to authenticate the client and bind its identity to the WebRTC peer
	// connection.
	//
	// When set to nil, no identity assertion is included in the offer.
	Identity *Identity
	// VerifyServerToken verifies the token contained in a server's identity
	// assertion and returns the public key populated in its 'cpk' claim.
	//
	// The returned public key is used to verify the fingerprint assertion
	// carried in the server answer's 'a=identity' attribute.
	//
	// When [Dialer.AllowIdentitylessServer] is set to true, VerifyServerToken may never be called.
	//
	// By default, this is set to a function that only extracts the public key
	// from the token's 'cpk' claim and trusts it unconditionally.
	VerifyServerToken func(ctx context.Context, token, domain string) (*ecdsa.PublicKey, error)

	// AllowIdentitylessServer specifies whether to allow answer SDPs without an
	// 'a=identity' attribute.
	//
	// When set to false, the server must present a valid identity assertion.
	// When set to true, unauthenticated servers are allowed to establish connections.
	//
	// This may be useful when connecting to legacy or custom implementations.
	AllowIdentitylessServer bool

	// ICEGatherPolicy limits which local ICE candidates are gathered for the
	// connection.
	//
	// It may be used to restrict connectivity to specific candidate types, such
	// as relayed candidates from TURN servers only.
	ICEGatherPolicy webrtc.ICEGatherPolicy

	// DisableTrickleICE disables trickle ICE for connection negotiation.
	//
	// When set to true, the dialer waits for ICE gathering to complete and embeds
	// all local candidates in the initial offer SDP. Otherwise, candidates are
	// signaled incrementally as separate [SignalTypeCandidate] signals after the
	// offer is sent.
	//
	// This may slow connection establishment because the initial offer cannot be
	// sent until candidate gathering completes.
	//
	// This behavior can be seen when connecting to dedicated servers with the
	// 'nethernet-disable-trickle-ice' setting property set to 'true'.
	DisableTrickleICE bool
}

Dialer encapsulates options for establishing a connection with a NetherNet network through Dialer.DialContext and other aliases. It allows customizing logging, WebRTC API settings, and contexts for a negotiation.

func (Dialer) DialContext

func (d Dialer) DialContext(ctx context.Context, networkID string, signaling Signaling) (_ *Conn, err error)

DialContext establishes a Conn with a remote network referenced by the ID. The Signaling is used to signal an offer with local candidates, and also to notify incoming signals received from the remote network. The context.Context may be used to cancel the connection as soon as possible. A Conn may be returned, that is ready to receive and send packets.

type ICEServer

type ICEServer struct {
	Username string   `json:"Username"`
	Password string   `json:"Password"`
	URLs     []string `json:"Urls"`
}

ICEServer represents a single ICE server configuration, including its authentication details and connection URLs. Each server requires a username and password for authentication.

type Identity added in v1.0.15

type Identity struct {
	// PrivateKey is the private key corresponding to the 'cpk' claim contained
	// in [Identity.Token].
	//
	// It is used to sign the SDP fingerprint assertion carried in the 'a=identity'
	// attribute, binding the authenticated identity to the WebRTC peer connection.
	//
	// For server identities, this key is also used to self-sign [Identity.Token].
	PrivateKey *ecdsa.PrivateKey
	// Token is the JWT token for this identity.
	// For client identities, this token is issued by Minecraft's authorization service.
	// For server identities, this token is self-signed by the server using the [Identity.PrivateKey].
	// The JWT token must contain the corresponding public key for [Identity.PrivateKey] as the 'cpk' claim.
	Token string
	// Domain is the domain name that may be surfaced to players on first join when
	// connecting via an insecure (non-TLS) context.
	// For server identities, this can be "self", as observed on Bedrock Dedicated Server.
	Domain string
}

Identity represents the authenticated identity used in a NetherNet peer connection.

func GenerateServerIdentity added in v1.0.15

func GenerateServerIdentity(privateKey *ecdsa.PrivateKey, domain string) (*Identity, error)

GenerateServerIdentity creates a new server Identity using the provided private key. The domain may be surfaced to players on first join when connecting via an insecure (non-TLS) context (though it is not functional in release versions somehow). The returned Identity contains a self-signed JWT token with a 1-minute expiration time and the public key embedded as the 'cpk' claim.

type ListenConfig

type ListenConfig struct {
	// Log is used for logging messages at various levels. If nil, the default [slog.Logger] will be set from
	// [slog.Default]. Log will be extended when a Conn is being accepted by [Listener.Accept] with additional
	// attributes such as the connection ID and network ID, and will have a 'src' attribute set to 'listener'
	// to mark that the Conn has been negotiated by Listener.
	Log *slog.Logger

	// API specifies custom configuration for WebRTC transports and data channels. If nil, a new [webrtc.API] will
	// be set from [webrtc.NewAPI]. The [webrtc.SettingEngine] of the API should not allow detaching data channels,
	// as it requires additional steps on the Conn (which cannot be determined by the Conn).
	API *webrtc.API

	// ConnContext provides a [context.Context] for starting the ICE, DTLS, and SCTP transports of the Conn. If nil,
	// a default [context.Context] with 5 seconds timeout will be used. The parent [context.Context] may be used to
	// create a [context.Context] to be returned (likely using [context.WithCancel] or [context.WithTimeout]).
	ConnContext func(parent context.Context, conn *Conn) (context.Context, context.CancelFunc)

	// NegotiationContext provides a [context.Context] for the negotiation. If nil, a default [context.Context]
	// with 5 seconds timeout will be used. The parent [context.Context] may be used to create a [context.Context]
	// to be returned (likely using [context.WithCancel] or [context.WithTimeout]). If the deadline of the context
	// is exceeded, a Signal of SignalTypeError with ErrorCodeNegotiationTimeoutWaitingForAccept will be signaled back.
	NegotiationContext func(parent context.Context) (context.Context, context.CancelFunc)

	// IssueServerIdentity issues the identity presented to clients in SDP answers.
	// The returned identity is used to produce the server-side 'a=identity' attribute.
	// The token must contain the public key corresponding the [Identity.PrivateKey] in
	// its 'cpk' claim.
	//
	// If set to nil, it is replaced to a function that automatically generates a
	// temporary identity. Because the generated key is not saved, clients using
	// Trust On First Use (TOFU) may treat each server restart as a different identity.
	IssueServerIdentity func(ctx context.Context) (*Identity, error)

	// VerifyClientToken verifies the token contained in a client's identity
	// assertion and returns the public key populated in its 'cpk' claim.
	// The returned public key is used to verify the fingerprint assertion
	// carried in the client offer's 'a=identity' attribute.
	//
	// Unlike identity tokens issued by servers, client tokens are issued by
	// Minecraft's authorization service and include additional information
	// such as gamertag and XUID.
	//
	// These claims may be used to implement allowlists or blocklists.
	// However, the same checks should also be enforced by the Minecraft protocol
	// layer, since a malicious client may present a different token that
	// is bound to the same public key.
	//
	// By default, this is set to a function that only extracts the public key
	// from the 'cpk' claim in the JWT token. It does not perform cryptographic
	// verification using the public keys exposed by Minecraft's authorization service,
	// as this library does not provide access to that endpoint.
	//
	// The default verifier only binds the SDP identity assertion to the public
	// key in the token. It is appropriate for Bedrock integrations only when the
	// Minecraft protocol layer also verifies the Login packet token and checks
	// that the same public key was used in its 'cpk' claim. Servers that rely on
	// NetherNet identity alone should provide a verifier that validates token
	// issuance.
	VerifyClientToken func(ctx context.Context, token string) (*ecdsa.PublicKey, error)

	// AllowAnonymous determines whether SDP offers without an 'a=identity'
	// attribute are accepted.
	// When set to false, all incoming connections must provide a valid identity
	// assertion. When set to true, unauthenticated peers are allowed to connect.
	//
	// The zero value is false. Set this explicitly for offline/custom clients
	// that do not send identity assertions.
	//
	// This may be useful for implementing offline-mode servers, but it removes
	// the identity binding normally provided by NetherNet and may allow replay
	// attacks against upstream protocols. It should therefore only be enabled
	// in trusted environments.
	AllowAnonymous bool

	// ICEGatherPolicy limits which local ICE candidates are gathered for
	// accepted connections.
	//
	// It may be used to restrict connectivity to specific candidate types, such
	// as relayed candidates from TURN servers only.
	ICEGatherPolicy webrtc.ICEGatherPolicy

	// DisableTrickleICE disables trickle ICE for connection negotiation.
	//
	// When set to true, the listener waits for ICE gathering to complete and embeds
	// all local candidates in the answer SDP. Otherwise, candidates are signaled
	// incrementally as separate [SignalTypeCandidate] signals after the answer is
	// sent.
	//
	// This may slow connection establishment because the answer cannot be sent
	// until candidate gathering completes.
	//
	// This behavior can be seen on dedicated servers with the
	// 'nethernet-disable-trickle-ice' setting property set to 'true'.
	DisableTrickleICE bool
}

ListenConfig encapsulates options for creating a new Listener through ListenConfig.Listen. It allows customizing logging, WebRTC API settings, and contexts for negotiations.

func (ListenConfig) Listen

func (conf ListenConfig) Listen(signaling Signaling) (*Listener, error)

Listen listens on the local network ID specified by the Signaling implementation. It returns a Listener that may be used to accept established connections from Listener.Accept. Signaling will be used to notify incoming Signals from remote connections.

type Listener

type Listener struct {
	// contains filtered or unexported fields
}

Listener implements a NetherNet connection listener.

func (*Listener) Accept

func (l *Listener) Accept() (net.Conn, error)

Accept waits for and returns the next Conn to the Listener. An error may be returned, if the Listener has been closed.

func (*Listener) Addr

func (l *Listener) Addr() net.Addr

Addr returns an Addr that represents the local network ID of the Listener.

func (*Listener) Close

func (l *Listener) Close() error

Close closes the Listener, ensuring that any blocking methods will return net.ErrClosed as an error.

func (*Listener) Context

func (l *Listener) Context() context.Context

Context returns a context that is canceled when the Listener is closed.

func (*Listener) ID

func (l *Listener) ID() int64

ID returns the network ID of Listener.

func (*Listener) NotifySignal added in v1.0.15

func (l *Listener) NotifySignal(signal *Signal) bool

NotifySignal handles an incoming Signal from the remote network and reports whether it was accepted for processing.

func (*Listener) PongData

func (l *Listener) PongData(b []byte)

PongData is a stub.

type MessageReliability

type MessageReliability uint8

MessageReliability represents the reliability of messages sent in a data channel. It is an internal type specific to this package's implementation, and shouldn't be sent over network in any way.

const (
	// MessageReliabilityReliable guarantees the ordering of messages. Currently, this is the
	// only reliability parameter used in the game.
	MessageReliabilityReliable MessageReliability = iota
	// MessageReliabilityUnreliable seems to be unused, and it is unclear how it
	// works with multiple segments as packet drops could leave the message data
	// in unconstructed state.
	// While it is technically possible to send or receive packets in this channel,
	// it is currently recommended to use only MessageReliabilityReliable.
	MessageReliabilityUnreliable
)

func (MessageReliability) Parameters

Parameters returns a webrtc.DataChannelParameters, which may be used for creating a data channel for the MessageReliability or to ensure that a data channel is valid to handle it in the Conn.

func (MessageReliability) Valid

func (r MessageReliability) Valid(channel *webrtc.DataChannel) bool

Valid determines whether the webrtc.DataChannel can be safe to use in Conn. If the data channel does not have the exact same parameters returned by MessageReliability.Parameters, it will return false.

type Notifier added in v1.0.15

type Notifier interface {
	// NotifySignal handles an incoming Signal from a remote network. It must
	// return promptly and must not block the Signaling implementation. It
	// reports whether the Signal was accepted for processing.
	NotifySignal(signal *Signal) bool
}

Notifier receives incoming Signals from a Signaling implementation.

type Signal

type Signal struct {
	// Type indicates the type of Signal. It is one of constants defined above.
	Type string

	// ConnectionID is the unique ID of the connection that has sent the Signal.
	// It is used by both server and client to uniquely reference the connection.
	ConnectionID uint64

	// Data is the actual data of the Signal, represented as a string.
	Data string

	// NetworkID is the internal ID used by Signaling to reference a remote network and not
	// included to the String representation to be signaled to the remote network. If sent by
	// a server, it represents the sender ID. If sent by a client, it represents the recipient ID.
	NetworkID string
}

Signal represents a signal sent or received to negotiate a connection in NetherNet network.

func (*Signal) MarshalText

func (s *Signal) MarshalText() ([]byte, error)

MarshalText returns the bytes of a string representation returned from Signal.String.

func (*Signal) String

func (s *Signal) String() string

String returns a string representation of the Signal in the format 'Signal.Type Signal.ConnectionID Signal.Data'.

func (*Signal) UnmarshalText

func (s *Signal) UnmarshalText(b []byte) (err error)

UnmarshalText decodes the text into the Signal. An error may be returned, if the text is invalid or does not follow the format 'Signal.Type Signal.ConnectionID Signal.Data'.

type Signaling

type Signaling interface {
	// Signal sends a Signal to a remote network referenced by [Signal.NetworkID].
	// The [context.Context] is used to cancel waiting for the acknowledgement from
	// the signaling server as soon as possible.
	Signal(ctx context.Context, signal *Signal) error

	// Notify registers n for receiving incoming signals from remote networks.
	// Each call creates an independent subscription; incoming signals are
	// broadcast to all active subscriptions, not load-balanced between them.
	// The returned stop function unregisters n and must be safe to call
	// multiple times.
	Notify(n Notifier) (stop func())

	// Context returns a context for Signaling that is canceled optionally with a cause when a fatal
	// error has occurred on the signaling server. It is used by both Dialer and Listener to notify
	// a fatal error so they can no longer listen or dial for a connection that is no longer notified.
	Context() context.Context

	// Credentials blocks until Credentials are received by Signaling, and returns them. If Signaling
	// does not support returning Credentials, it will return nil. Credentials are typically received
	// from a WebSocket connection. The [context.Context] may be used to cancel the blocking.
	Credentials(ctx context.Context) (*Credentials, error)

	// NetworkID returns the local network ID of Signaling. It is used by Listener to obtain its local
	// network ID.
	NetworkID() string

	// PongData sets the server data in the format of a RakNet pong response. It is used by the Listener
	// to respond to a ping request in the correct format.
	PongData(b []byte)
}

Signaling implements an interface for sending and receiving Signals over a network.

Directories

Path Synopsis
examples
endpoint/client command
endpoint/server command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL