object

# `http_websocket_server_service(HTTPTransport)`

Server-side convenience for callback-driven WebSocket sessions with atom text representation, including registry-backed broadcast helpers.

Availability:
`logtalk_load(http_websocket_service(loader))`
Author: Paulo Moura
Version: 1:0:0
Date: 2026-07-13
Compilation flags:
`static, context_switching_calls, threaded`
Extends:
`public` http_websocket_service(HTTPTransport,server,atom)
Uses:
http_websocket_service_registry
user
Remarks:
(none)
Inherited public predicates:
initial_state/1 is_message/1 is_state/1 message/3 payload/2 read_message/2 read_message/4 read_message/5 read_message/6 run_session/3 run_session/4 type/2 write_message/2 write_message/3 write_message/4 write_message/5

## Public predicates

### `serve_once/6`

Accepts one incoming socket connection on the given listener created by the selected transport parameterization, serves one WebSocket opening handshake using the given HTTP handler, then runs one callback-driven WebSocket session using the given session handler until the close handshake completes or the peer closes the stream.

Compilation flags:
`static`
Template:
`serve_once(Listener,HandshakeHandler,SessionHandler,Response,State,ClientInfo)`
Mode and number of proofs:
`serve_once(+compound,+object_identifier,+object_identifier,-compound,-compound,-compound)` - `one_or_error`
Exceptions:
The listener is invalid for the selected transport:
`domain_error(http_socket_transport_listener,Listener)`
The WebSocket opening request does not exist:
`existence_error(http_socket_transport_websocket_request,end_of_file)`
The WebSocket opening response is invalid:
`domain_error(http_socket_transport_websocket_response,Response)`
`SessionHandler` is a variable:
`instantiation_error`
`SessionHandler` is not a valid WebSocket service handler:
`domain_error(http_websocket_service_handler,SessionHandler)`
The upgraded connection handle is invalid:
`domain_error(http_socket_transport_connection,Connection)`
The delegated session loop raises a WebSocket session error:
`domain_error(http_websocket_session_sequence,Frame)`
`SessionHandler` returns an invalid reply:
`domain_error(http_websocket_service_handler_reply,Reply)`

### `serve_once/7`

Accepts one incoming socket connection on the given listener created by the selected transport parameterization, serves one WebSocket opening handshake using the given HTTP handler, then runs one callback-driven WebSocket session using the given session handler and the given session-loop options.

Compilation flags:
`static`
Template:
`serve_once(Listener,HandshakeHandler,SessionHandler,Response,State,ClientInfo,Options)`
Mode and number of proofs:
`serve_once(+compound,+object_identifier,+object_identifier,-compound,-compound,-compound,+list)` - `one_or_error`
Exceptions:
The listener is invalid for the selected transport:
`domain_error(http_socket_transport_listener,Listener)`
The WebSocket opening request does not exist:
`existence_error(http_socket_transport_websocket_request,end_of_file)`
The WebSocket opening response is invalid:
`domain_error(http_socket_transport_websocket_response,Response)`
`SessionHandler` is a variable:
`instantiation_error`
`SessionHandler` is not a valid WebSocket service handler:
`domain_error(http_websocket_service_handler,SessionHandler)`
`Options` is a variable or a partial list:
`instantiation_error`
`Options` is neither a variable nor a list:
`type_error(list,Options)`
An element `Option` of the list `Options` is neither a variable nor a compound term:
`type_error(compound,Option)`
An element `Option` of the list `Options` is a compound term but not a valid option:
`domain_error(option,Option)`
`Options` contains an invalid WebSocket service loop option:
`domain_error(http_websocket_service_option,Option)`
Timed session-loop options are not available on this backend:
`existence_error(http_websocket_service,timing)`
The upgraded connection handle is invalid:
`domain_error(http_socket_transport_connection,Connection)`
The delegated session loop raises a WebSocket session error:
`domain_error(http_websocket_session_sequence,Frame)`
`SessionHandler` returns an invalid reply:
`domain_error(http_websocket_service_handler_reply,Reply)`
Remarks:

> - Option `auto_pong(on)`: Automatically writes pong replies while still forwarding ping messages to the session handler.

> - Option `auto_pong(off)`: Disables automatic pong replies. This is the default.

> - Option `keepalive_interval(Seconds)`: Schedules empty ping messages when the peer stays silent for the given positive number of seconds. This option requires backend thread support.

> - Option `idle_timeout(Seconds)`: Closes the session with `status(1001, idle_timeout)` after the given positive number of seconds without an inbound message. This option requires backend thread support.

> - Option `max_payload_length(Bytes)`: Rejects inbound frames whose declared payload length is greater than `Bytes` before allocating payload storage. Oversized frames are treated as `1009` close errors in the session loop. Use a non-negative integer.

### `serve_until_shutdown/5`

Accepts WebSocket opening handshakes on the given listener created by the selected transport parameterization until request_shutdown/1 is called for the specified control term, runs one callback-driven session loop per accepted upgraded connection, registers active sessions in the given registry for queued broadcasts, and closes the listener before returning.

