LCOV - code coverage report
Current view: top level - lib - lwan.h (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 9 9 100.0 %
Date: 2023-04-18 16:19:03 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * lwan - web server
       3             :  * Copyright (c) 2012 L. A. F. Pereira <l@tia.mat.br>
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU General Public License
       7             :  * as published by the Free Software Foundation; either version 2
       8             :  * of the License, or any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :  * GNU General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License
      16             :  * along with this program; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
      18             :  * USA.
      19             :  */
      20             : 
      21             : #pragma once
      22             : 
      23             : #if defined(__cplusplus)
      24             : extern "C" {
      25             : #endif
      26             : 
      27             : #include <netinet/in.h>
      28             : #include <pthread.h>
      29             : #include <stdbool.h>
      30             : #include <stdint.h>
      31             : #include <string.h>
      32             : 
      33             : #include "hash.h"
      34             : #include "timeout.h"
      35             : #include "lwan-array.h"
      36             : #include "lwan-config.h"
      37             : #include "lwan-coro.h"
      38             : #include "lwan-status.h"
      39             : #include "lwan-strbuf.h"
      40             : #include "lwan-trie.h"
      41             : 
      42             : #if defined(__cplusplus)
      43             : #define ZERO_IF_IS_ARRAY(array) 0
      44             : #else
      45             : /* This macro expands to 0 if its parameter is an array, and causes a
      46             :  * compilation error otherwise.  This is used by the N_ELEMENTS() macro to catch
      47             :  * invalid usages of this macro (e.g. when using arrays decayed to pointers) */
      48             : #define ZERO_IF_IS_ARRAY(array)                                                \
      49             :     (!sizeof(char[1 - 2 * __builtin_types_compatible_p(                        \
      50             :                               __typeof__(array), __typeof__(&(array)[0]))]))
      51             : #endif
      52             : 
      53             : #define N_ELEMENTS(array)                                                      \
      54             :     (ZERO_IF_IS_ARRAY(array) | sizeof(array) / sizeof(array[0]))
      55             : 
      56             : 
      57             : #ifdef __APPLE__
      58             : #define LWAN_SECTION_NAME(name_) "__DATA," #name_
      59             : #else
      60             : #define LWAN_SECTION_NAME(name_) #name_
      61             : #endif
      62             : 
      63             : #define LWAN_MODULE_REF(name_) lwan_module_info_##name_.module
      64             : #define LWAN_MODULE_FORWARD_DECL(name_)                                        \
      65             :     extern const struct lwan_module_info lwan_module_info_##name_;
      66             : #define LWAN_REGISTER_MODULE(name_, module_)                                   \
      67             :     const struct lwan_module_info                                              \
      68             :         __attribute__((used, section(LWAN_SECTION_NAME(lwan_module))))         \
      69             :             lwan_module_info_##name_ = {.name = #name_, .module = module_}
      70             : 
      71             : #define LWAN_HANDLER_REF(name_) lwan_handler_##name_
      72             : 
      73             : #define LWAN_HANDLER_ROUTE(name_, route_)                                      \
      74             :     static enum lwan_http_status lwan_handler_##name_(                         \
      75             :         struct lwan_request *, struct lwan_response *, void *);                \
      76             :     static const struct lwan_handler_info                                      \
      77             :         __attribute__((used, section(LWAN_SECTION_NAME(lwan_handler))))        \
      78             :         __attribute__((aligned(8))) /* FIXME: why is this alignment needed? */ \
      79             :         lwan_handler_info_##name_ = {                                          \
      80             :             .name = #name_,                                                    \
      81             :             .route = route_,                                                   \
      82             :             .handler = lwan_handler_##name_,                                   \
      83             :     };                                                                         \
      84             :     __attribute__((used)) static enum lwan_http_status lwan_handler_##name_(   \
      85             :         struct lwan_request *request __attribute__((unused)),                  \
      86             :         struct lwan_response *response __attribute__((unused)),                \
      87             :         void *data __attribute__((unused)))
      88             : #define LWAN_HANDLER(name_) LWAN_HANDLER_ROUTE(name_, NULL)
      89             : 
      90             : #define ALWAYS_INLINE inline __attribute__((always_inline))
      91             : 
      92             : #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
      93             : #define STR4_INT(a, b, c, d) ((uint32_t)((a) | (b) << 8 | (c) << 16 | (d) << 24))
      94             : #define STR2_INT(a, b) ((uint16_t)((a) | (b) << 8))
      95             : #define STR8_INT(a, b, c, d, e, f, g, h)                                       \
      96             :     ((uint64_t)STR4_INT(a, b, c, d) | (uint64_t)STR4_INT(e, f, g, h) << 32)
      97             : #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
      98             : #define STR4_INT(d, c, b, a) ((uint32_t)((a) | (b) << 8 | (c) << 16 | (d) << 24))
      99             : #define STR2_INT(b, a) ((uint16_t)((a) | (b) << 8))
     100             : #define STR8_INT(a, b, c, d, e, f, g, h)                                       \
     101             :     ((uint64_t)STR4_INT(a, b, c, d) << 32 | (uint64_t)STR4_INT(e, f, g, h))
     102             : #elif __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__
     103             : #error A PDP? Seriously?
     104             : #endif
     105             : 
     106             : static ALWAYS_INLINE uint16_t string_as_uint16(const char *s)
     107             : {
     108             :     uint16_t u;
     109             : 
     110        2344 :     memcpy(&u, s, sizeof(u));
     111             : 
     112        2344 :     return u;
     113             : }
     114             : 
     115             : static ALWAYS_INLINE uint32_t string_as_uint32(const char *s)
     116             : {
     117             :     uint32_t u;
     118             : 
     119        6498 :     memcpy(&u, s, sizeof(u));
     120             : 
     121        6498 :     return u;
     122             : }
     123             : 
     124             : static ALWAYS_INLINE uint64_t string_as_uint64(const char *s)
     125             : {
     126             :     uint64_t u;
     127             : 
     128         593 :     memcpy(&u, s, sizeof(u));
     129             : 
     130         593 :     return u;
     131             : }
     132             : 
     133             : #define LOWER2(s) ((s) | (uint16_t)0x2020)
     134             : #define LOWER4(s) ((s) | (uint32_t)0x20202020)
     135             : #define LOWER8(s) ((s) | (uint64_t)0x2020202020202020)
     136             : 
     137             : #define STR2_INT_L(a, b) LOWER2(STR2_INT(a, b))
     138             : #define STR4_INT_L(a, b, c, d) LOWER4(STR4_INT(a, b, c, d))
     139             : #define STR8_INT_L(a, b, c, d, e, f, g, h) LOWER8(STR8_INT(a, b, c, d, e, f, g, h))
     140             : 
     141             : #define STRING_SWITCH_SMALL(s) switch (string_as_uint16(s))
     142             : #define STRING_SWITCH_SMALL_L(s) switch (LOWER2(string_as_uint16(s)))
     143             : #define STRING_SWITCH(s) switch (string_as_uint32(s))
     144             : #define STRING_SWITCH_L(s) switch (LOWER4(string_as_uint32(s)))
     145             : #define STRING_SWITCH_LARGE(s) switch (string_as_uint64(s))
     146             : #define STRING_SWITCH_LARGE_L(s) switch (LOWER8(string_as_uint64(s)))
     147             : 
     148             : #define LIKELY_IS(x, y) __builtin_expect((x), (y))
     149             : #define LIKELY(x) LIKELY_IS(!!(x), 1)
     150             : #define UNLIKELY(x) LIKELY_IS((x), 0)
     151             : 
     152             : #define ATOMIC_READ(V) (*(volatile typeof(V) *)&(V))
     153             : #define ATOMIC_OP(P, O, V) (__sync_##O##_and_fetch((P), (V)))
     154             : #define ATOMIC_AAF(P, V) ATOMIC_OP((P), add, (V))
     155             : #define ATOMIC_SAF(P, V) ATOMIC_OP((P), sub, (V))
     156             : #define ATOMIC_INC(V) ATOMIC_AAF(&(V), 1)
     157             : #define ATOMIC_DEC(V) ATOMIC_SAF(&(V), 1)
     158             : 
     159             : #if defined(__cplusplus)
     160             : #define LWAN_ARRAY_PARAM(length) [length]
     161             : #else
     162             : #define LWAN_ARRAY_PARAM(length) [static length]
     163             : #endif
     164             : 
     165             : #define FOR_EACH_HTTP_STATUS(X)                                                                                                             \
     166             :     X(SWITCHING_PROTOCOLS, 101, "Switching protocols", "Protocol is switching over from HTTP")                                              \
     167             :     X(OK, 200, "OK", "Success")                                                                                                             \
     168             :     X(PARTIAL_CONTENT, 206, "Partial content", "Delivering part of requested resource")                                                     \
     169             :     X(MOVED_PERMANENTLY, 301, "Moved permanently", "This content has moved to another place")                                               \
     170             :     X(NOT_MODIFIED, 304, "Not modified", "The content has not changed since previous request")                                              \
     171             :     X(TEMPORARY_REDIRECT, 307, "Temporary Redirect", "This content can be temporarily found at a different location")                       \
     172             :     X(BAD_REQUEST, 400, "Bad request", "The client has issued a bad request")                                                               \
     173             :     X(NOT_AUTHORIZED, 401, "Not authorized", "Client has no authorization to access this resource")                                         \
     174             :     X(FORBIDDEN, 403, "Forbidden", "Access to this resource has been denied")                                                               \
     175             :     X(NOT_FOUND, 404, "Not found", "The requested resource could not be found on this server")                                              \
     176             :     X(NOT_ALLOWED, 405, "Not allowed", "The requested method is not allowed by this server")                                                \
     177             :     X(TIMEOUT, 408, "Request timeout", "Client did not produce a request within expected timeframe")                                        \
     178             :     X(TOO_LARGE, 413, "Request too large", "The request entity is too large")                                                               \
     179             :     X(RANGE_UNSATISFIABLE, 416, "Requested range unsatisfiable", "The server can't supply the requested portion of the requested resource") \
     180             :     X(I_AM_A_TEAPOT, 418, "I'm a teapot", "Client requested to brew coffee but device is a teapot")                                         \
     181             :     X(CLIENT_TOO_HIGH, 420, "Client too high", "Client is too high to make a request")                                                      \
     182             :     X(INTERNAL_ERROR, 500, "Internal server error", "The server encountered an internal error that couldn't be recovered from")             \
     183             :     X(NOT_IMPLEMENTED, 501, "Not implemented", "Server lacks the ability to fulfil the request")                                            \
     184             :     X(UNAVAILABLE, 503, "Service unavailable", "The server is either overloaded or down for maintenance")                                   \
     185             :     X(SERVER_TOO_HIGH, 520, "Server too high", "The server is too high to answer the request")
     186             : 
     187             : #define GENERATE_ENUM_ITEM(id, code, short, long) HTTP_ ## id = code,
     188             : enum lwan_http_status {
     189             :     HTTP_CLASS__INFORMATIONAL = 100,
     190             :     HTTP_CLASS__SUCCESS = 200,
     191             :     HTTP_CLASS__REDIRECT = 300,
     192             :     HTTP_CLASS__CLIENT_ERROR = 400,
     193             :     HTTP_CLASS__SERVER_ERROR = 500,
     194             : 
     195             :     FOR_EACH_HTTP_STATUS(GENERATE_ENUM_ITEM)
     196             : };
     197             : #undef GENERATE_ENUM_ITEM
     198             : 
     199             : enum lwan_handler_flags {
     200             :     HANDLER_EXPECTS_BODY_DATA = 1 << 0,
     201             :     HANDLER_MUST_AUTHORIZE = 1 << 1,
     202             :     HANDLER_CAN_REWRITE_URL = 1 << 2,
     203             :     HANDLER_DATA_IS_HASH_TABLE = 1 << 3,
     204             : 
     205             :     HANDLER_PARSE_MASK = HANDLER_EXPECTS_BODY_DATA,
     206             : };
     207             : 
     208             : /* 1<<0 set: response has body; see has_response_body() in lwan-response.c */
     209             : /* 1<<3 set: request has body; see request_has_body() in lwan-request.c */
     210             : #define FOR_EACH_REQUEST_METHOD(X)                                                \
     211             :     X(GET, get, (1 << 0), (STR4_INT('G', 'E', 'T', ' ')), 0.6)                    \
     212             :     X(POST, post, (1 << 3 | 1 << 1 | 1 << 0), (STR4_INT('P', 'O', 'S', 'T')), 0.2)\
     213             :     X(HEAD, head, (1 << 1), (STR4_INT('H', 'E', 'A', 'D')), 0.2)                  \
     214             :     X(OPTIONS, options, (1 << 2), (STR4_INT('O', 'P', 'T', 'I')), 0.1)            \
     215             :     X(DELETE, delete, (1 << 1 | 1 << 2), (STR4_INT('D', 'E', 'L', 'E')), 0.1)     \
     216             :     X(PUT, put, (1 << 3 | 1 << 2 | 1 << 0), (STR4_INT('P', 'U', 'T', ' ')), 0.1)
     217             : 
     218             : #define SELECT_MASK(upper, lower, mask, constant, probability) mask |
     219             : #define GENERATE_ENUM_ITEM(upper, lower, mask, constant, probability) REQUEST_METHOD_##upper = mask,
     220             : 
     221             : enum lwan_request_flags {
     222             :     REQUEST_ALL_FLAGS = -1,
     223             : 
     224             :     REQUEST_METHOD_MASK = FOR_EACH_REQUEST_METHOD(SELECT_MASK) 0,
     225             :     FOR_EACH_REQUEST_METHOD(GENERATE_ENUM_ITEM)
     226             : 
     227             :     REQUEST_ACCEPT_DEFLATE = 1 << 4,
     228             :     REQUEST_ACCEPT_GZIP = 1 << 5,
     229             :     REQUEST_ACCEPT_BROTLI = 1 << 6,
     230             :     REQUEST_ACCEPT_ZSTD = 1 << 7,
     231             :     REQUEST_ACCEPT_MASK = 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7,
     232             : 
     233             :     REQUEST_IS_HTTP_1_0 = 1 << 8,
     234             :     REQUEST_ALLOW_PROXY_REQS = 1 << 9,
     235             :     REQUEST_PROXIED = 1 << 10,
     236             :     REQUEST_ALLOW_CORS = 1 << 11,
     237             : 
     238             :     RESPONSE_SENT_HEADERS = 1 << 12,
     239             :     RESPONSE_CHUNKED_ENCODING = 1 << 13,
     240             :     RESPONSE_NO_CONTENT_LENGTH = 1 << 14,
     241             :     RESPONSE_NO_EXPIRES = 1 << 15,
     242             :     RESPONSE_URL_REWRITTEN = 1 << 16,
     243             : 
     244             :     RESPONSE_STREAM = 1 << 17,
     245             : 
     246             :     REQUEST_PARSED_QUERY_STRING = 1 << 18,
     247             :     REQUEST_PARSED_IF_MODIFIED_SINCE = 1 << 19,
     248             :     REQUEST_PARSED_RANGE = 1 << 20,
     249             :     REQUEST_PARSED_FORM_DATA = 1 << 21,
     250             :     REQUEST_PARSED_COOKIES = 1 << 22,
     251             :     REQUEST_PARSED_ACCEPT_ENCODING = 1 << 23,
     252             : 
     253             :     RESPONSE_INCLUDE_REQUEST_ID = 1 << 24,
     254             : 
     255             :     REQUEST_HAS_QUERY_STRING = 1 << 25,
     256             : 
     257             :     REQUEST_WANTS_HSTS_HEADER = 1 << 26,
     258             : };
     259             : 
     260             : #undef SELECT_MASK
     261             : #undef GENERATE_ENUM_ITEM
     262             : 
     263             : enum lwan_connection_flags {
     264             :     CONN_MASK = -1,
     265             : 
     266             :     /* These flags have smaller numbers so that the table to convert
     267             :      * them to epoll events is smaller.  See conn_flags_to_epoll_events(). */
     268             :     CONN_EVENTS_READ = 1 << 0,
     269             :     CONN_EVENTS_WRITE = 1 << 1,
     270             :     CONN_EVENTS_READ_WRITE = CONN_EVENTS_READ | CONN_EVENTS_WRITE,
     271             :     CONN_EVENTS_MASK = 1 << 0 | 1 << 1,
     272             : 
     273             :     CONN_IS_KEEP_ALIVE = 1 << 2,
     274             : 
     275             :     /* WebSockets-related flags. */
     276             :     CONN_IS_UPGRADE = 1 << 3,
     277             :     CONN_IS_WEBSOCKET = 1 << 4,
     278             : 
     279             :     /* These are used for a few different things:
     280             :      * - Avoid re-deferring callbacks to remove request from the timeout wheel
     281             :      *   after it has slept previously and is requesting to sleep again. (The
     282             :      *   timeout defer is disarmed right after resuming, and is only there because
     283             :      *   connections may be closed when they're suspended.)
     284             :      * - Distinguish file descriptor in event loop between the connection and
     285             :      *   an awaited file descriptor.  (This is set in the connection that's awaiting
     286             :      *   since the pointer to the connection is used as user_data in both cases.
     287             :      *   This is required to be able to resume the connection coroutine after the
     288             :      *   await is completed, and to bubble up errors in awaited file descriptors to
     289             :      *   request handlers rather than abruptly closing the connection.) */
     290             :     CONN_SUSPENDED = 1 << 5,
     291             :     CONN_HAS_REMOVE_SLEEP_DEFER = 1 << 6,
     292             :     CONN_AWAITED_FD = CONN_SUSPENDED | CONN_HAS_REMOVE_SLEEP_DEFER,
     293             : 
     294             :     /* Used when HTTP pipelining has been detected.  This enables usage of the
     295             :      * MSG_MORE flags when sending responses to batch as many short responses
     296             :      * as possible in a single TCP fragment. */
     297             :     CONN_CORK = 1 << 7,
     298             : 
     299             :     /* Set only on file descriptors being watched by async/await to determine
     300             :      * which epoll operation to use when suspending/resuming (ADD/MOD). Reset
     301             :      * whenever associated client connection is closed. */
     302             :     CONN_ASYNC_AWAIT = 1 << 8,
     303             : 
     304             :     CONN_SENT_CONNECTION_HEADER = 1 << 9,
     305             : 
     306             :     /* Both are used to know if an epoll event pertains to a listener rather
     307             :      * than a client.  */
     308             :     CONN_LISTENER_HTTP = 1 << 10,
     309             :     CONN_LISTENER_HTTPS = 1 << 11,
     310             : 
     311             :     /* Is this a TLS connection? */
     312             :     CONN_TLS = 1 << 12,
     313             : };
     314             : 
     315             : enum lwan_connection_coro_yield {
     316             :     /* Returns to the event loop and terminates the coroutine, freeing
     317             :      * all resources associated with it, including calling deferred
     318             :      * callback, and the coroutine itself. */
     319             :     CONN_CORO_ABORT,
     320             : 
     321             :     /* Return to the event loop without changing the epoll event mask
     322             :      * or any other flag in this coroutine. */
     323             :     CONN_CORO_YIELD,
     324             : 
     325             :     /* Returns to the event loop, and optionally change the epoll event
     326             :      * mask (if it's not already the expected one.) */
     327             :     CONN_CORO_WANT_READ,
     328             :     CONN_CORO_WANT_WRITE,
     329             :     CONN_CORO_WANT_READ_WRITE,
     330             : 
     331             :     /* If a connection coroutine yields with CONN_CORO_SUSPEND, then
     332             :      * it'll be resumed using CONN_CORO_RESUME from the event loop.
     333             :      * CONN_CORO_RESUME should never be used from within connections
     334             :      * themselves, and should be considered a private API. */
     335             :     CONN_CORO_SUSPEND,
     336             :     CONN_CORO_RESUME,
     337             : 
     338             :     /* Group async stuff together to make it easier to check if a connection
     339             :      * coroutine is yielding because of async reasons. */
     340             :     CONN_CORO_ASYNC_AWAIT_READ,
     341             :     CONN_CORO_ASYNC_AWAIT_WRITE,
     342             :     CONN_CORO_ASYNC_AWAIT_READ_WRITE,
     343             : 
     344             :     CONN_CORO_MAX,
     345             : 
     346             :     /* Private API used by the async/await mechanism.  Shouldn't be used
     347             :      * by handlers. */
     348             :     CONN_CORO_ASYNC = CONN_CORO_ASYNC_AWAIT_READ,
     349             : };
     350             : 
     351             : struct lwan_key_value {
     352             :     char *key;
     353             :     char *value;
     354             : };
     355             : 
     356             : struct lwan_request;
     357             : 
     358             : struct lwan_response {
     359             :     struct lwan_strbuf *buffer;
     360             :     const char *mime_type;
     361             : 
     362             :     union {
     363             :         struct {
     364             :             const struct lwan_key_value *headers;
     365             :         };
     366             : 
     367             :         struct {
     368             :             enum lwan_http_status (*callback)(struct lwan_request *request,
     369             :                                               void *data);
     370             :             void *data;
     371             :         } stream;
     372             :     };
     373             : };
     374             : 
     375             : struct lwan_value {
     376             :     char *value;
     377             :     size_t len;
     378             : };
     379             : 
     380             : struct lwan_connection {
     381             :     /* This structure is exactly 32-bytes on x86-64. If it is changed,
     382             :      * make sure the scheduler (lwan-thread.c) is updated as well. */
     383             :     enum lwan_connection_flags flags;
     384             :     unsigned int time_to_expire;
     385             :     struct coro *coro;
     386             :     struct lwan_thread *thread;
     387             :     int prev, next; /* for timeout queue */
     388             : };
     389             : 
     390             : struct lwan_proxy {
     391             :     union {
     392             :         struct sockaddr_in ipv4;
     393             :         struct sockaddr_in6 ipv6;
     394             :     } from, to;
     395             : };
     396             : 
     397        1850 : DEFINE_ARRAY_TYPE(lwan_key_value_array, struct lwan_key_value)
     398             : 
     399             : struct lwan_request_parser_helper;
     400             : 
     401             : struct lwan_request {
     402             :     enum lwan_request_flags flags;
     403             :     int fd;
     404             :     struct lwan_connection *conn;
     405             :     const struct lwan_value *const global_response_headers;
     406             : 
     407             :     struct lwan_request_parser_helper *helper;
     408             : 
     409             :     struct lwan_value url;
     410             :     struct lwan_value original_url;
     411             :     struct lwan_response response;
     412             : 
     413             :     struct lwan_proxy *proxy;
     414             :     struct timeout timeout;
     415             : };
     416             : 
     417             : struct lwan_module {
     418             :     enum lwan_http_status (*handle_request)(struct lwan_request *request,
     419             :                                             struct lwan_response *response,
     420             :                                             void *instance);
     421             : 
     422             :     void *(*create)(const char *prefix, void *args);
     423             :     void *(*create_from_hash)(const char *prefix, const struct hash *hash);
     424             :     void (*destroy)(void *instance);
     425             : 
     426             :     bool (*parse_conf)(void *instance, struct config *config);
     427             : 
     428             :     enum lwan_handler_flags flags;
     429             : };
     430             : 
     431             : struct lwan_module_info {
     432             :     const char *name;
     433             :     const struct lwan_module *module;
     434             : };
     435             : 
     436             : struct lwan_url_map_route_info {
     437             :     const char *route;
     438             :     enum lwan_http_status (*handler)(struct lwan_request *request,
     439             :                                      struct lwan_response *response,
     440             :                                      void *data);
     441             : };
     442             : 
     443             : struct lwan_handler_info {
     444             :     const char *name;
     445             :     enum lwan_http_status (*handler)(struct lwan_request *request,
     446             :                                      struct lwan_response *response,
     447             :                                      void *data);
     448             :     const char *route;
     449             : };
     450             : 
     451             : struct lwan_url_map {
     452             :     enum lwan_http_status (*handler)(struct lwan_request *request,
     453             :                                      struct lwan_response *response,
     454             :                                      void *data);
     455             :     void *data;
     456             : 
     457             :     const char *prefix;
     458             :     size_t prefix_len;
     459             :     enum lwan_handler_flags flags;
     460             : 
     461             :     const struct lwan_module *module;
     462             :     void *args;
     463             : 
     464             :     struct {
     465             :         char *realm;
     466             :         char *password_file;
     467             :     } authorization;
     468             : };
     469             : 
     470             : struct lwan_thread {
     471             :     struct lwan *lwan;
     472             :     struct {
     473             :         char date[30];
     474             :         char expires[30];
     475             :     } date;
     476             :     int epoll_fd;
     477             :     struct timeouts *wheel;
     478             :     int listen_fd;
     479             :     int tls_listen_fd;
     480             :     unsigned int cpu;
     481             :     pthread_t self;
     482             : };
     483             : 
     484             : struct lwan_straitjacket {
     485             :     const char *user_name;
     486             :     const char *chroot_path;
     487             :     bool drop_capabilities;
     488             : };
     489             : 
     490             : struct lwan_config {
     491             :     /* Field will be overridden during initialization. */
     492             :     enum lwan_request_flags request_flags;
     493             :     struct lwan_key_value *global_headers;
     494             : 
     495             :     char *listener;
     496             :     char *tls_listener;
     497             :     char *error_template;
     498             :     char *config_file_path;
     499             : 
     500             :     struct {
     501             :         char *cert;
     502             :         char *key;
     503             :         bool send_hsts_header;
     504             :     } ssl;
     505             : 
     506             :     size_t max_post_data_size;
     507             :     size_t max_put_data_size;
     508             : 
     509             :     unsigned int keep_alive_timeout;
     510             :     unsigned int expires;
     511             :     unsigned int n_threads;
     512             : 
     513             :     bool quiet;
     514             :     bool proxy_protocol;
     515             :     bool allow_cors;
     516             :     bool allow_post_temp_file;
     517             :     bool allow_put_temp_file;
     518             : };
     519             : 
     520             : struct lwan {
     521             :     struct lwan_trie url_map_trie;
     522             :     struct lwan_connection *conns;
     523             :     struct lwan_value headers;
     524             : 
     525             : #if defined(LWAN_HAVE_MBEDTLS)
     526             :     struct lwan_tls_context *tls;
     527             : #endif
     528             : 
     529             :     struct {
     530             :         struct lwan_thread *threads;
     531             : 
     532             :         unsigned int max_fd;
     533             :         unsigned int count;
     534             :         pthread_barrier_t barrier;
     535             :     } thread;
     536             : 
     537             :     struct lwan_config config;
     538             : 
     539             :     unsigned int online_cpus;
     540             :     unsigned int available_cpus;
     541             : };
     542             : 
     543             : void lwan_set_url_map(struct lwan *l, const struct lwan_url_map *map);
     544             : void lwan_detect_url_map(struct lwan *l);
     545             : void lwan_main_loop(struct lwan *l);
     546             : 
     547             : size_t lwan_prepare_response_header(struct lwan_request *request,
     548             :                                     enum lwan_http_status status,
     549             :                                     char header_buffer[],
     550             :                                     size_t header_buffer_size)
     551             :     __attribute__((warn_unused_result));
     552             : 
     553             : const char *lwan_request_get_post_param(struct lwan_request *request,
     554             :                                         const char *key)
     555             :     __attribute__((warn_unused_result, pure));
     556             : const char *lwan_request_get_query_param(struct lwan_request *request,
     557             :                                          const char *key)
     558             :     __attribute__((warn_unused_result, pure));
     559             : const char *lwan_request_get_cookie(struct lwan_request *request,
     560             :                                     const char *key)
     561             :     __attribute__((warn_unused_result, pure));
     562             : const char *lwan_request_get_header(struct lwan_request *request,
     563             :                                     const char *header)
     564             :     __attribute__((warn_unused_result));
     565             : 
     566             : void lwan_request_sleep(struct lwan_request *request, uint64_t ms);
     567             : 
     568             : bool lwan_response_set_chunked(struct lwan_request *request,
     569             :                                enum lwan_http_status status);
     570             : bool lwan_response_set_chunked_full(struct lwan_request *request,
     571             :                                     enum lwan_http_status status,
     572             :                                     const struct lwan_key_value *additional_headers);
     573             : void lwan_response_send_chunk(struct lwan_request *request);
     574             : void lwan_response_send_chunk_full(struct lwan_request *request,
     575             :                                    struct lwan_strbuf *strbuf);
     576             : 
     577             : bool lwan_response_set_event_stream(struct lwan_request *request,
     578             :                                     enum lwan_http_status status);
     579             : void lwan_response_send_event(struct lwan_request *request, const char *event);
     580             : 
     581             : const char *lwan_determine_mime_type_for_file_name(const char *file_name)
     582             :     __attribute__((pure)) __attribute__((warn_unused_result));
     583             : 
     584             : void lwan_init(struct lwan *l);
     585             : void lwan_init_with_config(struct lwan *l, const struct lwan_config *config);
     586             : void lwan_shutdown(struct lwan *l);
     587             : 
     588             : static inline int lwan_main(void)
     589             : {
     590             :     struct lwan l;
     591             : 
     592             :     lwan_init(&l);
     593             : 
     594             :     lwan_detect_url_map(&l);
     595             :     lwan_main_loop(&l);
     596             : 
     597             :     lwan_shutdown(&l);
     598             : 
     599             :     return 0;
     600             : }
     601             : 
     602             : const struct lwan_config *lwan_get_default_config(void);
     603             : 
     604             : const char *lwan_request_get_host(struct lwan_request *request);
     605             : 
     606             : const char *
     607             : lwan_request_get_remote_address(struct lwan_request *request,
     608             :                                 char buffer LWAN_ARRAY_PARAM(INET6_ADDRSTRLEN))
     609             :     __attribute__((warn_unused_result));
     610             : 
     611             : const char *
     612             : lwan_request_get_remote_address_and_port(struct lwan_request *request,
     613             :                                          char buffer LWAN_ARRAY_PARAM(INET6_ADDRSTRLEN),
     614             :                                          uint16_t *port)
     615             :     __attribute__((warn_unused_result));
     616             : 
     617             : static inline enum lwan_request_flags
     618        1644 : lwan_request_get_method(const struct lwan_request *request)
     619             : {
     620        1644 :     return (enum lwan_request_flags)(request->flags & REQUEST_METHOD_MASK);
     621             : }
     622             : const char *lwan_request_get_method_str(const struct lwan_request *request);
     623             : 
     624             : int lwan_request_get_range(struct lwan_request *request,
     625             :                            off_t *from,
     626             :                            off_t *to);
     627             : int lwan_request_get_if_modified_since(struct lwan_request *request,
     628             :                                        time_t *value);
     629             : const struct lwan_value *
     630             : lwan_request_get_request_body(struct lwan_request *request);
     631             : const struct lwan_value *
     632             : lwan_request_get_content_type(struct lwan_request *request);
     633             : const struct lwan_key_value_array *
     634             : lwan_request_get_cookies(struct lwan_request *request);
     635             : const struct lwan_key_value_array *
     636             : lwan_request_get_query_params(struct lwan_request *request);
     637             : const struct lwan_key_value_array *
     638             : lwan_request_get_post_params(struct lwan_request *request);
     639             : enum lwan_request_flags
     640             : lwan_request_get_accept_encoding(struct lwan_request *request);
     641             : 
     642             : enum lwan_http_status
     643             : lwan_request_websocket_upgrade(struct lwan_request *request);
     644             : void lwan_response_websocket_write_text(struct lwan_request *request);
     645             : void lwan_response_websocket_write_binary(struct lwan_request *request);
     646             : int lwan_response_websocket_read(struct lwan_request *request);
     647             : int lwan_response_websocket_read_hint(struct lwan_request *request, size_t size_hint);
     648             : 
     649             : void lwan_request_await_read(struct lwan_request *r, int fd);
     650             : void lwan_request_await_write(struct lwan_request *r, int fd);
     651             : void lwan_request_await_read_write(struct lwan_request *r, int fd);
     652             : ssize_t lwan_request_async_read(struct lwan_request *r, int fd, void *buf, size_t len);
     653             : ssize_t lwan_request_async_read_flags(struct lwan_request *request, int fd, void *buf, size_t len, int flags);
     654             : ssize_t lwan_request_async_write(struct lwan_request *r, int fd, const void *buf, size_t len);
     655             : ssize_t lwan_request_async_writev(struct lwan_request *request,
     656             :                                   int fd,
     657             :                                   struct iovec *iov,
     658             :                                   int iov_count);
     659             : 
     660             : void lwan_straitjacket_enforce(const struct lwan_straitjacket *sj);
     661             : 
     662             : #if defined(__cplusplus)
     663             : }
     664             : #endif

Generated by: LCOV version 1.15-2-gb9d6727