LCP Protocol Internals
This page documents the internal protocol mechanics of the LiveContentProtocol (LCP). For the high-level overview, connector patterns, and creating new connectors, see LCP & RPC.
LiveContentWrapper
LiveContentWrapper (in io-oidis-services) is the core protocol encoder/decoder. Every connector call ultimately delegates to one of its four static factory methods:
| Method | Purpose | Used by |
|---|---|---|
InvokeMethod() | Remote method invocation | BaseConnector.invoke() / asyncInvoke() |
setProperty() | Remote property setter | Direct usage via LiveContentWrapper.setProperty() |
getProperty() | Remote property getter | Direct usage via LiveContentWrapper.getProperty() |
AddEventHandler() | Subscribe to backend events | Event-driven connectors |
Each factory method creates a LiveContentWrapper instance, builds the wire-format protocol, sends it via the transport client, and returns a chainable callback API.
The Wire Format (IWebServiceProtocol)
Every LCP message — request or response — is wrapped in IWebServiceProtocol:
{
id: number, // Request ID for correlation
clientId: number, // Browser client identifier
type: string, // e.g. "LiveContentWrapper.InvokeMethod"
status: number, // HTTP-style status code (200 = success)
origin: string, // Request origin for CORS
token: string, // Auth session token
data: { // ILiveContentProtocol payload
name: string, // "Namespace.ClassName.MethodName"
args: any[], // Serialized arguments
returnValue: any // Response value (in responses)
},
format: string, // Encoding: "json" or "auto"
version: "1.1" // Protocol version
}
The type field follows the pattern "LiveContentWrapper.<operation>" where operation is InvokeMethod, setProperty, getProperty, AddEventHandler, or getEvent.
Response Deserialization
When a response arrives, LiveContentWrapper.getReturnValue() automatically deserializes the return value:
- Base64 detection — If format is not JSON and the value matches a Base64 pattern, it is decoded first
- JSON objects/arrays — Strings starting with
{or[are parsed as JSON - Numeric strings — Converted to
number(integer or double) - Boolean strings —
"true"/"false"converted toboolean - Void/null —
RETURN_VOIDmarker or"null"string returnsnull - Non-string values — Returned as-is (already deserialized by transport)
Error Propagation
When the backend throws an exception, the response arrives with type = "WebServiceClientEventType.ON_ERROR" and the data field contains IWebServiceException:
{
message: string, // Error message (may be Base64-encoded)
file: string, // Source file
line: number, // Line number
col: number, // Column number
code: number, // Error code
stack: string, // Full stack trace
args?: any // Custom error context
}
The wrapper reconstructs a full Error object with the original stack trace, wraps it in ErrorEventArgs, and either calls the registered OnError() handler or fires a global error event.
Event Handler Polling
For WebSocket transports, backend events are pushed to the client in real-time. For HTTP/AJAX transports (which cannot receive server push), LiveContentWrapper implements a polling mechanism:
AddEventHandler()sends the initial subscription request- If the transport is not WebSocket, a polling loop starts
- Every 500ms, a
getEventprotocol message is sent to check for pending events - Received events are dispatched to all registered handlers asynchronously
- Polling stops when the client connection closes
Callback Chain API
The LiveContentWrapper instance returned from factory methods implements a chainable API:
LiveContentWrapper.InvokeMethod(config)
.DataFormatter(($data) => transform($data)) // Optional: transform raw response
.OnError(($error) => handleError($error)) // Optional: handle errors
.Then(($result) => useResult($result)); // Required: handle success
Each step is optional except Then(). If OnError() is not provided, errors propagate to the global EventsManager.
See also: LCP & RPC | Connectors Reference | Response API