LCOV - code coverage report
Current view: top level - waltz/http - fd_http_server.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 11 28 39.3 %
Date: 2026-09-17 04:28:31 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_waltz_http_fd_http_server_h
       2             : #define HEADER_fd_src_waltz_http_fd_http_server_h
       3             : 
       4             : /* An fd_http_server is a WebSocket capable HTTP server designed to
       5             :    stream output messages quickly to many connected clients, where each
       6             :    output message can go to many (and in some cases all) clients.
       7             : 
       8             :    The primary use case is for serving ongoing RPC data to RPC
       9             :    subscribers, but it also serves a WebSocket stream for browser
      10             :    clients to show the GUI.
      11             : 
      12             :    The server does not allocate and has a built in allocation strategy
      13             :    and memory region for outgoing messages which the caller should use.
      14             :    HTTP response bodies and WebSocket frames are placed into an outgoing
      15             :    ring buffer, wrapping around when reaching the end, and the server
      16             :    will automatically evict slow clients that do not read their messages
      17             :    in time and would be overwritten when the buffer has wrapped fully
      18             :    around.
      19             : 
      20             :    Using the outgoing ring has two steps,
      21             : 
      22             :      (1) Stage data into the ring with fd_http_server_printf and
      23             :          fd_http_server_memcpy functions.
      24             :      (2) Send the staged data to clients with fd_http_server_send and
      25             :          fd_http_server_oring_broadcast.
      26             : 
      27             :    The server is designed to be used in a single threaded event loop
      28             :    and run within a tile.  Server fds live in the epoll set provided
      29             :    at listen time; the caller calls fd_http_server_epoll_poll when the
      30             :    set is ready to service connections and make forward progress. */
      31             : 
      32             : #include "../../util/fd_util_base.h"
      33             : #include "../../util/net/fd_ip6.h"
      34             : 
      35         342 : #define FD_HTTP_SERVER_ALIGN       (128UL)
      36             : 
      37        1179 : #define FD_HTTP_SERVER_METHOD_GET     (0)
      38          18 : #define FD_HTTP_SERVER_METHOD_POST    (1)
      39           0 : #define FD_HTTP_SERVER_METHOD_OPTIONS (2)
      40           3 : #define FD_HTTP_SERVER_METHOD_PUT     (3)
      41             : 
      42          45 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_OK                            ( -1)
      43           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_EVICTED                       ( -2)
      44           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_TOO_SLOW                      ( -3)
      45           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_EXPECTED_EOF                  ( -4)
      46          21 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_PEER_RESET                    ( -5)
      47           3 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_LARGE_REQUEST                 ( -6)
      48          21 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_BAD_REQUEST                   ( -7)
      49           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_MISSING_CONTENT_LENGTH_HEADER ( -8)
      50           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_UNKNOWN_METHOD                ( -9)
      51           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_PATH_TOO_LONG                 (-10)
      52           6 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_BAD_KEY                    (-11)
      53           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_UNEXPECTED_VERSION         (-12)
      54           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_MISSING_KEY_HEADER         (-13)
      55           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_MISSING_VERSION_HEADER     (-14)
      56           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_BAD_MASK                   (-15)
      57           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_UNKNOWN_OPCODE             (-16)
      58           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_OVERSIZE_FRAME             (-17)
      59           3 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_CLIENT_TOO_SLOW            (-18)
      60           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_MISSING_UPGRADE            (-19)
      61           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_EXPECTED_CONT_OPCODE       (-20)
      62           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_EXPECTED_TEXT_OPCODE       (-21)
      63           0 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_WS_CONTROL_FRAME_TOO_LARGE    (-22)
      64           6 : #define FD_HTTP_SERVER_CONNECTION_CLOSE_UNSUPPORTED_TRANSFER_ENCODING (-23)
      65             : 
      66             : /* Given a FD_HTTP_SERVER_CONNECTION_CLOSE_* reason code, a reason that
      67             :    a HTTP connection a client was closed, produce a human readable
      68             :    string describing the reason. */
      69             : 
      70             : FD_FN_CONST char const *
      71             : fd_http_server_connection_close_reason_str( int reason );
      72             : 
      73             : /* Given a FD_HTTP_SERVER_METHOD_* code, produce the string for that
      74             :    method. */
      75             : 
      76             : FD_FN_CONST char const *
      77             : fd_http_server_method_str( uchar method );
      78             : 
      79             : /* Parameters needed for constructing an HTTP server.  */
      80             : 
      81             : struct fd_http_server_params {
      82             :   ulong treap_seed;            /* Seed used to randomize connection treap priorities */
      83             :   ulong max_connection_cnt;    /* Maximum number of concurrent HTTP/1.1 connections open.  Connections are persistent and serve requests until the client closes or is evicted */
      84             :   ulong max_ws_connection_cnt; /* Maximum number of concurrent websocket connections open */
      85             :   ulong max_request_len;       /* Maximum total length of an HTTP request, including the terminating \r\n\r\n and any body in the case of a POST */
      86             :   ulong max_ws_recv_frame_len; /* Maximum size of an incoming websocket frame from the client.  Must be >= max_request_len */
      87             :   ulong max_ws_send_frame_cnt; /* Maximum number of outgoing websocket frames that can be queued before the client is disconnected */
      88             :   ulong outgoing_buffer_sz;    /* Size of the outgoing data ring, which is used to stage outgoing HTTP response bodies and WebSocket frames */
      89             :   ulong send_buffer_sz;        /* SO_SNDBUF for the listen socket, inherited by accepted sockets.  Zero leaves the kernel default */
      90             :   int   compress_websocket;    /* True if large websocket messages are compressed and sent as binary websocket frames */
      91             : };
      92             : 
      93             : typedef struct fd_http_server_params fd_http_server_params_t;
      94             : 
      95             : struct fd_http_server_request {
      96             :   ulong        connection_id; /* Unique identifier for the connection.  In [0, max_connection_cnt).  The connection ID is a unique identifier for the lifetime of the connection, and will be
      97             :                                  provided to close to indicate that the connection is closed.  After a connection is closed the ID may be recycled */
      98             : 
      99             :   uchar        method;        /* One of FD_HTTP_SERVER_METHOD_* indicating what the method of the request is */
     100             :   char const * path;          /* The NUL termoinated path component of the request.  Not sanitized and may contain arbitrary content.  Path is the full HTTP path of the request, for example
     101             :                                  "/img/monkeys/gorilla.jpg" */
     102             :   char const * path_raw;      /* The non-NUL-terminated path component backed by the connection request buffer.  Valid until the response has been sent */
     103             :   ulong        path_len;      /* The length of path_raw */
     104             : 
     105             :   void *       ctx;           /* The user provided context pointer passed when constructing the HTTP server */
     106             : 
     107             :   struct {
     108             :     char const * content_type;         /* The NUL terminated value of the Content-Type header of the request.  Not sanitized and may contain arbitrary content.  May be NULL if the header was not present */
     109             :     char const * accept_encoding;      /* The NUL terminated value of the Accept-Encoding header of the request.  Not sanitized and may contain arbitrary content.  May be NULL if the header was not present */
     110             :     char const * if_none_match;        /* The NUL terminated value of the If-None-Match header of the request.  Not sanitized and may contain arbitrary content.  Empty if the header was not present */
     111             :     int          compress_websocket;   /* True if the client has provided an `Sec-WebSocket-Protocol: compress-zstd` header indicating that the responder can choose to compress WebSocket frames with ZStandard.  Only large (>200 bytes) Server -> Client messages are compressed */
     112             :     int          upgrade_websocket;    /* True if the client has provided an `Upgrade: websocket` header, valid `Sec-WebSocket-Key` and supported `Sec-Websocket-Version`, indicating that the
     113             :                                           responder should upgrade the connection to a WebSocket by setting `upgrade_websocket` to 1 in the response */
     114             :   } headers;
     115             : 
     116             :   union {
     117             :     struct {
     118             :       uchar const * body;     /* The body of the HTTP request.  The body is byte data, might have internal NUL characters, and may not be NUL terminated */
     119             :       ulong         body_len; /* The length of the body of the HTTP request */
     120             :     } post;
     121             :   };
     122             : };
     123             : 
     124             : typedef struct fd_http_server_request fd_http_server_request_t;
     125             : 
     126             : /* A response issued by the server handler function to an HTTP request.
     127             : 
     128             :    The handler should typically create response bodies via. the HTTP
     129             :    server functions like fd_http_server_printf.  This allows the server
     130             :    to manage buffer lifetimes and ensure high performance.  If using
     131             :    the server buffers, the handler should not set a static_body or
     132             :    static_body_len, and should instead use fd_http_server_stage_body
     133             :    to snap off the staging buffer contents into the body.
     134             : 
     135             :    In certain cases, it is desirable to send static content where the
     136             :    lifetime of the buffer is known to outlive the HTTP server.  In
     137             :    that case, you can set body_static to non-NULL and body_len_static
     138             :    to the length of the body payload, and the server will send this
     139             :    data instead of the staged data instead.
     140             : 
     141             :    status is an HTTP status code.  If status is not 200, the response
     142             :    body is ignored and the server will send an empty response.
     143             : 
     144             :    If upgrade_websocket is true, the connection will be upgraded to a
     145             :    websocket, after which the handler will begin receiving websocket
     146             :    frames. */
     147             : 
     148             : struct fd_http_server_response {
     149             :   ulong status;                  /* Status code of the HTTP response */
     150             :   int   upgrade_websocket;       /* 1 if we should send a websocket upgrade response */
     151             :   int   compress_websocket;      /* 1 if we should add a `Sec-WebSocket-Protocol: compress-zstd` header to the response  */
     152             : 
     153             :   char const * content_type;     /* Content-Type to set in the HTTP response */
     154             :   char const * cache_control;    /* Cache-Control to set in the HTTP response */
     155             :   char const * link;             /* Link to set in the HTTP response */
     156             :   char const * content_encoding; /* Content-Encoding to set in the HTTP response */
     157             :   char const * vary;             /* Vary to set in the HTTP response */
     158             :   char const * etag;             /* ETag to set in the HTTP response */
     159             :   char const * location[2];      /* Location to set in the HTTP response (concatenated) */
     160             :   ulong        location_len[2];  /* Lengths of the two location fragments */
     161             : 
     162             :   char const * access_control_allow_origin;
     163             :   char const * access_control_allow_methods;
     164             :   char const * access_control_allow_headers;
     165             :   ulong        access_control_max_age;
     166             : 
     167             :   uchar const * static_body;     /* Response body to send.  Lifetime of response data must outlive the entire HTTP server. */
     168             :   ulong         static_body_len; /* Length of the response body */
     169             : 
     170             :   ulong _body_off;               /* Internal use only.  Offset into the outgoing buffer where the body starts */
     171             :   ulong _body_len;               /* Internal use only.  Length of the body in the outgoing buffer */
     172             : };
     173             : 
     174             : typedef struct fd_http_server_response fd_http_server_response_t;
     175             : 
     176             : struct fd_http_server_callbacks {
     177             :   /* Handle an incoming HTTP request.  The callback must be provided
     178             :      and is assumed to be non-NULL.  request is a representation of
     179             :      the incoming HTTP request.  The callback should return a response
     180             :      which will be sent to the client. */
     181             : 
     182             :   fd_http_server_response_t ( * request     )( fd_http_server_request_t const * request );
     183             : 
     184             :   /* Called when a regular HTTP connection is established.  Called
     185             :      immediately after the connection is accepted.  sockfd is the file
     186             :      descriptor of the socket.  ctx is the user provided context pointer
     187             :      provided when constructing the HTTP server.  The open callback can
     188             :      be NULL in which case the callback will not be invoked. */
     189             : 
     190             :   void                      ( * open        )( ulong conn_id, int sockfd, void * ctx );
     191             : 
     192             :   /* Close an HTTP connection.  Connections are persistent and may
     193             :      serve many requests, so this is not a per-request completion
     194             :      notification: it is called back when the connection closes, which
     195             :      happens after a response completes for HTTP/1.0 clients, explicit
     196             :      Connection: close, or pipelined requests, and otherwise when an
     197             :      error condition occurs, the connection is evicted, the client
     198             :      disconnects, or the caller force closes it by calling close.  If a
     199             :      connection is upgraded to a WebSocket connection, a close event is
     200             :      first sent once the HTTP upgrade response is sent, before a ws_open
     201             :      event is sent.  Close is not called when a WebSocket connection is
     202             :      closed, instead ws_close is called.  reason is one of
     203             :      FD_HTTP_SERVER_CONNECTION_CLOSE_* indicating why the connection is
     204             :      being closed.  ctx is the user provided context pointer provided
     205             :      when constructing the HTTP server.  The close callback can be NULL
     206             :      in which case the callback will not be invoked. */
     207             : 
     208             :   void                      ( * close       )( ulong conn_id, int reason, void * ctx );
     209             : 
     210             :   /* Called when a WebSocket is opened.  ws_conn_id in [0,
     211             :      max_ws_connection_cnt).  Connection IDs are recycled as WebSocket
     212             :      connections are closed.  Connection IDs overlap with regular
     213             :      (non-WebSocket) connection IDs, but are in a distinct namespace,
     214             :      and WebSocket connection 0 is different from regular connection 0.
     215             :      ctx is the user provided context pointer provided when constructing
     216             :      the HTTP server. */
     217             : 
     218             :   void                      ( * ws_open     )( ulong ws_conn_id, void * ctx );
     219             : 
     220             :   /* Called when a WebSocket message is received on the connection.
     221             :      data is the message data, and data_len is the length of the message
     222             :      data.  ctx is the user provided context pointer provided when
     223             :      constructing the HTTP server.  The data provided is valid only
     224             :      until the callback returns, and the buffer will be recycled again
     225             :      immediately.  data_len is in [0, max_ws_recv_frame_len). */
     226             : 
     227             :   void                      ( * ws_message  )( ulong ws_conn_id, uchar const * data, ulong data_len, void * ctx );
     228             : 
     229             :   /* Called when a WebSocket connection is closed.  reason is one of
     230             :      FD_HTTP_SERVER_CONNECTION_CLOSE_* indicating why the connection was
     231             :      closed.  ctx is the user provided context pointer provided when
     232             :      constructing the HTTP server.  Typical reasons for closing the
     233             :      WebSocket include the peer disconnecting or timing out, or being
     234             :      evicted to make space for a new incoming connection.  Also called
     235             :      back when the user of the API forcibly closes a connection by
     236             :      calling ws_close. */
     237             : 
     238             :   void                      ( * ws_close    )( ulong ws_conn_id, int reason, void * ctx );
     239             : };
     240             : 
     241             : typedef struct fd_http_server_callbacks fd_http_server_callbacks_t;
     242             : 
     243             : struct fd_http_server_private;
     244             : typedef struct fd_http_server_private fd_http_server_t;
     245             : 
     246             : FD_PROTOTYPES_BEGIN
     247             : 
     248             : /* fd_http_server_{align,footprint} give the needed alignment and
     249             :    footprint of a memory region suitable to hold an http server.
     250             : 
     251             :    fd_http_server_new formats memory region with suitable alignment and
     252             :    footprint suitable for holding a http server state.  Assumes shmem
     253             :    points on the caller to the first byte of the memory region owned by
     254             :    the caller to use.  Returns shmem on success and NULL on failure
     255             :    (logs details).  The memory region will be owned by the state on
     256             :    successful return.  The caller is not joined on return.
     257             : 
     258             :    fd_http_server_join joins the caller to a http server state. Assumes
     259             :    shhttp points to the first byte of the memory region holding the
     260             :    state.  Returns a local handle to the join on success (this is
     261             :    not necessarily a simple cast of the address) and NULL on failure
     262             :    (logs details).
     263             : 
     264             :    fd_http_server_leave leaves the caller's current local join to a http
     265             :    server state.  Returns a pointer to the memory region holding the
     266             :    state on success (this is not necessarily a simple cast of the
     267             :    address) and NULL on failure (logs details).  The caller is not
     268             :    joined on successful return.
     269             : 
     270             :    fd_http_server_delete unformats a memory region that holds a http
     271             :    server state.  Assumes shhttp points on the caller to the first
     272             :    byte of the memory region holding the state and that nobody is
     273             :    joined.  Returns a pointer to the memory region on success and NULL
     274             :    on failure (logs details).  The caller has ownership of the memory
     275             :    region on successful return. */
     276             : 
     277             : FD_FN_CONST ulong
     278             : fd_http_server_align( void );
     279             : 
     280             : FD_FN_CONST ulong
     281             : fd_http_server_footprint( fd_http_server_params_t params );
     282             : 
     283             : void *
     284             : fd_http_server_new( void *                     shmem,
     285             :                     fd_http_server_params_t    params,
     286             :                     fd_http_server_callbacks_t callbacks,
     287             :                     void *                     callback_ctx );
     288             : 
     289             : fd_http_server_t *
     290             : fd_http_server_join( void * shhttp );
     291             : 
     292             : void *
     293             : fd_http_server_leave( fd_http_server_t * http );
     294             : 
     295             : void *
     296             : fd_http_server_delete( void * shhttp );
     297             : 
     298             : /* fd_http_server_fd returns the file descriptor of the server.  The
     299             :    file descriptor is used to poll for incoming connections and data
     300             :    on the server. */
     301             : 
     302             : int
     303             : fd_http_server_fd( fd_http_server_t * http );
     304             : 
     305             : /* fd_http_server_listen binds and listens on the given IPv4 address
     306             :    and port.  All server fds (listen socket and connections, present
     307             :    and future) are registered in the provided epoll set,
     308             :    level-triggered, with EPOLLOUT armed only while a connection has
     309             :    pending output.  The server does not take ownership of epoll_fd.
     310             :    Logs an error and exits the process on failure. */
     311             : 
     312             : fd_http_server_t *
     313             : fd_http_server_listen( fd_http_server_t * http,
     314             :                        int                epoll_fd,
     315             :                        uint               address,
     316             :                        ushort             port );
     317             : 
     318             : /* fd_http_server_listen6 binds and listens on the given IPv6 address
     319             :    and port.  Logs an error and exits the process on failure.
     320             : 
     321             :    An IPv4-mapped address without a zone ID creates an AF_INET socket,
     322             :    any other address creates a dual stack AF_INET6 socket, which also
     323             :    accepts IPv4 clients if bound to the wildcard address (::). */
     324             : 
     325             : fd_http_server_t *
     326             : fd_http_server_listen6( fd_http_server_t *    http,
     327             :                         int                   epoll_fd,
     328             :                         fd_ip6_addr_t const * address,
     329             :                         ushort                port );
     330             : 
     331             : /* Close an active connection.  The connection ID must be an open
     332             :    open connection in [0, max_connection_cnt).  The connection will
     333             :    be forcibly (ungracefully) terminated.  The connection ID is released
     334             :    and should not be used again, as it may be recycled for a future
     335             :    connection.  If a close callback has been provided to the http
     336             :    server, it will be invoked with the reason provided. */
     337             : 
     338             : void
     339             : fd_http_server_close( fd_http_server_t * http,
     340             :                       ulong              conn_id,
     341             :                       int                reason );
     342             : 
     343             : /* Returns 1 if the If-None-Match field value matches etag, else 0.
     344             :    etag is the quoted strong validator the server would serve. */
     345             : 
     346             : int
     347             : fd_http_server_etag_matches( char const * if_none_match,
     348             :                              char const * etag );
     349             : 
     350             : /* fd_http_server_accept_encoding_q returns the qvalue, in thousandths
     351             :    (0..1000), that the NUL terminated Accept-Encoding header value gives
     352             :    content coding `coding` (whole token, case-insensitive, RFC 9110
     353             :    s12.5.3); 0 if the coding is absent or has q=0.  "*" is not honored;
     354             :    a request that accepts nothing on offer is served identity. */
     355             : 
     356             : int
     357             : fd_http_server_accept_encoding_q( char const * accept_encoding,
     358             :                                   char const * coding );
     359             : 
     360             : /* Close an active WebSocket connection.  The connection ID must be an
     361             :    open WebSocket connection ID in [0, max_ws_connection_cnt).  The
     362             :    connection will be forcibly (ungracefully) terminated.  The
     363             :    connection ID is released and should not be used again, as it may be
     364             :    recycled for a future WebSocket connection.  If a ws_close callback
     365             :    has been provided to the http server, it will be invoked with the
     366             :    reason provided. */
     367             : 
     368             : void
     369             : fd_http_server_ws_close( fd_http_server_t * http,
     370             :                          ulong              ws_conn_id,
     371             :                          int                reason );
     372             : 
     373             : /* fd_http_server_buffer_trunc truncates the pending message to the given length. */
     374             : 
     375             : void
     376             : fd_http_server_stage_trunc( fd_http_server_t * http,
     377             :                              ulong len );
     378             : 
     379             : /* fd_http_server_buffer_len returns the length of the pending message. */
     380             : 
     381             : ulong
     382             : fd_http_server_stage_len( fd_http_server_t * http );
     383             : 
     384             : /* fd_http_server_printf appends the rendered format string fmt into the
     385             :    staging area of the outgoing ring buffer.  Assumes http is a current
     386             :    local join.
     387             : 
     388             :    If appending to the ring buffer causes it to wrap around and
     389             :    overwrite existing data from a prior message, any connections which
     390             :    are still using data from the prior message will be evicted, as they
     391             :    cannot keep up.
     392             : 
     393             :    Once the full message has been appended into the outgoing ring buffer,
     394             :    the staged contents can be sent to all connected WebSocket clients of
     395             :    the HTTP server using fd_http_server_broadcast.  This will end the
     396             :    current staged message so future prints go into a new message.
     397             : 
     398             :    Printing is not error-free, it is assumed that the format string is
     399             :    valid but the entire outgoing buffer may not be large enough to hold
     400             :    the printed string.  In that case, the staging buffer is marked as
     401             :    being in an error state internally.  The next call to send or
     402             :    broadcast will fail, returning the error, and the error state will be
     403             :    cleared. */
     404             : 
     405             : void
     406             : fd_http_server_printf( fd_http_server_t * http,
     407             :                        char const *       fmt,
     408             :                        ... )  __attribute__((format (printf, 2, 3)));
     409             : 
     410             : /* fd_http_server_memcpy appends the data provided to the end of the
     411             :    staging area of the outgoing ring buffer.  Assumes http is a current
     412             :    local join.
     413             : 
     414             :    If appending to the ring buffer causes it to wrap around and
     415             :    overwrite existing data from a prior message, any connections which
     416             :    are still using data from the prior message will be evicted, as they
     417             :    cannot keep up.
     418             : 
     419             :    Once the full message has been appended into the outgoing ring buffer,
     420             :    the staged contents can be sent to all connected WebSocket clients of
     421             :    the HTTP server using fd_http_server_broadcast.  This will end the
     422             :    current staged message so future prints go into a new message.
     423             : 
     424             :    Appending is not error-free, it is assumed that the data provided is
     425             :    valid but the entire outgoing buffer may not be large enough to hold
     426             :    data_len bytes.  In that case, the staging buffer is marked as
     427             :    being in an error state internally.  The next call to send or
     428             :    broadcast will fail, returning the error, and the error state will be
     429             :    cleared. */
     430             : 
     431             : void
     432             : fd_http_server_memcpy( fd_http_server_t * http,
     433             :                        uchar const *      data,
     434             :                        ulong              data_len );
     435             : 
     436             : /* fd_http_server_append_start starts an in-place append operation.
     437             :    len is the amount of buffer space to reserve.  Returns a pointer to
     438             :    len bytes to which the user should write the message to, on success.
     439             :    On failure (insufficient buffer space), returns NULL. */
     440             : 
     441             : uchar *
     442             : fd_http_server_append_start( fd_http_server_t * http,
     443             :                              ulong              len );
     444             : 
     445             : /* fd_http_server_append_end finishes an earlier started in-place
     446             :    append.  len is the number of bytes that were actually written. */
     447             : 
     448             : void
     449             : fd_http_server_append_end( fd_http_server_t * http,
     450             :                            ulong              len );
     451             : 
     452             : /* fd_http_server_unstage unstages any data written into the staging
     453             :    buffer, clearing its contents.  It does not advance the ring buffer
     454             :    usage, and no clients will be evicted. */
     455             : 
     456             : void
     457             : fd_http_server_unstage( fd_http_server_t * http );
     458             : 
     459             : /* fd_http_server_stage_body marks the current contents of the staging
     460             :    buffer as the body of the response.  The response is then ready to be
     461             :    sent to the client.  Returns 0 on success and -1 on failure if the
     462             :    ring buffer is in an error state, and then clears the error state. */
     463             : 
     464             : int
     465             : fd_http_server_stage_body( fd_http_server_t *          http,
     466             :                            fd_http_server_response_t * response );
     467             : 
     468             : /* Send the contents of the staging buffer as a a WebSocket message to a
     469             :    single client.  The staging buffer is then cleared.  Returns -1 on
     470             :    failure if the ring buffer is an error state, and then clears the
     471             :    error state.
     472             : 
     473             :    The contents are marked as needing to be sent to the client, but this
     474             :    does not block or wait for them to send, which happens async as the
     475             :    client is able to read.  If the client reads too slow, and the
     476             :    staging buffer wraps around and is eventually overwritten by another
     477             :    printer, this client will be force disconnected as being too slow. */
     478             : 
     479             : int
     480             : fd_http_server_ws_send( fd_http_server_t * http,
     481             :                         ulong              ws_conn_id ); /* An existing, open connection.  In [0, max_ws_connection_cnt) */
     482             : 
     483             : /* Broadcast the contents of the staging buffer as a WebSocket message
     484             :    to all connected clients.  The staging buffer is then cleared.
     485             :    Returns -1 on failure if the ring buffer is an error state, and then
     486             :    clears the error state.
     487             : 
     488             :    The contents are marked as needing to be sent to the client, but this
     489             :    does not block or wait for them to send, which happens async as the
     490             :    client is able to read.  If the client reads too slow, and the
     491             :    staging buffer wraps around and is eventually overwritten by another
     492             :    printer, this client will be force disconnected as being too slow. */
     493             : 
     494             : int
     495             : fd_http_server_ws_broadcast( fd_http_server_t * http );
     496             : 
     497             : /* fd_http_server_epoll_poll drives the server forward: a non-blocking
     498             :    epoll_wait on the registered set, servicing only ready connections.
     499             :    conn_max limits the number of fds serviced per call (clamped to
     500             :    [1,64]); leftover readiness stays pending in the kernel and is
     501             :    picked up by the next call.  Returns 1 if there was any work to do
     502             :    on the HTTP server, or 0 otherwise.  Call repeatedly until it
     503             :    returns 0 to drain the set. */
     504             : 
     505             : int
     506             : fd_http_server_epoll_poll( fd_http_server_t * http,
     507             :                            ulong              conn_max );
     508             : 
     509             : FD_PROTOTYPES_END
     510             : 
     511             : #endif /* HEADER_fd_src_waltz_http_fd_http_server_h */

Generated by: LCOV version 1.14