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.

The mobile package provides a gomobile-compatible API for Android. It exposes a local SOCKS5 proxy that tunnels traffic through an encrypted WebRTC session to an olcRTC server, with full support for Android VPN socket protection. The API is intentionally flat — all state is package-level, designed for the gomobile binding model.

Build

Prerequisites

  • Go 1.26+
  • gomobile installed: go install golang.org/x/mobile/cmd/gomobile@latest && gomobile init
  • Android NDK configured

Build Command

gomobile bind -target=android ./mobile
This produces an .aar archive (and a .jar sources stub) that you include in your Android/Kotlin project like any other local dependency.
The default transport is vp8channel. The datachannel transport is also supported and can be selected at runtime via SetTransport or StartWithTransport.

Interfaces

The mobile package exposes two Go interfaces that you implement in Kotlin or Java and pass back via the setup functions.

SocketProtector

type SocketProtector interface {
    Protect(fd int) bool
}
Implement this in Kotlin/Java to protect raw sockets from being routed back through your VPN (VpnService.protect(fd)). Pass the implementation to SetProtector before calling Start.
class MySocketProtector(private val vpnService: VpnService) : mobile.SocketProtector {
    override fun protect(fd: Long): Boolean = vpnService.protect(fd.toInt())
}

LogWriter

type LogWriter interface {
    WriteLog(msg string)
}
Implement this to receive log output from the olcRTC runtime and forward it to Android Logcat or your own logging backend.
class AndroidLogWriter : mobile.LogWriter {
    override fun writeLog(msg: String) {
        Log.d("olcRTC", msg.trimEnd())
    }
}

Setup Functions

Call these before Start to configure the runtime. All setters are safe to call multiple times; subsequent calls overwrite the previous value.
Always call SetProviders() before Start(). Without it, no carriers or transports are registered and Start will fail.

SetProviders

func SetProviders()
Registers all built-in carriers (jitsi, telemost, wbstream), links, and transports (datachannel, vp8channel, etc.). Must be called at least once before any Start, Check, or Ping call.

SetProtector

func SetProtector(p SocketProtector)
Sets the Android VPN socket protector. Pass nil to clear it. Must be called before Start to ensure all sockets created during the WebRTC handshake are protected.

SetLogWriter

func SetLogWriter(w LogWriter)
Redirects olcRTC log output to your LogWriter implementation. Replaces the default os.Stderr output.

SetTransport

func SetTransport(transport string)
Selects the transport used by subsequent Start calls. Accepted values: "vp8channel" (default) and "datachannel". Unrecognized values fall back to "vp8channel".

SetDNS

func SetDNS(dnsServer string)
Sets the DNS server used by the tunnel, e.g. "8.8.8.8:53". Defaults to "8.8.8.8:53".

SetWBToken

func SetWBToken(token string)
Sets a pre-issued WbStream account token. When set, the session joins as that account instead of as an anonymous guest. Empty string keeps the guest flow.
The datachannel transport over WbStream requires a moderator/account token with canPublishData=true. Guest accounts cannot publish data on WbStream. Either call SetWBToken with a valid account token, or switch to vp8channel / seichannel which work without a special token.

SetSocksListenHost

func SetSocksListenHost(host string)
Sets the local bind host for the SOCKS5 listener. Default is "127.0.0.1". Use "0.0.0.0" to accept connections from other network interfaces on the device.

SetVP8Options

func SetVP8Options(fps, batchSize int)
Configures the vp8channel transport. fps controls the frame rate (default 30, max 120); batchSize controls the number of packets batched per frame (default 8, max 64). Values below 1 are clamped to 1.

SetLivenessOptions

func SetLivenessOptions(intervalMillis, timeoutMillis, failures int)
Configures the control-stream ping/pong liveness check. All durations are in milliseconds. Values ≤ 0 reset that field to its internal default.
ParameterDescription
intervalMillisHow often to send a ping.
timeoutMillisHow long to wait for a pong before counting a failure.
failuresNumber of consecutive failures before the session is considered dead.

SetDebug

func SetDebug(enabled bool)
Enables or disables verbose logging. When enabled, log flags include time and source file. Useful during development; disable in production.

Core Lifecycle Functions

Start

func Start(
    carrierName, roomID, clientID, keyHex string,
    socksPort int,
    socksUser, socksPass string,
) error
Launches the olcRTC client in the background using the transport set by SetTransport (default vp8channel). Returns immediately; the tunnel is not yet ready when Start returns. Call WaitReady to block until the SOCKS5 listener is accepting connections.
ParameterDescription
carrierNameAuth provider: "jitsi", "telemost", or "wbstream".
roomIDCarrier-specific room identifier.
clientIDClient identifier that must match the server’s -client-id.
keyHex64-character hex encryption key shared with the server.
socksPortLocal SOCKS5 port to listen on, e.g. 10808.
socksUserSOCKS5 username (empty = no auth).
socksPassSOCKS5 password (empty = no auth).
Returns errAlreadyRunning if the client is already active.

