Help us shape the future of Go! Take the 2026 Go Developer Survey

clientopts

package
v0.16.0 Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package clientopts holds the RustDesk client options the panel pushes to every device through the heartbeat "strategy" (config_options), currently the WebRTC ones: ice-servers (STUN/TURN for the WebRTC transport of RustDesk 1.5+) and allow-webrtc-congestion-control. See docs/webrtc.md and docs/research/client-api.md §7.4.

The value is one JSON document in the settings table; the ICE server list is AEAD-sealed because TURN URLs carry credentials. Nothing is pushed until an admin saves the options once; from then on the panel owns these keys on the clients ("" removes a key, which restores the client default). Client strategies assigned to a device, its group or marked default are merged in by StrategyFor.

Index

Constants

View Source
const (
	OptionICEServers       = "ice-servers"
	OptionWebRTCCongestion = "allow-webrtc-congestion-control"
)

RustDesk option names pushed in config_options.

View Source
const (
	MaxICEServers   = 16
	MaxICEServerLen = 512
)

Limits of the ICE server list.

View Source
const DefaultPublicSTUNSource = "https://raw.githubusercontent.com/pradt2/always-online-stun/master/valid_hosts.txt"

DefaultPublicSTUNSource is the community-maintained repository of verified STUN servers.

View Source
const DefaultSTUNPort = 3478

DefaultSTUNPort is the standard UDP port for STUN/TURN.

View Source
const DefaultSTUNSPort = 5349

DefaultSTUNSPort is the standard TLS port for STUNS/TURNS.

View Source
const SettingKey = "client.options"

SettingKey is the settings row holding the options.

Variables

View Source
var CuratedFallbackSTUNs = []string{
	"stun:stun.cloudflare.com:3478",
	"stun:stun.l.google.com:19302",
	"stun:stun1.l.google.com:19302",
	"stun:stun2.l.google.com:19302",
	"stun:stun.qq.com:3478",
	"stun:stun.syncthing.net:3478",
	"stun:stun.miwifi.com:3478",
	"stun:stun.nextcloud.com:443",
	"stun:stun.sipgate.net:3478",
	"stun:stun.framasoft.org:3478",
	"stun:stun.freeswitch.org:3478",
	"stun:stun.voip.blackberry.com:3478",
}

CuratedFallbackSTUNs provides high-availability worldwide STUN servers when remote fetch is unavailable.

View Source
var ErrInvalidICEServer = errors.New("invalid ICE server")

ErrInvalidICEServer is wrapped by NormalizeICEServers' errors.

View Source
var Presets = []Preset{
	{
		ID: "global",
		Servers: "stun:stun.cloudflare.com:3478\n" +
			"stun:stun.l.google.com:19302\n" +
			"stun:stun1.l.google.com:19302",
	},
	{
		ID: "ru",
		Servers: "stun:stun.cloudflare.com:3478\n" +
			"stun:stun.qq.com:3478\n" +
			"stun:stun.syncthing.net:3478",
	},
	{
		ID:      "cloudflare",
		Servers: "stun:stun.cloudflare.com:3478",
	},
	{
		ID: "google",
		Servers: "stun:stun.l.google.com:19302\n" +
			"stun:stun1.l.google.com:19302",
	},
	{
		ID:      "default",
		Servers: "",
	},
}

Built-in presets for WebRTC ICE servers.

Functions

func ConfigOptions

func ConfigOptions(o *Options) map[string]string

ConfigOptions is the config_options map pushed to clients. Every managed key is present; "" removes it on the client.

func NormalizeICEServers

func NormalizeICEServers(in string) (string, error)

NormalizeICEServers validates a comma- or newline-separated ICE server list the way RustDesk parses it (hbb_common webrtc.rs get_ice_server_from_url) and returns it comma-joined. TURN URLs without credentials are rejected because the client drops them silently.

func Version added in v0.11.0

func Version(cfg map[string]string) int64

