Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/openlibrecommunity/olcrtc/llms.txt

Use this file to discover all available pages before exploring further.

olcRTC exposes two embeddable Go packages: pkg/olcrtc provides a client session that returns a net.Conn-compatible handle backed by a WebRTC data channel, while pkg/olcrtc/tunnel provides the server-side tunnel that accepts encrypted connections and proxies them to arbitrary TCP targets. Both packages can be imported independently into any Go program.

Installation

go get github.com/openlibrecommunity/olcrtc

pkg/olcrtc

Import path: github.com/openlibrecommunity/olcrtc/pkg/olcrtc This package implements the client half of the tunnel. It handles authentication with a built-in provider (jitsi, telemost, wbstream) or connects directly to any LiveKit-compatible SFU, then returns a net.Conn whose reads and writes are transparently relayed over WebRTC.
You must register the engine and auth provider implementations before calling New. Either add the necessary blank imports yourself, or call olcrtc.RegisterDefaults() once at program start to get all built-in providers and engines in one call.

RegisterDefaults

func RegisterDefaults()
Registers all built-in engines (livekit, goolom, jitsi) and auth providers (jitsi, telemost, wbstream). Safe to call multiple times. Use this when you do not want to manage blank imports manually.
import "github.com/openlibrecommunity/olcrtc/pkg/olcrtc"

func main() {
    olcrtc.RegisterDefaults()
    // ...
}
Alternatively, import only what you need:
import (
    _ "github.com/openlibrecommunity/olcrtc/internal/engine/jitsi"
    _ "github.com/openlibrecommunity/olcrtc/internal/auth/jitsi"
)

Config

Config is the input to New. Fill only the fields that apply to your mode.
type Config struct {
    // --- built-in auth mode ---
    // Auth is the name of a registered auth provider ("jitsi", "telemost", "wbstream").
    // When set, RoomID is forwarded to the provider as the room reference.
    Auth   string
    RoomID string

    // --- direct engine mode (Auth == "") ---
    // Engine selects the SFU protocol ("livekit", "goolom", "jitsi").
    // Defaults to "livekit" when Auth is empty.
    Engine string
    URL    string
    Token  string

    // --- common ---
    // Name is the display name used when joining the room.
    Name string
    // DNSServer is an optional custom DNS resolver (e.g. "8.8.8.8:53").
    DNSServer string
    // ProxyAddr / ProxyPort configure an outbound SOCKS5 proxy.
    ProxyAddr string
    ProxyPort int
}
FieldTypeDescription
AuthstringBuilt-in auth provider name: "jitsi", "telemost", or "wbstream". When set, auth mode is used and RoomID is forwarded to the provider.
RoomIDstringRoom reference for the auth provider — typically the full Jitsi room URL, e.g. "https://meet.example.org/myroom".
EnginestringDirect engine mode: "livekit", "goolom", or "jitsi". Defaults to "livekit" when Auth is empty.
URLstringSFU WebSocket URL for direct engine mode (e.g. "wss://sfu.example/").
TokenstringJWT token for direct engine mode.
NamestringDisplay name used when joining the conference room.
DNSServerstringOptional custom DNS resolver address, e.g. "8.8.8.8:53".
ProxyAddrstringOutbound SOCKS5 proxy host.
ProxyPortintOutbound SOCKS5 proxy port.

Session

Session is the library handle returned by New. It is not connected until Dial or Connect is called.
type Session struct { /* ... */ }

New

func New(ctx context.Context, cfg Config) (*Session, error)
Creates a Session from cfg. If cfg.Auth is set, the built-in auth provider is used; otherwise direct engine mode applies (requires URL and Token). Returns ErrURLRequired or ErrTokenRequired when required direct-mode fields are missing. Returns an error if the named auth provider is not registered.

Dial

func (s *Session) Dial(ctx context.Context) (net.Conn, error)
Connects to the SFU and returns a net.Conn backed by the WebRTC data channel. This is the highest-level entry point — it calls Connect internally, starts the connection watcher in a goroutine, and wraps everything in a net.Conn interface. The returned net.Conn:
  • Read is backed by an io.Pipe fed by the engine’s OnData callback.
  • Write calls the engine’s Send method.
  • SetDeadline / SetReadDeadline / SetWriteDeadline return errors.ErrUnsupported — use context cancellation instead.
  • When the session ends permanently, Read returns ErrSessionEnded.

Connect

