endpoint

package
v1.0.24 Latest Latest
Warning

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

Go to latest
Published: Sep 25, 2026 License: MIT Imports: 16 Imported by: 1

Documentation

Index

Examples

Constants

View Source
const (
	GameTypeSurvival = iota
	GameTypeCreative
	GameTypeAdventure
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

Client implements nethernet.Signaling using the HTTP endpoints exposed by a NetherNet server.

Example

ExampleClient demonstrates how to connect to a NetherNet server using HTTP signaling.

// Create a signaling client.
// This client is responsible for exchanging WebRTC connection details with the server over HTTP.
client := NewClient()

// Establish a NetherNet connection using the client for the signaling.
var d nethernet.Dialer
conn, err := d.DialContext(context.TODO(), "https://localhost:19132", client)
if err != nil {
	panic(fmt.Sprintf("error connecting to server: %s", err))
}
defer conn.Close()

fmt.Printf("connected, latency: %s", conn.Latency())

func NewClient

func NewClient() *Client

NewClient creates a new Client with the default ClientConfig. It is equivalent to calling ClientConfig{}.New().

func (*Client) Context

func (c *Client) Context() context.Context

Context always returns context.Background.

func (*Client) Credentials

func (c *Client) Credentials(ctx context.Context) (*nethernet.Credentials, error)

Credentials returns a nethernet.Credentials using the ClientConfig.Credentials if possible. Otherwise, it returns an empty nethernet.Credentials. It is optimal for the caller to provide ClientConfig.Credentials containing STUN/TURN servers in order to stabilize WebRTC peer negotiations.

func (*Client) DisableTrickleICE

func (c *Client) DisableTrickleICE() bool

DisableTrickleICE always returns true as it is not supported because the HTTP request-response model requires the full SDP exchange to complete within a single round trip. A peer connection should wait for all local ICE candidates to be gathered and include them as SDP attributes in the initial offer.

func (*Client) NetworkID

func (c *Client) NetworkID() string

NetworkID returns a network ID assigned for this Client. It is included to the URL path of requests sent to servers. Callers can specify this value from ClientConfig.NetworkID.

func (*Client) Notify

func (c *Client) Notify(n nethernet.Notifier) (stop func())

Notify registers n to receive incoming NetherNet signals.

func (*Client) PingContext added in v1.0.22

func (c *Client) PingContext(ctx context.Context, address string) ([]byte, error)

PingContext sends a ping request to the given address and returns the pong data in the same format used with RakNet transport. It is useful for older code that still expects that format.

func (*Client) PongData

func (c *Client) PongData([]byte)

PongData is unsupported on Client because endpoint clients only dial and do not receive server ping data.

func (*Client) Signal

func (c *Client) Signal(ctx context.Context, signal *nethernet.Signal) error

Signal sends a Signal to the remote endpoint.

Only nethernet.SignalTypeOffer is supported. The returned SDP answer is delivered to the Dialers registered to this Client.

func (*Client) Status added in v1.0.23

func (c *Client) Status(ctx context.Context, address string) (Status, error)

Status sends a ping request to the given address and returns the Status reported by the server. The returned Status can also be converted to RakNet-compatible pong data via Status.RakNet, for use with older code that still expects that format.

Example

ExampleClient_Status demonstrates how to retrieve a status for a NetherNet server.

// Create a client.
client := NewClient()

// Query the server status at the specific address. The address can be an HTTP or HTTPS URL with a port number.
status, err := client.Status(context.TODO(), "http://127.0.0.1:19132")
if err != nil {
	panic(err)
}

fmt.Println(strconv.Quote(status.ServerName)) // "Dedicated Server"

type ClientConfig

type ClientConfig struct {
	// HTTPClient is the HTTP client used for making HTTP requests to the remote servers.
	// If nil, [http.DefaultClient] will be used instead.
	HTTPClient *http.Client

	// Credentials is an optional function that supplies ICE credentials
	// to the ICE gatherer used by the peer connection.
	// When nil, [Handler.Credentials] returns an empty [nethernet.Credentials]
	// with no STUN/TURN servers, which may reduce NAT traversal reliability.
	Credentials func(ctx context.Context) (*nethernet.Credentials, error)

	// Logger is used to log messages produced when handling requests.
	// If nil, it will be set from [slog.Default].
	Logger *slog.Logger

	// NetworkID is the identifier assigned to this Handler.
	// It is included to the URL path of requests sent to servers.
	// If empty, a random uint64 is generated and used.
	NetworkID string
}

ClientConfig represents a configuration for creating a Client.

func (ClientConfig) New

func (conf ClientConfig) New() *Client

New returns a new Client from the configuration. The resulting Client can be passed to nethernet.Dialer.DialContext.

type Handler

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

Handler is an http.Handler that negotiates incoming NetherNet connections over HTTP. Callers can create a Handler from NewHandler or HandlerConfig.New, then pass it to http.ListenAndServeTLS or assign to http.Server.Handler.

Currently, Handler implements the following endpoints:

  • GET /v1/join (ping)
  • POST /v1/join/{networkID} (WebRTC negotiation)

On an address join a Bedrock client discovers this endpoint by sending the GET /v1/join ping to each candidate URL in order, stopping at the first that responds: https://host:port, https://host (443), http://host:port, then http://host (80). An explicit port collapses the list to the https/http variants on that port. If none respond the client falls back to RakNet, so a server that serves this Handler is reached over NetherNet in preference to a RakNet listener on the same address.

Example

ExampleHandler demonstrates how to expose a NetherNet listener using HTTP/TLS server for signaling.

handler, err := Serve(":19132")
if err != nil {
	panic(fmt.Sprintf("error listening on HTTP: %s", err))
}
defer handler.Close()

// Set up a NetherNet listener.
var cfg nethernet.ListenConfig
l, err := cfg.Listen(handler)
if err != nil {
	panic(fmt.Sprintf("error listening on NetherNet: %s", err))
}
defer l.Close()

// Start accepting NetherNet connections.
for {
	conn, err := l.Accept()
	if err != nil {
		return
	}
	slog.Info("connected",
		"remoteAddr", conn.RemoteAddr(),
		"localAddr", conn.LocalAddr(),
		"latency", conn.(*nethernet.Conn).Latency(),
	)
}

func NewHandler

func NewHandler() *Handler

NewHandler creates a new Handler with default HandlerConfig values and returns it. It is equivalent to calling HandlerConfig{}.New().

func Serve added in v1.0.22

func Serve(address string) (*Handler, error)

Serve is a utility method that sets up an HTTP server on the specified address. It is equivalent of calling HandlerConfig{}.Serve().

func ServeTLS added in v1.0.16

func ServeTLS(address string, certFile, keyFile string) (*Handler, error)

ServeTLS is a utility method that sets up an HTTP/TLS server on the specified address using the TLS certificate and key file. It is equivalent of calling HandlerConfig{}.ServeTLS().

func (*Handler) Addr added in v1.0.24

func (h *Handler) Addr() net.Addr

Addr returns the TCP address used by the underlying HTTP server. It may be nil if the Handler has not been created using HandlerConfig.Serve or HandlerConfig.ServeTLS.

func (*Handler) Close added in v1.0.16

func (h *Handler) Close() error

Close closes the underlying HTTP server, if one is bound. Otherwise, Close is no-op.

func (*Handler) Context

func (h *Handler) Context() context.Context

Context returns the background context of the underlying HTTP server, if one is bound to this Handler. Otherwise, Context always returns context.Background.

func (*Handler) Credentials

func (h *Handler) Credentials(ctx context.Context) (*nethernet.Credentials, error)

Credentials returns a nethernet.Credentials using the HandlerConfig.Credentials if possible. Otherwise, it returns an empty nethernet.Credentials. It is optimal for the caller to provide HandlerConfig.Credentials containing STUN/TURN servers in order to stabilize WebRTC peer negotiations.

func (*Handler) DisableTrickleICE

func (h *Handler) DisableTrickleICE() bool

DisableTrickleICE always returns true as it is not supported because the HTTP request-response model requires the full SDP exchange to complete within a single round trip. A peer connection should wait for all local ICE candidates to be gathered and include them as SDP attributes in the initial offer.

func (*Handler) NetworkID

func (h *Handler) NetworkID() string

NetworkID returns a network ID assigned for this Handler. This is never transmitted to clients and is currently only used for locally identifying this Handler.

func (*Handler) Notify

func (h *Handler) Notify(n nethernet.Notifier) (stop func())

Notify registers n to receive incoming HTTP endpoint offers.

func (*Handler) PongData

func (h *Handler) PongData(data []byte)

PongData is a no-op implementation of nethernet.Signaling.PongData. It may become meaningful in the future if Mojang introduces an HTTP endpoint for serving MOTDs.

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP implements http.Handler by delegating the given response writer and the request to the internal http.ServeMux.

func (*Handler) Signal

func (h *Handler) Signal(ctx context.Context, signal *nethernet.Signal) error

Signal delivers a signal to the pending negotiation identified by the nethernet.Signal.NetworkID and nethernet.Signal.ConnectionID.

func (*Handler) Status added in v1.0.22

func (h *Handler) Status(status Status)

Status sets the server status that the Handler responds with for HTTP requests sent by clients. Note that if the upstream game listener also provides pong data via Handler.PongData, that data will take precedence, since Handler.PongData overwrites the status set here. Callers can set HandlerConfig.DisablePongData to true to disable this behavior.

type HandlerConfig

type HandlerConfig struct {
	// Logger is used to log messages produced when handling requests.
	// If nil, it will be set from [slog.Default].
	Logger *slog.Logger

	// NegotiationContext returns the [context.Context] that controls how long
	// the Handler waits for the listener to produce an SDP answer.
	// The resulting [context.Context] must be derived from the parent context.
	// If nil, a context with a 15-second timeout will be returned.
	NegotiationContext func(parent context.Context) (context.Context, context.CancelFunc)

	// Credentials is an optional function that supplies ICE credentials
	// to the ICE gatherer used by the peer connection.
	// When nil, [Handler.Credentials] returns an empty [nethernet.Credentials]
	// with no STUN/TURN servers, which may reduce NAT traversal reliability.
	Credentials func(ctx context.Context) (*nethernet.Credentials, error)

	// NetworkID is the identifier assigned to this Handler.
	// It is used only for identifying Handler and is never transmitted to clients.
	// If empty, a random uint64 is generated and used.
	NetworkID string

	// DisablePongData specifies whether to disable syncing with the RakNet pong
	// data provided by the upstream game protocol. When set to true, [Handler.PongData]
	// becomes no-op.
	DisablePongData bool
}

HandlerConfig represents a configuration for creating a Handler.

func (HandlerConfig) New

func (conf HandlerConfig) New() *Handler

New returns a new Handler from the configuration. The resulting Handler can be passed directly to http.ListenAndServeTLS or assigned to http.Server.Handler.

func (HandlerConfig) Serve added in v1.0.22

func (conf HandlerConfig) Serve(address string) (*Handler, error)

Serve is a utility method that sets up an HTTP server on the specified address.

func (HandlerConfig) ServeTLS added in v1.0.16

func (conf HandlerConfig) ServeTLS(address string, certFile, keyFile string) (*Handler, error)

ServeTLS is a utility method that sets up an HTTP/TLS server on the specified address using the TLS certificate and key file.

type Status added in v1.0.22

type Status struct {
	// ServerName is the name of the server. It is displayed as the MOTD.
	ServerName string `json:"name"`
	// Protocol is the protocol version used by the upstream game listener.
	Protocol int `json:"protocol"`
	// Version is the version of the game that the server is currently running.
	Version string `json:"version"`
	// LevelName is the name of the world. It is never displayed in the server card in Multiplayer tab.
	LevelName string `json:"level"`
	// PlayerCount is the number of players that is currently connected to the server.
	PlayerCount int `json:"players"`
	// MaxPlayerCount is the number of players that can be connected to the server.
	MaxPlayerCount int `json:"maxPlayers"`
	// GameType represents the game mode of the level running in the server in numerical value.
	// It is 0 for survival, 1 for creative, and 2 for adventure.
	GameType int `json:"gameType"`
}

Status represents a server status of a NetherNet server.

func RakNetPongData added in v1.0.22

func RakNetPongData(b []byte) (Status, error)

RakNetPongData parses a RakNet-compatible pong data into a Status. It is typically used for maintaining compatibility with older code that still produces the same format used in RakNet servers, e.g. Gophertunnel. It is also used in Handler.PongData to synchronize the status with the upstream game listener.

func (Status) RakNet added in v1.0.23

func (s Status) RakNet() []byte

RakNet produces a RakNet-compatible pong data from the status. It is typically used for maintaining compatibility with older code that still expects the same format used in RakNet servers. The port included in the resulting data is always 19132.

func (Status) RakNetPongData deprecated added in v1.0.22

func (s Status) RakNetPongData() []byte

RakNetPongData produces a RakNet-compatible pong data from the status. It is typically used for maintaining compatibility with older code that still expects the same format used in RakNet servers. The port included in the resulting data is always 19132.

Deprecated: Use Status.RakNet instead.

Jump to

Keyboard shortcuts

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