remoteProtocol

Transport-agnostic protocol constants + pure helpers for the remote-control receiver: the http-gate, the session-socket URL builder, reconnect backoff, and the client KeepAlive frame. No socket, no node, no m.global — fully unit-testable.

Members

(static, constant) CONTRACT_VERSION

The long-poll wire-contract version this client implements. The plugin advertises its own contractVersion in the /info probe body; JellyRock refuses a mismatch and stays dark rather than risk acting on a command shape it might misread. See remote-control-longpoll-contract.md (Versioning).

Default Value
  • 1

(static, constant) PLUGIN_ROUTE

--- HTTPS long-poll transport (#667) --- The plugin route prefix. JellyRock consumes the long-poll over TLS (roUrlTransfer) because Roku can't wss://. Unlike buildSocketUrl, these carry NO token in the URL — the caller attaches the standard Authorization header (baseRequest.buildAuthHeader), which already binds the session by DeviceId. See docs/architecture/remote-control-longpoll-contract.md.

Default Value
  • /JellyRock/RemoteControl

Methods

(static) buildLongPollUrl(serverUrl, waitMs) → {string}

Build the plugin's long-poll command-channel URL for a server base URL. Returns "" for a blank server URL. waitMs is JellyRock's requested hold ceiling; the client-side transfer timeout is set longer so a 204 (empty hold) always arrives before the transfer itself times out. https://host -> https://host/JellyRock/RemoteControl/poll?waitMs=

Parameters:
NameTypeDescription
serverUrldynamic
waitMsinteger
Returns:
Type: 
string

(static) buildProbeUrl(serverUrl) → {string}

Build the plugin presence/version probe URL (200 = plugin present, 404 = absent). Returns "" for a blank server URL. No token in the URL (auth is header-based). https://host -> https://host/JellyRock/RemoteControl/info

Parameters:
NameTypeDescription
serverUrldynamic
Returns:
Type: 
string

(static) buildSocketUrl(serverUrl, authToken, deviceId) → {string}

Build the Jellyfin session-socket URL from the server URL + session credentials. Returns "" when the server isn't http:// (never downgrades an https:// token onto ws://) or when a credential is missing. The deviceId MUST match the DeviceId in baseRequest's auth header so the socket binds the SAME session the REST API uses. http://host:port -> ws://host:port/socket?api_key=&deviceId=

Parameters:
NameTypeDescription
serverUrldynamic
authTokendynamic
deviceIddynamic
Returns:
Type: 
string

(static) isHttpServer(serverUrl) → {boolean}

The http-gate. JellyRock can only open a ws:// socket to an http:// server — Roku can't do wss:// (no socket TLS), so an https:// session stays uncontrolled (the future plugin long-poll path). Both the advertised capability (deviceCapabilities) and the receiver gate on this, so they never disagree.

Parameters:
NameTypeDescription
serverUrldynamic
Returns:
Type: 
boolean

(static) keepAliveFrame() → {string}

The client->server KeepAlive frame. Jellyfin's ForceKeepAlive asks the client to send these on the requested interval so the session isn't reaped by the inactivity timeout.

Returns:
Type: 
string

(static) nextBackoffMs(attempt) → {integer}

Exponential reconnect backoff, 0-based attempt: 1s, 2s, 4s, 8s, 16s, then capped at 30s.

Parameters:
NameTypeDescription
attemptinteger
Returns:
Type: 
integer

(static) parseContractVersion(body) → {integer}

Extract the contractVersion from a /info probe body. Returns 0 for a blank/unparseable body, a non-object body, a missing key, or a non-numeric value — callers treat anything <> CONTRACT_VERSION as "no usable plugin". NEVER throws on a hostile/garbled body (it's network-controlled input): a string/object/bool contractVersion is rejected before any coercion that could raise at runtime.

Parameters:
NameTypeDescription
bodydynamic
Returns:
Type: 
integer

(static) pluginBaseUrl(serverUrl) → {string}

Shared plugin route-prefix builder. Trims a single trailing slash on the server URL so we never emit "//". Returns "" for a missing/blank server URL.

Parameters:
NameTypeDescription
serverUrldynamic
Returns:
Type: 
string