v1.39.1 Latest Latest

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

Go to latest
Published: Jan 31, 2023 License: GPL-3.0 Imports: 28 Imported by: 0



Package wsnet handles client and server ends of Workspace networking negotiations and protocol.




View Source
const (
	CodeDialErr       = "dial_error"
	CodePermissionErr = "permission_error"
	CodeBadAddressErr = "bad_address_error"

Codes for DialChannelResponse.


View Source
var (
	// ErrMismatchedProtocol occurs when a TURN is requested to a STUN server,
	// or a TURN server is requested instead of TURNS.
	ErrMismatchedProtocol = errors.New("mismatched protocols")
	// ErrInvalidCredentials occurs when invalid credentials are passed to a
	// TURN server. This error cannot occur for STUN servers, as they don't accept
	// credentials.
	ErrInvalidCredentials = errors.New("invalid credentials")


func ConnectEndpoint

func ConnectEndpoint(baseURL *url.URL, workspace, token string) string

ConnectEndpoint returns the Coder endpoint to dial a connection for a workspace.

func DialICE

func DialICE(server webrtc.ICEServer, options *DialICEOptions) error

DialICE confirms ICE servers are dialable. Timeout defaults to 200ms.

func Listen

func Listen(ctx context.Context, log slog.Logger, broker string, turnProxyAuthToken string) (io.Closer, error)

Listen connects to the broker proxies connections to the local net. Close will end all RTC connections.

func ListenEndpoint

func ListenEndpoint(baseURL *url.URL, token string) string

ListenEndpoint returns the Coder endpoint to listen for workspace connections.

func TURNProxyICECandidate added in v1.21.0

func TURNProxyICECandidate() webrtc.ICEServer

TURNWebSocketICECandidate returns a fake TCP relay ICEServer. It's used to trigger the ICEProxyDialer.


type BrokerMessage added in v1.21.0

type BrokerMessage struct {
	// Dialer -> Listener
	Offer        *webrtc.SessionDescription `json:"offer"`
	Servers      []webrtc.ICEServer         `json:"servers"`
	TURNProxyURL string                     `json:"turn_proxy_url"`

	// Policies denote which addresses the client can dial. If empty or nil, all
	// addresses are permitted.
	Policies []DialPolicy `json:"ports"`

	// Listener -> Dialer
	Error  string                     `json:"error"`
	Answer *webrtc.SessionDescription `json:"answer"`

	// Bidirectional
	Candidate string `json:"candidate"`

BrokerMessage is used for brokering a dialer and listener.

Dialers initiate an exchange by providing an Offer, along with a list of ICE servers for the listener to peer with.

The listener should respond with an offer, then both sides can begin exchanging candidates.

type DialChannelResponse added in v1.21.0

type DialChannelResponse struct {
	Code string
	Err  string
	// Fields are set if the code is CodeDialErr.
	Net string
	Op  string

DialChannelResponse is used to notify a dial channel of a listening state. Modeled after net.OpError, and marshalled to that if Net is not "".

type DialICEOptions

type DialICEOptions struct {
	Timeout time.Duration
	// Whether to ignore TLS errors.
	InsecureSkipVerify bool

DialICEOptions provides options for dialing an ICE server.

type DialOptions added in v1.21.0

type DialOptions struct {
	// Logger is an optional logger to use for logging mostly debug messages. If
	// set to nil, nothing will be logged.
	Log *slog.Logger

	// ICEServers is an array of STUN or TURN servers to use for negotiation purposes.
	// See:
	ICEServers []webrtc.ICEServer

	// TURNProxyAuthToken is used to authenticate a TURN proxy request.
	TURNProxyAuthToken string

	// TURNRemoteProxyURL is the URL to proxy listener TURN data through.
	TURNRemoteProxyURL *url.URL

	// TURNLocalProxyURL is the URL to proxy client TURN data through.
	TURNLocalProxyURL *url.URL

DialOptions are configurable options for a wsnet connection.

type DialPolicy added in v1.21.0

type DialPolicy struct {
	// If network is empty, it applies to all networks.
	Network string `json:"network"`
	// Host is the IP or hostname of the address. It should not contain the
	// port.If empty, it applies to all hosts. "localhost", [::1], and any IPv4
	// address under "" can be used interchangeably.
	Host string `json:"address"`
	// If port is 0, it applies to all ports.
	Port uint16 `json:"port"`

DialPolicy a single network + address + port combinations that a connection is permitted to use.

type Dialer

type Dialer struct {
	// contains filtered or unexported fields

Dialer enables arbitrary dialing to any network and address inside a workspace. The opposing end of the WebSocket messages should be proxied with a Listener.

func Dial

func Dial(ctx context.Context, conn net.Conn, options *DialOptions) (*Dialer, error)

Dial negotiates a connection to a listener.

Example (Basic)
servers := []webrtc.ICEServer{{
	URLs:           []string{""},
	Username:       "kyle",
	Credential:     "pass",
	CredentialType: webrtc.ICECredentialTypePassword,

for _, server := range servers {
	err := DialICE(server, nil)
	if errors.Is(err, ErrInvalidCredentials) {
		// You could do something...
	if errors.Is(err, ErrMismatchedProtocol) {
		// Likely they used TURNS when they should have used TURN.
		// Or they could have used TURN instead of TURNS.

dialer, err := DialWebsocket(context.Background(), "wss://", &DialOptions{
	ICEServers: servers,
}, nil)
if err != nil {
	// Do something...
conn, err := dialer.DialContext(context.Background(), "tcp", "localhost:13337")
if err != nil {
	// Something...
defer conn.Close()
// You now have access to the proxied remote port in `conn`.

func DialWebsocket

func DialWebsocket(ctx context.Context, broker string, netOpts *DialOptions, wsOpts *websocket.DialOptions) (*Dialer, error)

DialWebsocket dials the broker with a WebSocket and negotiates a connection.

func (*Dialer) Candidates added in v1.21.6

func (d *Dialer) Candidates() (*webrtc.ICECandidatePair, error)

Candidates returns the candidate pair that was chosen for the connection.

func (*Dialer) Close

func (d *Dialer) Close() error

Close closes the RTC connection. All data channels dialed will be closed.

func (*Dialer) DialContext

func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error)

DialContext dials the network and address on the remote listener.

func (*Dialer) Ping

func (d *Dialer) Ping(ctx context.Context) error

Ping sends a ping through the control channel.

type DialerCache added in v1.21.0

type DialerCache struct {
	// contains filtered or unexported fields

func DialCache added in v1.21.0

func DialCache(ttl time.Duration) *DialerCache

DialCache constructs a new DialerCache. The cache clears connections that: 1. Are older than the TTL and have no active user-created connections. 2. Have been closed.

func (*DialerCache) Close added in v1.21.0

func (d *DialerCache) Close() error

Close closes all cached dialers.

func (*DialerCache) Dial added in v1.21.0

func (d *DialerCache) Dial(ctx context.Context, key string, dialerFunc func() (*Dialer, error)) (*Dialer, bool, error)

Dial returns a Dialer from the cache if one exists with the key provided, or dials a new connection using the dialerFunc. The bool returns whether the connection was found in the cache or not.

Jump to

Keyboard shortcuts

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