mirror of
https://github.com/openlibrecommunity/olcrtc.git
synced 2026-05-26 07:08:11 +00:00
147 lines
5.4 KiB
Go
147 lines
5.4 KiB
Go
// Package tunnel exposes olcrtc's server-side tunnel as an embeddable Go library.
|
|
//
|
|
// A [Server] accepts encrypted tunnel connections over a WebRTC SFU carrier
|
|
// and proxies their traffic to arbitrary TCP targets. Consumers plug in
|
|
// authorization and observability via the [Config] hooks:
|
|
//
|
|
// srv := tunnel.New(tunnel.Config{
|
|
// Transport: "datachannel",
|
|
// Carrier: "jitsi",
|
|
// RoomURL: "https://meet.small-dm.ru/myroom",
|
|
// KeyHex: "<64-char hex>",
|
|
// DNSServer: "8.8.8.8:53",
|
|
// AuthHook: func(deviceID string, claims map[string]any) (string, error) {
|
|
// // reject unknown devices, enrich session with a DB-issued ID
|
|
// return db.IssueSession(deviceID, claims)
|
|
// },
|
|
// 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) {
|
|
// metrics.Record(sid, addr, in, out)
|
|
// },
|
|
// })
|
|
// if err := srv.Run(ctx); err != nil {
|
|
// log.Fatal(err)
|
|
// }
|
|
//
|
|
// Call [RegisterDefaults] once at program start to register the built-in
|
|
// carriers (jitsi, telemost, wbstream) and transports (datachannel,
|
|
// videochannel, seichannel, vp8channel).
|
|
package tunnel
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/openlibrecommunity/olcrtc/internal/app/session"
|
|
"github.com/openlibrecommunity/olcrtc/internal/handshake"
|
|
"github.com/openlibrecommunity/olcrtc/internal/server"
|
|
"github.com/openlibrecommunity/olcrtc/internal/transport"
|
|
)
|
|
|
|
// TransportOptions is the marker type for transport-specific tuning options.
|
|
// Pass a value from the corresponding transport package (videochannel.Options,
|
|
// vp8channel.Options, seichannel.Options) or nil for transports without
|
|
// tunables (datachannel).
|
|
type TransportOptions = transport.Options
|
|
|
|
// AuthFunc is invoked after CLIENT_HELLO to authorize the client and issue a
|
|
// session ID. Returning a non-nil error rejects the handshake; the error's
|
|
// message is forwarded to the client as the reject reason, so it should not
|
|
// leak sensitive details.
|
|
type AuthFunc = handshake.AuthFunc
|
|
|
|
// SessionOpenFunc fires right after a successful handshake, before the server
|
|
// starts accepting tunnel streams on that session.
|
|
type SessionOpenFunc = server.SessionOpenFunc
|
|
|
|
// SessionCloseFunc fires when a session ends. Reasons include "reconnect"
|
|
// (carrier dropped and was reestablished) and "closed" (graceful shutdown or
|
|
// ctx cancel).
|
|
type SessionCloseFunc = server.SessionCloseFunc
|
|
|
|
// TrafficFunc fires once per tunnel stream after both copy loops finish.
|
|
// bytesIn counts client→target bytes; bytesOut counts target→client bytes.
|
|
type TrafficFunc = server.TrafficFunc
|
|
|
|
// Config holds runtime server configuration.
|
|
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
|
|
|
|
// --- transport tuning ---
|
|
// TransportOptions carries transport-specific tuning. Use the Options
|
|
// type from the corresponding internal/transport/* package, or leave nil
|
|
// for transports that need no extra configuration (datachannel).
|
|
TransportOptions TransportOptions
|
|
|
|
// --- hooks ---
|
|
// AuthHook authorizes the client. If nil, every client is admitted with a
|
|
// random UUID as session ID.
|
|
AuthHook AuthFunc
|
|
// OnSessionOpen fires after a successful handshake. Nil is a no-op.
|
|
OnSessionOpen SessionOpenFunc
|
|
// OnSessionClose fires when the session is torn down. Nil is a no-op.
|
|
OnSessionClose SessionCloseFunc
|
|
// OnTraffic fires once per tunnel stream after both copy loops finish.
|
|
// Nil is a no-op.
|
|
OnTraffic TrafficFunc
|
|
}
|
|
|
|
// Server is an embeddable tunnel server.
|
|
type Server struct {
|
|
cfg Config
|
|
}
|
|
|
|
// New returns a Server configured by cfg. Call [Server.Run] to start it.
|
|
func New(cfg Config) *Server {
|
|
return &Server{cfg: cfg}
|
|
}
|
|
|
|
// Run starts the server and blocks until ctx is cancelled or the carrier ends.
|
|
func (s *Server) Run(ctx context.Context) error {
|
|
if err := server.Run(ctx, server.Config{
|
|
Transport: s.cfg.Transport,
|
|
Carrier: s.cfg.Carrier,
|
|
RoomURL: s.cfg.RoomURL,
|
|
Engine: s.cfg.Engine,
|
|
URL: s.cfg.URL,
|
|
Token: s.cfg.Token,
|
|
KeyHex: s.cfg.KeyHex,
|
|
DNSServer: s.cfg.DNSServer,
|
|
SOCKSProxyAddr: s.cfg.SOCKSProxyAddr,
|
|
SOCKSProxyPort: s.cfg.SOCKSProxyPort,
|
|
TransportOptions: s.cfg.TransportOptions,
|
|
AuthHook: s.cfg.AuthHook,
|
|
OnSessionOpen: s.cfg.OnSessionOpen,
|
|
OnSessionClose: s.cfg.OnSessionClose,
|
|
OnTraffic: s.cfg.OnTraffic,
|
|
}); err != nil {
|
|
return fmt.Errorf("tunnel: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// RegisterDefaults registers the built-in carriers, links and transports.
|
|
// Safe to call multiple times.
|
|
func RegisterDefaults() {
|
|
session.RegisterDefaults()
|
|
}
|