func (s *Session) Connect(ctx context.Context) error
Establishes the WebRTC connection. Blocks until the data channel (or media channel) is ready, or until ctx is cancelled. Lower-level than Dial — use Dial unless you need manual control.

Send

func (s *Session) Send(data []byte) error
Queues data for transmission over the data channel.

Close

func (s *Session) Close() error
Tears down the session and releases all resources.

WatchConnection

func (s *Session) WatchConnection(ctx context.Context)
Monitors the connection and handles automatic reconnects. Dial launches this in a background goroutine. Call it manually only if you are using Connect directly.

CanSend

func (s *Session) CanSend() bool
Reports whether the session is currently ready to accept outgoing data.

SetEndedCallback

func (s *Session) SetEndedCallback(cb func(reason string))
Registers a function that is called when the session ends permanently — after reconnect exhaustion or an explicit Close. The reason string describes why the session ended.

SetShouldReconnect

func (s *Session) SetShouldReconnect(fn func() bool)
Controls whether automatic reconnection is attempted after a disconnect. Return false from fn to disable reconnection.

CreateRoom

func CreateRoom(ctx context.Context, authName string) (string, error)
Creates a new room via the named auth provider and returns the room ID. Only works for providers that implement room creation. Built-in providers (jitsi, telemost, wbstream) currently return ErrRoomCreationUnsupported.

Error Variables

VariableDescription
ErrURLRequiredReturned when direct engine mode is used without setting Config.URL.
ErrTokenRequiredReturned when direct engine mode is used without setting Config.Token.
ErrRoomCreationUnsupportedReturned by CreateRoom when the auth provider does not support room creation.
ErrSessionEndedReturned from Read/Write on the net.Conn when the session has ended permanently.

Code Examples

package main

import (
    "context"
    "fmt"
    "io"
    "log"

    "github.com/openlibrecommunity/olcrtc/pkg/olcrtc"
)

func main() {
    // Register all built-in engines and auth providers.
    olcrtc.RegisterDefaults()

    ctx := context.Background()

    sess, err := olcrtc.New(ctx, olcrtc.Config{
        Auth: "jitsi",
        // Use meet.small-dm.ru, meet1.arbitr.ru, or meet.handyweb.org
        // whichever works in your network.
        RoomID: "https://meet.small-dm.ru/myroom",
    })
    if err != nil {
        log.Fatal(err)
    }

    // Dial blocks until the WebRTC data channel is ready.
    conn, err := sess.Dial(ctx)
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    // conn implements net.Conn — pass it to sing-box, an HTTP client,
    // or any other io.ReadWriter consumer.
    _, err = fmt.Fprintf(conn, "CONNECT example.com:443 HTTP/1.1\r\n\r\n")
    if err != nil {
        log.Fatal(err)
    }

    buf := make([]byte, 4096)
    n, err := conn.Read(buf)
    if err != nil && err != io.EOF {
        log.Fatal(err)
    }
    fmt.Printf("received %d bytes: %s\n", n, buf[:n])
}

pkg/olcrtc/tunnel

Import path: github.com/openlibrecommunity/olcrtc/pkg/olcrtc/tunnel This package implements the server half of the tunnel. A Server connects to a WebRTC SFU room, accepts encrypted smux streams from clients, and proxies each stream to the client-requested TCP target.
In the tunnel API, the Carrier field in Config is kept for compatibility with existing integrations. Semantically it is the auth.provider name — the same values apply: "jitsi", "telemost", "wbstream", "none".

RegisterDefaults (tunnel)

func RegisterDefaults()
Registers the built-in carriers (jitsi, telemost, wbstream), links, and transports (datachannel, videochannel, seichannel, vp8channel). Safe to call multiple times.

Config