StartWithTransport

func StartWithTransport(
    carrierName, transportName, roomID, clientID, keyHex string,
    socksPort int,
    socksUser, socksPass string,
) error
Same as Start, but overrides the transport for this call only without changing the default set by SetTransport.

WaitReady

func WaitReady(timeoutMillis int) error
Blocks until the SOCKS5 listener is ready to accept connections, or until the timeout expires. Call this after Start before routing any traffic through the SOCKS5 proxy. Returns nil when the tunnel is ready. Returns errStartTimedOut if the timeout elapses, errStoppedBeforeReady if the client stopped before becoming ready, or errNotRunning if Start was never called.

Stop

func Stop()
Gracefully shuts down the olcRTC client. Blocks until the background goroutine exits. Safe to call even if the client is not running.

IsRunning

func IsRunning() bool
Returns true if the olcRTC client is currently active.

Probe Functions

Check and Ping run isolated, short-lived client sessions and do not interact with the singleton managed by Start/Stop. Multiple probes can run concurrently.
Check and Ping create their own independent client session each time they are called. They do not share state with Start/Stop, so you can run parallel latency checks across different rooms or providers while a main tunnel session is active.

Check

func Check(
    carrierName, transportName, roomID, clientID, keyHex string,
    socksPort int,
    timeoutMillis int,
    vp8FPS int,
    vp8BatchSize int,
) (int64, error)
Starts an isolated client session and returns the elapsed milliseconds from call to SOCKS5 listener readiness. Use this to measure tunnel establishment latency for a given carrier/room combination. timeoutMillis ≤ 0 defaults to 8000 ms. vp8FPS and vp8BatchSize tune the vp8channel transport for this probe; values below 1 are clamped to 1.

Ping

func Ping(
    carrierName, transportName, roomID, clientID, keyHex string,
    socksPort int,
    timeoutMillis int,
    pingURL string,
    vp8FPS int,
    vp8BatchSize int,
) (int64, error)
Starts an isolated client session, waits until the SOCKS5 listener is ready, then performs HTTP requests through the tunnel and returns the best observed HTTP latency in milliseconds. The warmup request is excluded from the measurement. pingURL defaults to https://www.google.com/generate_204 if empty. The returned value measures only HTTP request latency after the tunnel is ready, not tunnel establishment time. Ping timing constants:
ConstantValue
Warmup timeout1500 ms
Per-sample timeout1500 ms
Number of samples3
Sample delay80 ms

Error Values

ErrorDescription
errAlreadyRunningStart called while the client is already running.
errCarrierRequiredcarrierName is empty.
errRoomIDRequiredroomID is empty.
errClientIDRequiredclientID is empty.
errKeyHexRequiredkeyHex is empty.
errNotRunningWaitReady called without a prior Start.
errStoppedBeforeReadyThe client stopped or crashed before the SOCKS5 listener became ready.
errStartTimedOutWaitReady (or Check/Ping) timed out before the tunnel was ready.

Default Values

ConstantValue
defaultTransport"vp8channel"
defaultDNSServer"8.8.8.8:53"
defaultSocksHost"127.0.0.1"
VP8 FPS30
VP8 batch size8
HTTP ping warmup timeout1500 ms
HTTP ping sample timeout1500 ms
HTTP ping samples3

Examples

import go.mobile.Mobile

class MyVpnService : VpnService() {

    fun startTunnel() {
        // 1. Protect sockets so WebRTC traffic bypasses the VPN.
        Mobile.setProtector(object : Mobile.SocketProtector {
            override fun protect(fd: Long): Boolean = protect(fd.toInt())
        })

        // 2. Register built-in providers (always call first).
        Mobile.setProviders()

        // 3. Route log output to Logcat.
        Mobile.setLogWriter(object : Mobile.LogWriter {
            override fun writeLog(msg: String) {
                android.util.Log.d("olcRTC", msg.trimEnd())
            }
        })

        // 4. Configure transport and options.
        Mobile.setTransport("vp8channel")
        Mobile.setVP8Options(30, 8)
        Mobile.setDNS("8.8.8.8:53")

        // 5. Start the tunnel in the background.
        Mobile.start(
            /* carrierName */ "jitsi",
            /* roomID      */ "https://meet.small-dm.ru/myroom",
            /* clientID    */ "my-device-id",
            /* keyHex      */ "aabbcc...(64 hex chars)...",
            /* socksPort   */ 10808,
            /* socksUser   */ "",
            /* socksPass   */ ""
        )

        // 6. Block until the SOCKS5 listener is ready (max 10 s).
        Mobile.waitReady(10_000)

        // 7. Route app traffic through 127.0.0.1:10808 (SOCKS5).
    }

    fun stopTunnel() {
        Mobile.stop()
    }
}

Build docs developers (and LLMs) love