.. _library_http_socket_transport:

``http_socket_transport``
=========================

The ``http_socket_transport`` library is the first transport-aware layer
on top of the ``http_client_core``, ``http_server_core``, and
``sockets`` libraries. It uses TCP sockets for connection management
while delegating HTTP message framing and connection semantics to the
existing stream core and server layers.

This library can be used with backend Prolog systems that support
unbound integer arithmetic and the ``sockets`` library: ECLiPSe, SICStus
Prolog, SWI-Prolog, Trealla Prolog, and XVM.

API documentation
-----------------

Open the
`../../apis/library_index.html#http_socket_transport <../../apis/library_index.html#http_socket_transport>`__
link in a web browser.

Loading
-------

To load the library, load the ``loader.lgt`` file:

::

   | ?- logtalk_load(http_socket_transport(loader)).

Testing
-------

To test this library, load the ``tester.lgt`` file:

::

   | ?- logtalk_load(http_socket_transport(tester)).

Current scope
-------------

The current implementation provides nineteen public predicates, grouped
by responsibility:

- Listener lifecycle: ``open_listener/4``, ``close_listener/1``, and
  ``request_listener_shutdown/1``.
- Reusable client connections: ``open_connection/4``,
  ``close_connection/1``, ``connection_streams/3``, ``exchange/3``,
  ``exchange_sequence/3``, ``exchange/4``, and ``exchange_sequence/4``.
- Managed connection pools: ``open_connection_pool/4``,
  ``close_connection_pool/1``, and ``connection_pool_stats/2``.
- Server-side request serving: ``serve_once/3``,
  ``serve_websocket_once/5``, ``serve_listener/4``, and
  ``serve_listener/5``.
- Open-ended serving control: ``serve_until_shutdown/4``,
  ``serve_until_shutdown/5``, and ``request_shutdown/1``.

Although it exposes these transport-oriented helpers, the library stays
focused on socket-backed connection and listener management. It
delegates HTTP message framing and connection semantics to
``http_client_core`` and ``http_server_core``, and delegates socket
creation and teardown to the ``sockets`` library.

Reusable client connections are represented by
``http_connection(Host, Port, ...)`` handle terms that carry normalized
endpoint metadata and can be passed to ``exchange/3``,
``exchange_sequence/3``, ``connection_streams/3``, and
``close_connection/1``.

Accepted WebSocket upgrades are represented by
``http_websocket_connection(ClientInfo, Input, Output)`` handle terms
that can be passed to ``connection_streams/3`` and
``close_connection/1``.

Managed connection pools are represented by
``http_connection_pool(Host, Port, ...)`` handle terms that carry
normalized endpoint metadata and can be passed to ``exchange/3``,
``exchange_sequence/3``, ``close_connection_pool/1``, and
``connection_pool_stats/2``.

Open-ended serving is controlled by a user-supplied control term. A
control term is any fresh non-variable term chosen by the caller to
identify one active ``serve_until_shutdown/4`` or
``serve_until_shutdown/5`` loop. The same term is later passed to
``request_shutdown/1`` to stop that specific serving loop,
distinguishing it from any other listener loops running at the same
time.

The ``open_connection_pool/4`` predicate supports the following options:

- ``min_size(N)`` pre-opens ``N`` reusable connections when the pool is
  created. The default is ``0``.
- ``max_size(N)`` limits the pool to at most ``N`` managed connections.
  The default is ``10``.
- ``connection_options(Options)`` passes socket options through to
  ``open_connection/4`` when creating pooled connections.

Pool exchanges fail immediately with
``resource_error(http_socket_transport_connection_pool)`` when no pooled
connection is available and the pool is already at its maximum size.

The ``serve_listener/5`` predicate supports the following option
families:

Shutdown options:

- ``shutdown(keep_open)`` leaves the listener open after the bounded
  serving loop. This is the default.
- ``shutdown(close)`` closes the listener when the bounded serving loop
  finishes or aborts.

Worker options:

- ``workers(serial)`` serves accepted connections sequentially in the
  caller thread. This is the default.
- ``workers(per_connection)`` spawns one worker thread per accepted
  connection and waits for all workers before returning.
- ``workers(pool(N))`` serves accepted connections in batches of up to
  ``N`` worker threads, waiting for each batch to finish before
  accepting the next batch.
- ``workers(pool(N, rolling))`` keeps up to ``N`` worker threads active
  and accepts the next connection as soon as one worker finishes.

Calling ``request_listener_shutdown/1`` for a listener with an active
bounded ``serve_listener/5`` loop wakes any blocked accept call and lets
the loop return with the client information terms accepted before the
shutdown request.

The ``serve_until_shutdown/4`` and ``serve_until_shutdown/5`` predicates
support the ``workers/1`` option family:

- ``workers(serial)`` serves accepted connections sequentially in the
  caller thread. This is the default.
- ``workers(per_connection)`` spawns one worker thread per accepted
  connection and waits for active workers when shutdown is requested.
- ``workers(pool(N))`` serves accepted connections using at most ``N``
  concurrent worker threads, waiting for worker completion notifications
  before accepting additional connections.
- ``workers(pool(N, rolling))`` is accepted as an explicit alias for the
  rolling fixed-size worker-pool policy used by ``workers(pool(N))``.

Open-ended serving loops should use a fresh control term for each call
to ``serve_until_shutdown/4`` or ``serve_until_shutdown/5``.

When the same listener, serving, or pool-management option is given
multiple times, the first occurrence is used.

WebSocket handshake workflow
----------------------------

The current WebSocket transport workflow is intentionally limited to the
opening handshake handoff:

- Client-side code can use ``http_client::open_websocket/4`` to obtain a
  reusable upgraded connection handle.
- Server-side code can use ``serve_websocket_once/5`` with a handler
  that builds a valid ``101 Switching Protocols`` response, typically
  via ``http_server_core::accept_websocket/3``.
- When the opening handshake succeeds, the returned upgraded connection
  remains open and its streams are available through
  ``connection_streams/3`` for use with ``http_websocket::read_frame/2``
  and ``http_websocket::write_frame/2`` or, at the next abstraction
  level, with ``http_websocket_messages::read_message/2`` and
  ``http_websocket_messages::write_message/2``, or with the stateful
  ``http_websocket_session`` layer when interleaved control frames and
  role-aware masking policies matter, including automatic close replies
  and optional automatic pong replies, or with the
  ``http_websocket_service`` layer, which provides the higher-level
  ``run_session/3-4`` callback loop that takes ownership of the upgraded
  connection and closes it automatically after the close handshake
  completes, the client-side ``http_websocket_client_service::open/4-5``
  convenience, and the server-side
  ``http_websocket_server_service::serve_once/6-7`` convenience.
- Rejected or malformed handshakes are written to the peer and then
  reported as errors by ``serve_websocket_once/5``; the accepted streams
  are closed in that case.

Current limitations
-------------------

- Availability depends on the supported backends of the ``sockets``
  library.
- The library does not provide TLS or URL-based request helpers.
- The WebSocket transport helper is limited to the opening handshake and
  upgraded connection handle management. It does not provide frame
  parsing, message I/O, or higher-level session handling.
- The ``workers(per_connection)`` and ``workers(pool(N))`` options
  depend on backend thread support.
- Server-side helpers do not provide supervision trees.