type Config struct {
    // --- carrier selection ---
    Transport string // "datachannel", "videochannel", "seichannel", "vp8channel"
    Carrier   string // "jitsi", "telemost", "wbstream", "none"
    RoomURL   string // conference room identifier for the carrier

    // --- direct engine mode (Carrier == "none") ---
    Engine string // "livekit", "goolom", "jitsi"
    URL    string
    Token  string

    // --- crypto & networking ---
    KeyHex         string // 64-char hex (32 bytes) shared with the client
    DNSServer      string // resolver used for target dials, e.g. "8.8.8.8:53"
    SOCKSProxyAddr string // optional outbound SOCKS5 proxy host
    SOCKSProxyPort int    // optional outbound SOCKS5 proxy port
    SOCKSProxyUser string // optional username for SOCKS5 proxy auth (RFC 1929)
    SOCKSProxyPass string // optional password for SOCKS5 proxy auth (RFC 1929)

    // --- transport tuning ---
    // TransportOptions carries transport-specific tuning.
    // Pass a value from the corresponding transport package, or nil
    // for transports that need no extra configuration (datachannel).
    TransportOptions TransportOptions

    // --- hooks ---
    AuthHook       AuthFunc        // authorizes the client after CLIENT_HELLO
    OnSessionOpen  SessionOpenFunc // fires after a successful handshake
    OnSessionClose SessionCloseFunc // fires when a session ends
    OnTraffic      TrafficFunc     // fires once per tunnel stream after copy loops finish
}
FieldDescription
TransportWebRTC transport to use: "datachannel", "videochannel", "seichannel", or "vp8channel".
CarrierAuth provider / carrier name: "jitsi", "telemost", "wbstream", or "none" for direct engine mode.
RoomURLThe conference room identifier passed to the carrier (e.g. a Jitsi room URL).
EngineDirect engine name when Carrier == "none": "livekit", "goolom", or "jitsi".
URLSFU WebSocket URL for direct engine mode.
TokenJWT for direct engine mode.
KeyHex64-character hex string (32 bytes) — the shared encryption key. Generate with openssl rand -hex 32. Must match the client.
DNSServerCustom DNS resolver for target TCP dials, e.g. "8.8.8.8:53".
SOCKSProxyAddrOutbound SOCKS5 proxy host for target connections.
SOCKSProxyPortOutbound SOCKS5 proxy port.
SOCKSProxyUserSOCKS5 proxy username (RFC 1929).
SOCKSProxyPassSOCKS5 proxy password (RFC 1929).
TransportOptionsTransport-specific tuning (e.g. vp8channel.Options). Pass nil for datachannel.
AuthHookfunc(deviceID string, claims map[string]any) (string, error) — authorizes the client and issues a session ID. Returning a non-nil error rejects the handshake. If nil, every client is admitted with a random UUID.
OnSessionOpenfunc(sid, dev string, claims map[string]any) — fires after a successful handshake, before tunnel streams are accepted.
OnSessionClosefunc(sid, reason string) — fires when a session ends. Reason is "reconnect" or "closed".
OnTrafficfunc(sid, addr string, in, out uint64) — fires once per tunnel stream; in = client→target bytes, out = target→client bytes.

New

func New(cfg Config) *Server
Returns a Server configured by cfg. The server is not started until Run is called.

Run

func (s *Server) Run(ctx context.Context) error
Starts the server and blocks until ctx is cancelled or the carrier disconnects. Returns an error if the carrier cannot be reached or if the server exits abnormally.

Code Example

package main

import (
    "context"
    "log"

    "github.com/openlibrecommunity/olcrtc/pkg/olcrtc/tunnel"
)

func main() {
    // Register built-in carriers, links, and transports.
    tunnel.RegisterDefaults()

    srv := tunnel.New(tunnel.Config{
        Transport: "datachannel",
        Carrier:   "jitsi",
        // Use the Jitsi instance that works in your network.
        RoomURL:   "https://meet.small-dm.ru/myroom",
        KeyHex:    "<64-char hex key>",
        DNSServer: "8.8.8.8:53",

        // Optional: authorize each client after CLIENT_HELLO.
        AuthHook: func(deviceID string, claims map[string]any) (string, error) {
            // Reject unknown devices or issue a DB session ID.
            log.Printf("client connecting: deviceID=%s", deviceID)
            return "session-" + deviceID, nil
        },

        // Optional: observability hooks.
        OnSessionOpen: func(sid, dev string, claims map[string]any) {
            log.Printf("session %s opened (device=%s)", sid, dev)
        },
        OnSessionClose: func(sid, reason string) {
            log.Printf("session %s closed (%s)", sid, reason)
        },
        OnTraffic: func(sid, addr string, in, out uint64) {
            log.Printf("session %s%s  in=%d out=%d", sid, addr, in, out)
        },
    })

    ctx := context.Background()
    if err := srv.Run(ctx); err != nil {
        log.Fatal(err)
    }
}
The AuthHook error message is forwarded to the client as the rejection reason, so it should not leak sensitive internal details.

Build docs developers (and LLMs) love