Version is the strategy version of a config_options map: the first 52 bits of a SHA-256 over the sorted key/value pairs. 52 bits stay exact in JSON tooling that reads numbers as doubles; it is never 0, which clients send when they applied nothing yet.

Types

type Options

type Options struct {
	// ICEServers is a comma-separated list of stun:/stuns:/turn:/turns: URLs;
	// TURN entries must carry credentials (turn://user:pass@host:port). ""
	// removes the option from clients (they use RustDesk's default STUN).
	ICEServers string
	// WebRTCCongestion sets allow-webrtc-congestion-control; nil removes it.
	WebRTCCongestion *bool
	// ModifiedAt (unix ms) is when the options were last saved (the heartbeat
	// version is a hash of the pushed options, see Version).
	ModifiedAt int64
	UpdatedAt  time.Time
}

Options are the client options as the admin API sees them.

type Preset added in v0.5.7

type Preset struct {
	ID      string `json:"id"`
	Servers string `json:"servers"`
}

Preset represents a pre-configured ICE / STUN server list.

type ProbeResult added in v0.5.7

type ProbeResult struct {
	Server    string  `json:"server"`
	Scheme    string  `json:"scheme"`
	Reachable bool    `json:"reachable"`
	RTTMs     float64 `json:"rtt_ms,omitempty"`
	Error     string  `json:"error,omitempty"`
}

ProbeResult holds reachability and latency for one ICE server.

func ProbeICEServers added in v0.5.7

func ProbeICEServers(ctx context.Context, iceServers string, allowPrivate bool) []ProbeResult

ProbeICEServers probes every server in iceServers in parallel (max MaxICEServers).

func ProbeOne added in v0.5.7

func ProbeOne(ctx context.Context, raw string, allowPrivate bool) ProbeResult

ProbeOne probes a single ICE server (STUN or TURN).

type PublicSTUNResult added in v0.5.9

type PublicSTUNResult struct {
	Source       string        `json:"source"`
	FetchedCount int           `json:"fetched_count"`
	WorkingCount int           `json:"working_count"`
	Items        []ProbeResult `json:"items"`
}

PublicSTUNResult contains discovered, probed, and ranked STUN servers.

func FetchPublicSTUN added in v0.5.9

func FetchPublicSTUN(ctx context.Context, sourceURL string, limit int) (*PublicSTUNResult, error)

FetchPublicSTUN downloads a list of public STUN servers, tests reachability concurrently, and returns the fastest working servers sorted by latency. Candidates that resolve to private, loopback or link-local addresses are never probed.

type Service

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

Service reads and writes the options and serves them as a heartbeat strategy (clientapi.StrategyProvider). The decoded value is cached; Set refreshes it, so the heartbeat path costs no database read.

func New

func New(st *store.Store, aead *crypto.AEAD, now func() time.Time) *Service

New returns a Service. now may be nil (time.Now).

func (*Service) Get

func (s *Service) Get(ctx context.Context) (*Options, error)

Get returns the saved options, or nil when they were never saved.

func (*Service) Set

func (s *Service) Set(ctx context.Context, iceServers string, congestion *bool, actor *int64) (*Options, error)

Set validates and stores the options (a new strategy version) and returns them as saved. actor may be nil.

func (*Service) StrategyFor

func (s *Service) StrategyFor(ctx context.Context, d *store.Device) (*clientapi.Strategy, error)

StrategyFor implements clientapi.StrategyProvider: the effective MDM strategy of d (device -> group -> default) merged with the global client options (such as ICE servers).

Without a strategy only the admin-saved client options are pushed (nothing at all until they are saved), as before strategies existed. Under a strategy the panel owns every key any strategy can set: keys the effective strategy does not set are sent as "" so a switch from another strategy does not leave its options behind.

The version (ModifiedAt) is a hash of the pushed map: the client stores whatever differs from what it sent (docs/research/client-api.md §7.4), so any change of the effective options, and only that, reaches the device.

Jump to

Keyboard shortcuts

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