Compilation flags:
`static`
Template:
`serve_until_shutdown(Listener,HandshakeHandler,SessionHandler,Registry,Control)`
Mode and number of proofs:
`serve_until_shutdown(+compound,+object_identifier,+object_identifier,+compound,+nonvar)` - `one_or_error`
Exceptions:
Registry-backed serving is not available on this backend:
`existence_error(http_websocket_server_service,registry)`
`Registry` is not an open WebSocket service registry handle:
`domain_error(http_websocket_service_registry,Registry)`
`Registry` refers to a closed WebSocket service registry handle:
`existence_error(http_websocket_service_registry,session_registry(RegistryId))`
`Control` is a variable:
`instantiation_error`
`Control` is already registered for another open-ended WebSocket server loop:
`permission_error(reuse,http_websocket_service_shutdown_control,Control)`
The WebSocket opening response is invalid:
`domain_error(http_socket_transport_websocket_response,Response)`
`SessionHandler` is a variable:
`instantiation_error`
`SessionHandler` is not a valid WebSocket service handler:
`domain_error(http_websocket_service_handler,SessionHandler)`
The delegated session loop raises a WebSocket session error:
`domain_error(http_websocket_session_sequence,Frame)`
`SessionHandler` returns an invalid registry action:
`domain_error(http_websocket_service_handler_action,Action)`
Remarks:

> - Thread support: This helper requires backend thread support so that multiple sessions can stay active concurrently.

> - Handler actions: Plain normalized messages are written back to the originating session. `broadcast(Message)` queues `Message` for all registered sessions and `broadcast_others(Message)` queues it for all registered sessions except the originating one.

### `serve_until_shutdown/6`

Accepts WebSocket opening handshakes on the given listener created by the selected transport parameterization until request_shutdown/1 is called for the specified control term, runs one registry-backed callback session per accepted connection, applies the given session-loop options to every active session, and closes the listener before returning.

Compilation flags:
`static`
Template:
`serve_until_shutdown(Listener,HandshakeHandler,SessionHandler,Registry,Control,Options)`
Mode and number of proofs:
`serve_until_shutdown(+compound,+object_identifier,+object_identifier,+compound,+nonvar,+list)` - `one_or_error`
Exceptions:
Registry-backed serving is not available on this backend:
`existence_error(http_websocket_server_service,registry)`
`Registry` is not an open WebSocket service registry handle:
`domain_error(http_websocket_service_registry,Registry)`
`Registry` refers to a closed WebSocket service registry handle:
`existence_error(http_websocket_service_registry,session_registry(RegistryId))`
`Control` is a variable:
`instantiation_error`
`Control` is already registered for another open-ended WebSocket server loop:
`permission_error(reuse,http_websocket_service_shutdown_control,Control)`
`Options` is a variable or a partial list:
`instantiation_error`
`Options` is neither a variable nor a list:
`type_error(list,Options)`
`Options` contains an invalid WebSocket service loop option:
`domain_error(http_websocket_service_option,Option)`
Timed session-loop options are not available on this backend:
`existence_error(http_websocket_service,timing)`
The WebSocket opening response is invalid:
`domain_error(http_socket_transport_websocket_response,Response)`
`SessionHandler` is a variable:
`instantiation_error`
`SessionHandler` is not a valid WebSocket service handler:
`domain_error(http_websocket_service_handler,SessionHandler)`
The delegated session loop raises a WebSocket session error:
`domain_error(http_websocket_session_sequence,Frame)`
`SessionHandler` returns an invalid registry action:
`domain_error(http_websocket_service_handler_action,Action)`
Remarks:

> - Option `auto_pong(on|off)`: Controls automatic pong replies in each active session loop.

> - Option `keepalive_interval(Seconds)`: Schedules empty ping messages when a peer stays silent for the given positive number of seconds.

> - Option `idle_timeout(Seconds)`: Closes a session with `status(1001, idle_timeout)` after the given positive number of seconds without an inbound message.

> - Option `max_payload_length(Bytes)`: Rejects inbound frames whose declared payload length is greater than `Bytes` before allocating payload storage. Oversized frames are treated as `1009` close errors in each session loop. Use a non-negative integer.

### `request_shutdown/1`

Requests shutdown of a registry-backed server loop started with serve_until_shutdown/5-6 for the specified control term and wakes any blocked accept call so the loop can terminate portably.

Compilation flags:
`static`
Template:
`request_shutdown(Control)`
Mode and number of proofs:
`request_shutdown(+nonvar)` - `one_or_error`
Exceptions:
Registry-backed serving is not available on this backend:
`existence_error(http_websocket_server_service,registry)`
`Control` is a variable:
`instantiation_error`
`Control` is not registered for an open-ended WebSocket server loop:
`existence_error(http_websocket_service_shutdown_control,Control)`

## Protected predicates

(no local declarations; see entity ancestors if any)

## Private predicates

### `shutdown_seed_/1`

Last allocated shutdown run identifier for open-ended WebSocket server loops.

Compilation flags:
`dynamic`
Template:
`shutdown_seed_(RunId)`
Mode and number of proofs:
`shutdown_seed_(?positive_integer)` - `zero_or_one`

### `shutdown_control_/3`

Registered shutdown control terms and their associated listeners.

Compilation flags:
`dynamic`
Template:
`shutdown_control_(Control,Listener,RunId)`
Mode and number of proofs:
`shutdown_control_(?nonvar,?compound,?positive_integer)` - `zero_or_more`

### `shutdown_requested_/2`

Recorded shutdown requests indexed by control term and run identifier.

Compilation flags:
`dynamic`
Template:
`shutdown_requested_(Control,RunId)`
Mode and number of proofs:
`shutdown_requested_(?nonvar,?positive_integer)` - `zero_or_more`

### `active_worker_/3`

Active WebSocket session worker records indexed by control term and run identifier.

Compilation flags:
`dynamic`
Template:
`active_worker_(Control,RunId,Worker)`
Mode and number of proofs:
`active_worker_(?nonvar,?positive_integer,?compound)` - `zero_or_more`

## Operators

(none)