.. index:: single: http_websocket_server_service(HTTPTransport) .. _http_websocket_server_service/1: .. rst-class:: right **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`` :ref:`http_websocket_service(HTTPTransport,server,atom) ` | **Uses:** | :ref:`http_websocket_service_registry ` | :ref:`user ` | **Remarks:** | (none) | **Inherited public predicates:** |  :ref:`http_websocket_session/2::initial_state/1`  :ref:`http_websocket_messages/1::is_message/1`  :ref:`http_websocket_session/2::is_state/1`  :ref:`http_websocket_messages/1::message/3`  :ref:`http_websocket_messages/1::payload/2`  :ref:`http_websocket_messages/1::read_message/2`  :ref:`http_websocket_session/2::read_message/4`  :ref:`http_websocket_session/2::read_message/5`  :ref:`http_websocket_session/2::read_message/6`  :ref:`http_websocket_service/3::run_session/3`  :ref:`http_websocket_service/3::run_session/4`  :ref:`http_websocket_messages/1::type/2`  :ref:`http_websocket_session/2::write_message/2`  :ref:`http_websocket_session/2::write_message/3`  :ref:`http_websocket_session/2::write_message/4`  :ref:`http_websocket_session/2::write_message/5`   .. contents:: :local: :backlinks: top Public predicates ----------------- .. index:: serve_once/6 .. _http_websocket_server_service/1::serve_once/6: ``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)`` ------------ .. index:: serve_once/7 .. _http_websocket_server_service/1::serve_once/7: ``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. ------------ .. index:: serve_until_shutdown/5 .. _http_websocket_server_service/1::serve_until_shutdown/5: ``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. ------------ .. index:: serve_until_shutdown/6 .. _http_websocket_server_service/1::serve_until_shutdown/6: ``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. ------------ .. index:: request_shutdown/1 .. _http_websocket_server_service/1::request_shutdown/1: ``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 ------------------ .. index:: shutdown_seed_/1 .. _http_websocket_server_service/1::shutdown_seed_/1: ``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`` ------------ .. index:: shutdown_control_/3 .. _http_websocket_server_service/1::shutdown_control_/3: ``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`` ------------ .. index:: shutdown_requested_/2 .. _http_websocket_server_service/1::shutdown_requested_/2: ``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`` ------------ .. index:: active_worker_/3 .. _http_websocket_server_service/1::active_worker_/3: ``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)