| 1 | /* |
| 2 | * libwebsockets - small server side websockets and web server implementation |
| 3 | * |
| 4 | * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com> |
| 5 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 7 | * of this software and associated documentation files (the "Software"), to |
| 8 | * deal in the Software without restriction, including without limitation the |
| 9 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
| 10 | * sell copies of the Software, and to permit persons to whom the Software is |
| 11 | * furnished to do so, subject to the following conditions: |
| 12 | * |
| 13 | * The above copyright notice and this permission notice shall be included in |
| 14 | * all copies or substantial portions of the Software. |
| 15 | * |
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 22 | * IN THE SOFTWARE. |
| 23 | */ |
| 24 | |
| 25 | /* minimal space for typical headers and CSP stuff */ |
| 26 | |
| 27 | #define 2048 |
| 28 | |
| 29 | /*! \defgroup http HTTP |
| 30 | |
| 31 | Modules related to handling HTTP |
| 32 | */ |
| 33 | //@{ |
| 34 | |
| 35 | /*! \defgroup httpft HTTP File transfer |
| 36 | * \ingroup http |
| 37 | |
| 38 | APIs for sending local files in response to HTTP requests |
| 39 | */ |
| 40 | //@{ |
| 41 | |
| 42 | /** |
| 43 | * lws_get_mimetype() - Determine mimetype to use from filename |
| 44 | * |
| 45 | * \param file: filename |
| 46 | * \param m: NULL, or mount context |
| 47 | * |
| 48 | * This uses a canned list of known filetypes first, if no match and m is |
| 49 | * non-NULL, then tries a list of per-mount file suffix to mimtype mappings. |
| 50 | * |
| 51 | * Returns either NULL or a pointer to the mimetype matching the file. |
| 52 | */ |
| 53 | LWS_VISIBLE LWS_EXTERN const char * |
| 54 | lws_get_mimetype(const char *file, const struct lws_http_mount *m); |
| 55 | |
| 56 | /** |
| 57 | * lws_serve_http_file() - Send a file back to the client using http |
| 58 | * \param wsi: Websocket instance (available from user callback) |
| 59 | * \param file: The file to issue over http |
| 60 | * \param content_type: The http content type, eg, text/html |
| 61 | * \param other_headers: NULL or pointer to header string |
| 62 | * \param other_headers_len: length of the other headers if non-NULL |
| 63 | * |
| 64 | * This function is intended to be called from the callback in response |
| 65 | * to http requests from the client. It allows the callback to issue |
| 66 | * local files down the http link in a single step. |
| 67 | * |
| 68 | * Returning <0 indicates error and the wsi should be closed. Returning |
| 69 | * >0 indicates the file was completely sent and |
| 70 | * lws_http_transaction_completed() called on the wsi (and close if != 0) |
| 71 | * ==0 indicates the file transfer is started and needs more service later, |
| 72 | * the wsi should be left alone. |
| 73 | */ |
| 74 | LWS_VISIBLE LWS_EXTERN int |
| 75 | lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type, |
| 76 | const char *, int ); |
| 77 | |
| 78 | LWS_VISIBLE LWS_EXTERN int |
| 79 | lws_serve_http_file_fragment(struct lws *wsi); |
| 80 | //@} |
| 81 | |
| 82 | |
| 83 | enum http_status { |
| 84 | HTTP_STATUS_CONTINUE = 100, |
| 85 | |
| 86 | HTTP_STATUS_OK = 200, |
| 87 | HTTP_STATUS_NO_CONTENT = 204, |
| 88 | HTTP_STATUS_PARTIAL_CONTENT = 206, |
| 89 | |
| 90 | HTTP_STATUS_MOVED_PERMANENTLY = 301, |
| 91 | HTTP_STATUS_FOUND = 302, |
| 92 | HTTP_STATUS_SEE_OTHER = 303, |
| 93 | HTTP_STATUS_NOT_MODIFIED = 304, |
| 94 | |
| 95 | HTTP_STATUS_BAD_REQUEST = 400, |
| 96 | HTTP_STATUS_UNAUTHORIZED, |
| 97 | HTTP_STATUS_PAYMENT_REQUIRED, |
| 98 | HTTP_STATUS_FORBIDDEN, |
| 99 | HTTP_STATUS_NOT_FOUND, |
| 100 | HTTP_STATUS_METHOD_NOT_ALLOWED, |
| 101 | HTTP_STATUS_NOT_ACCEPTABLE, |
| 102 | HTTP_STATUS_PROXY_AUTH_REQUIRED, |
| 103 | HTTP_STATUS_REQUEST_TIMEOUT, |
| 104 | HTTP_STATUS_CONFLICT, |
| 105 | HTTP_STATUS_GONE, |
| 106 | HTTP_STATUS_LENGTH_REQUIRED, |
| 107 | HTTP_STATUS_PRECONDITION_FAILED, |
| 108 | HTTP_STATUS_REQ_ENTITY_TOO_LARGE, |
| 109 | HTTP_STATUS_REQ_URI_TOO_LONG, |
| 110 | HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, |
| 111 | HTTP_STATUS_REQ_RANGE_NOT_SATISFIABLE, |
| 112 | HTTP_STATUS_EXPECTATION_FAILED, |
| 113 | |
| 114 | HTTP_STATUS_INTERNAL_SERVER_ERROR = 500, |
| 115 | HTTP_STATUS_NOT_IMPLEMENTED, |
| 116 | HTTP_STATUS_BAD_GATEWAY, |
| 117 | HTTP_STATUS_SERVICE_UNAVAILABLE, |
| 118 | HTTP_STATUS_GATEWAY_TIMEOUT, |
| 119 | HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED, |
| 120 | }; |
| 121 | /*! \defgroup html-chunked-substitution HTML Chunked Substitution |
| 122 | * \ingroup http |
| 123 | * |
| 124 | * ##HTML chunked Substitution |
| 125 | * |
| 126 | * APIs for receiving chunks of text, replacing a set of variable names via |
| 127 | * a callback, and then prepending and appending HTML chunked encoding |
| 128 | * headers. |
| 129 | */ |
| 130 | //@{ |
| 131 | |
| 132 | struct lws_process_html_args { |
| 133 | char *p; /**< pointer to the buffer containing the data */ |
| 134 | int len; /**< length of the original data at p */ |
| 135 | int max_len; /**< maximum length we can grow the data to */ |
| 136 | int final; /**< set if this is the last chunk of the file */ |
| 137 | int chunked; /**< 0 == unchunked, 1 == produce chunk headers |
| 138 | (incompatible with HTTP/2) */ |
| 139 | }; |
| 140 | |
| 141 | typedef const char *(*lws_process_html_state_cb)(void *data, int index); |
| 142 | |
| 143 | struct lws_process_html_state { |
| 144 | char *start; /**< pointer to start of match */ |
| 145 | char swallow[16]; /**< matched character buffer */ |
| 146 | int pos; /**< position in match */ |
| 147 | void *data; /**< opaque pointer */ |
| 148 | const char * const *vars; /**< list of variable names */ |
| 149 | int count_vars; /**< count of variable names */ |
| 150 | |
| 151 | lws_process_html_state_cb replace; |
| 152 | /**< called on match to perform substitution */ |
| 153 | }; |
| 154 | |
| 155 | /*! lws_chunked_html_process() - generic chunked substitution |
| 156 | * \param args: buffer to process using chunked encoding |
| 157 | * \param s: current processing state |
| 158 | */ |
| 159 | LWS_VISIBLE LWS_EXTERN int |
| 160 | lws_chunked_html_process(struct lws_process_html_args *args, |
| 161 | struct lws_process_html_state *s); |
| 162 | //@} |
| 163 | |
| 164 | /** \defgroup HTTP-headers-read HTTP headers: read |
| 165 | * \ingroup http |
| 166 | * |
| 167 | * ##HTTP header releated functions |
| 168 | * |
| 169 | * In lws the client http headers are temporarily stored in a pool, only for the |
| 170 | * duration of the http part of the handshake. It's because in most cases, |
| 171 | * the header content is ignored for the whole rest of the connection lifetime |
| 172 | * and would then just be taking up space needlessly. |
| 173 | * |
| 174 | * During LWS_CALLBACK_HTTP when the URI path is delivered is the last time |
| 175 | * the http headers are still allocated, you can use these apis then to |
| 176 | * look at and copy out interesting header content (cookies, etc) |
| 177 | * |
| 178 | * Notice that the header total length reported does not include a terminating |
| 179 | * '\0', however you must allocate for it when using the _copy apis. So the |
| 180 | * length reported for a header containing "123" is 3, but you must provide |
| 181 | * a buffer of length 4 so that "123\0" may be copied into it, or the copy |
| 182 | * will fail with a nonzero return code. |
| 183 | * |
| 184 | * In the special case of URL arguments, like ?x=1&y=2, the arguments are |
| 185 | * stored in a token named for the method, eg, WSI_TOKEN_GET_URI if it |
| 186 | * was a GET or WSI_TOKEN_POST_URI if POST. You can check the total |
| 187 | * length to confirm the method. |
| 188 | * |
| 189 | * For URL arguments, each argument is stored urldecoded in a "fragment", so |
| 190 | * you can use the fragment-aware api lws_hdr_copy_fragment() to access each |
| 191 | * argument in turn: the fragments contain urldecoded strings like x=1 or y=2. |
| 192 | * |
| 193 | * As a convenience, lws has an api that will find the fragment with a |
| 194 | * given name= part, lws_get_urlarg_by_name(). |
| 195 | */ |
| 196 | ///@{ |
| 197 | |
| 198 | /** struct lws_tokens |
| 199 | * you need these to look at headers that have been parsed if using the |
| 200 | * LWS_CALLBACK_FILTER_CONNECTION callback. If a header from the enum |
| 201 | * list below is absent, .token = NULL and len = 0. Otherwise .token |
| 202 | * points to .len chars containing that header content. |
| 203 | */ |
| 204 | struct lws_tokens { |
| 205 | unsigned char *token; /**< pointer to start of the token */ |
| 206 | int len; /**< length of the token's value */ |
| 207 | }; |
| 208 | |
| 209 | /* enum lws_token_indexes |
| 210 | * these have to be kept in sync with lextable.h / minilex.c |
| 211 | * |
| 212 | * NOTE: These public enums are part of the abi. If you want to add one, |
| 213 | * add it at where specified so existing users are unaffected. |
| 214 | */ |
| 215 | enum lws_token_indexes { |
| 216 | WSI_TOKEN_GET_URI, /* 0 */ |
| 217 | WSI_TOKEN_POST_URI, |
| 218 | #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) |
| 219 | WSI_TOKEN_OPTIONS_URI, |
| 220 | #endif |
| 221 | WSI_TOKEN_HOST, |
| 222 | WSI_TOKEN_CONNECTION, |
| 223 | WSI_TOKEN_UPGRADE, /* 5 */ |
| 224 | WSI_TOKEN_ORIGIN, |
| 225 | #if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) |
| 226 | WSI_TOKEN_DRAFT, |
| 227 | #endif |
| 228 | WSI_TOKEN_CHALLENGE, |
| 229 | #if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) |
| 230 | WSI_TOKEN_EXTENSIONS, |
| 231 | WSI_TOKEN_KEY1, /* 10 */ |
| 232 | WSI_TOKEN_KEY2, |
| 233 | WSI_TOKEN_PROTOCOL, |
| 234 | WSI_TOKEN_ACCEPT, |
| 235 | WSI_TOKEN_NONCE, |
| 236 | #endif |
| 237 | WSI_TOKEN_HTTP, |
| 238 | #if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) |
| 239 | WSI_TOKEN_HTTP2_SETTINGS, /* 16 */ |
| 240 | #endif |
| 241 | WSI_TOKEN_HTTP_ACCEPT, |
| 242 | #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) |
| 243 | , |
| 244 | #endif |
| 245 | WSI_TOKEN_HTTP_IF_MODIFIED_SINCE, |
| 246 | WSI_TOKEN_HTTP_IF_NONE_MATCH, /* 20 */ |
| 247 | WSI_TOKEN_HTTP_ACCEPT_ENCODING, |
| 248 | WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, |
| 249 | WSI_TOKEN_HTTP_PRAGMA, |
| 250 | WSI_TOKEN_HTTP_CACHE_CONTROL, |
| 251 | WSI_TOKEN_HTTP_AUTHORIZATION, |
| 252 | WSI_TOKEN_HTTP_COOKIE, |
| 253 | WSI_TOKEN_HTTP_CONTENT_LENGTH, /* 27 */ |
| 254 | WSI_TOKEN_HTTP_CONTENT_TYPE, |
| 255 | WSI_TOKEN_HTTP_DATE, |
| 256 | WSI_TOKEN_HTTP_RANGE, |
| 257 | #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) |
| 258 | WSI_TOKEN_HTTP_REFERER, |
| 259 | #endif |
| 260 | #if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL) |
| 261 | WSI_TOKEN_KEY, |
| 262 | WSI_TOKEN_VERSION, |
| 263 | WSI_TOKEN_SWORIGIN, |
| 264 | #endif |
| 265 | #if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) |
| 266 | WSI_TOKEN_HTTP_COLON_AUTHORITY, |
| 267 | WSI_TOKEN_HTTP_COLON_METHOD, |
| 268 | WSI_TOKEN_HTTP_COLON_PATH, |
| 269 | WSI_TOKEN_HTTP_COLON_SCHEME, |
| 270 | WSI_TOKEN_HTTP_COLON_STATUS, |
| 271 | #endif |
| 272 | |
| 273 | #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) |
| 274 | WSI_TOKEN_HTTP_ACCEPT_CHARSET, |
| 275 | #endif |
| 276 | WSI_TOKEN_HTTP_ACCEPT_RANGES, |
| 277 | #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) |
| 278 | WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN, |
| 279 | #endif |
| 280 | WSI_TOKEN_HTTP_AGE, |
| 281 | WSI_TOKEN_HTTP_ALLOW, |
| 282 | WSI_TOKEN_HTTP_CONTENT_DISPOSITION, |
| 283 | WSI_TOKEN_HTTP_CONTENT_ENCODING, |
| 284 | WSI_TOKEN_HTTP_CONTENT_LANGUAGE, |
| 285 | WSI_TOKEN_HTTP_CONTENT_LOCATION, |
| 286 | WSI_TOKEN_HTTP_CONTENT_RANGE, |
| 287 | WSI_TOKEN_HTTP_ETAG, |
| 288 | WSI_TOKEN_HTTP_EXPECT, |
| 289 | WSI_TOKEN_HTTP_EXPIRES, |
| 290 | WSI_TOKEN_HTTP_FROM, |
| 291 | WSI_TOKEN_HTTP_IF_MATCH, |
| 292 | WSI_TOKEN_HTTP_IF_RANGE, |
| 293 | WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE, |
| 294 | WSI_TOKEN_HTTP_LAST_MODIFIED, |
| 295 | WSI_TOKEN_HTTP_LINK, |
| 296 | WSI_TOKEN_HTTP_LOCATION, |
| 297 | #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) |
| 298 | WSI_TOKEN_HTTP_MAX_FORWARDS, |
| 299 | WSI_TOKEN_HTTP_PROXY_AUTHENTICATE, |
| 300 | WSI_TOKEN_HTTP_PROXY_AUTHORIZATION, |
| 301 | #endif |
| 302 | WSI_TOKEN_HTTP_REFRESH, |
| 303 | WSI_TOKEN_HTTP_RETRY_AFTER, |
| 304 | WSI_TOKEN_HTTP_SERVER, |
| 305 | WSI_TOKEN_HTTP_SET_COOKIE, |
| 306 | #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) |
| 307 | WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY, |
| 308 | #endif |
| 309 | WSI_TOKEN_HTTP_TRANSFER_ENCODING, |
| 310 | #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) |
| 311 | WSI_TOKEN_HTTP_USER_AGENT, |
| 312 | WSI_TOKEN_HTTP_VARY, |
| 313 | WSI_TOKEN_HTTP_VIA, |
| 314 | WSI_TOKEN_HTTP_WWW_AUTHENTICATE, |
| 315 | #endif |
| 316 | #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) |
| 317 | WSI_TOKEN_PATCH_URI, |
| 318 | WSI_TOKEN_PUT_URI, |
| 319 | WSI_TOKEN_DELETE_URI, |
| 320 | #endif |
| 321 | |
| 322 | WSI_TOKEN_HTTP_URI_ARGS, |
| 323 | #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) |
| 324 | WSI_TOKEN_PROXY, |
| 325 | WSI_TOKEN_HTTP_X_REAL_IP, |
| 326 | #endif |
| 327 | WSI_TOKEN_HTTP1_0, |
| 328 | WSI_TOKEN_X_FORWARDED_FOR, |
| 329 | WSI_TOKEN_CONNECT, |
| 330 | WSI_TOKEN_HEAD_URI, |
| 331 | #if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) |
| 332 | WSI_TOKEN_TE, |
| 333 | WSI_TOKEN_REPLAY_NONCE, /* ACME */ |
| 334 | #endif |
| 335 | #if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL) |
| 336 | WSI_TOKEN_COLON_PROTOCOL, |
| 337 | #endif |
| 338 | WSI_TOKEN_X_AUTH_TOKEN, |
| 339 | WSI_TOKEN_DSS_SIGNATURE, |
| 340 | |
| 341 | /****** add new things just above ---^ ******/ |
| 342 | |
| 343 | /* use token storage to stash these internally, not for |
| 344 | * user use */ |
| 345 | |
| 346 | _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, |
| 347 | _WSI_TOKEN_CLIENT_PEER_ADDRESS, |
| 348 | _WSI_TOKEN_CLIENT_URI, |
| 349 | _WSI_TOKEN_CLIENT_HOST, |
| 350 | _WSI_TOKEN_CLIENT_ORIGIN, |
| 351 | _WSI_TOKEN_CLIENT_METHOD, |
| 352 | _WSI_TOKEN_CLIENT_IFACE, |
| 353 | _WSI_TOKEN_CLIENT_LOCALPORT, |
| 354 | _WSI_TOKEN_CLIENT_ALPN, |
| 355 | |
| 356 | /* always last real token index*/ |
| 357 | WSI_TOKEN_COUNT, |
| 358 | |
| 359 | /* parser state additions, no storage associated */ |
| 360 | WSI_TOKEN_NAME_PART, |
| 361 | #if defined(LWS_WITH_CUSTOM_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) |
| 362 | WSI_TOKEN_UNKNOWN_VALUE_PART, |
| 363 | #endif |
| 364 | WSI_TOKEN_SKIPPING, |
| 365 | WSI_TOKEN_SKIPPING_SAW_CR, |
| 366 | WSI_PARSING_COMPLETE, |
| 367 | WSI_INIT_TOKEN_MUXURL, |
| 368 | }; |
| 369 | |
| 370 | struct lws_token_limits { |
| 371 | unsigned short token_limit[WSI_TOKEN_COUNT]; /**< max chars for this token */ |
| 372 | }; |
| 373 | |
| 374 | enum lws_h2_settings { |
| 375 | = 1, |
| 376 | H2SET_ENABLE_PUSH, |
| 377 | H2SET_MAX_CONCURRENT_STREAMS, |
| 378 | H2SET_INITIAL_WINDOW_SIZE, |
| 379 | H2SET_MAX_FRAME_SIZE, |
| 380 | , |
| 381 | H2SET_RESERVED7, |
| 382 | H2SET_ENABLE_CONNECT_PROTOCOL, /* defined in mcmanus-httpbis-h2-ws-02 */ |
| 383 | |
| 384 | H2SET_COUNT /* always last */ |
| 385 | }; |
| 386 | |
| 387 | /** |
| 388 | * lws_token_to_string() - returns a textual representation of a hdr token index |
| 389 | * |
| 390 | * \param token: token index |
| 391 | */ |
| 392 | LWS_VISIBLE LWS_EXTERN const unsigned char * |
| 393 | lws_token_to_string(enum lws_token_indexes token); |
| 394 | |
| 395 | /** |
| 396 | * lws_hdr_total_length: report length of all fragments of a header totalled up |
| 397 | * The returned length does not include the space for a |
| 398 | * terminating '\0' |
| 399 | * |
| 400 | * \param wsi: websocket connection |
| 401 | * \param h: which header index we are interested in |
| 402 | */ |
| 403 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 404 | lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h); |
| 405 | |
| 406 | /** |
| 407 | * lws_hdr_fragment_length: report length of a single fragment of a header |
| 408 | * The returned length does not include the space for a |
| 409 | * terminating '\0' |
| 410 | * |
| 411 | * \param wsi: websocket connection |
| 412 | * \param h: which header index we are interested in |
| 413 | * \param frag_idx: which fragment of h we want to get the length of |
| 414 | */ |
| 415 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 416 | lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, |
| 417 | int frag_idx); |
| 418 | |
| 419 | /** |
| 420 | * lws_hdr_copy() - copy all fragments of the given header to a buffer |
| 421 | * The buffer length len must include space for an additional |
| 422 | * terminating '\0', or it will fail returning -1. |
| 423 | * |
| 424 | * \param wsi: websocket connection |
| 425 | * \param dest: destination buffer |
| 426 | * \param len: length of destination buffer |
| 427 | * \param h: which header index we are interested in |
| 428 | * |
| 429 | * copies the whole, aggregated header, even if it was delivered in |
| 430 | * several actual headers piece by piece. Returns -1 or length of the whole |
| 431 | * header. |
| 432 | */ |
| 433 | LWS_VISIBLE LWS_EXTERN int |
| 434 | lws_hdr_copy(struct lws *wsi, char *dest, int len, enum lws_token_indexes h); |
| 435 | |
| 436 | /** |
| 437 | * lws_hdr_copy_fragment() - copy a single fragment of the given header to a buffer |
| 438 | * The buffer length len must include space for an additional |
| 439 | * terminating '\0', or it will fail returning -2. |
| 440 | * If the requested fragment index is not present, it fails |
| 441 | * returning -1. |
| 442 | * |
| 443 | * \param wsi: websocket connection |
| 444 | * \param dest: destination buffer |
| 445 | * \param len: length of destination buffer |
| 446 | * \param h: which header index we are interested in |
| 447 | * \param frag_idx: which fragment of h we want to copy |
| 448 | * |
| 449 | * Normally this is only useful |
| 450 | * to parse URI arguments like ?x=1&y=2, token index WSI_TOKEN_HTTP_URI_ARGS |
| 451 | * fragment 0 will contain "x=1" and fragment 1 "y=2" |
| 452 | */ |
| 453 | LWS_VISIBLE LWS_EXTERN int |
| 454 | lws_hdr_copy_fragment(struct lws *wsi, char *dest, int len, |
| 455 | enum lws_token_indexes h, int frag_idx); |
| 456 | |
| 457 | /** |
| 458 | * lws_hdr_custom_length() - return length of a custom header |
| 459 | * |
| 460 | * \param wsi: websocket connection |
| 461 | * \param name: header string (including terminating :) |
| 462 | * \param nlen: length of name |
| 463 | * |
| 464 | * Lws knows about 100 common http headers, and parses them into indexes when |
| 465 | * it recognizes them. When it meets a header that it doesn't know, it stores |
| 466 | * the name and value directly, and you can look them up using |
| 467 | * lws_hdr_custom_length() and lws_hdr_custom_copy(). |
| 468 | * |
| 469 | * This api returns -1, or the length of the value part of the header if it |
| 470 | * exists. Lws must be built with LWS_WITH_CUSTOM_HEADERS (on by default) to |
| 471 | * use this api. |
| 472 | */ |
| 473 | LWS_VISIBLE LWS_EXTERN int |
| 474 | lws_hdr_custom_length(struct lws *wsi, const char *name, int nlen); |
| 475 | |
| 476 | /** |
| 477 | * lws_hdr_custom_copy() - copy value part of a custom header |
| 478 | * |
| 479 | * \param wsi: websocket connection |
| 480 | * \param dst: pointer to buffer to receive the copy |
| 481 | * \param len: number of bytes available at dst |
| 482 | * \param name: header string (including terminating :) |
| 483 | * \param nlen: length of name |
| 484 | * |
| 485 | * Lws knows about 100 common http headers, and parses them into indexes when |
| 486 | * it recognizes them. When it meets a header that it doesn't know, it stores |
| 487 | * the name and value directly, and you can look them up using |
| 488 | * lws_hdr_custom_length() and lws_hdr_custom_copy(). |
| 489 | * |
| 490 | * This api returns -1, or the length of the string it copied into dst if it |
| 491 | * was big enough to contain both the string and an extra terminating NUL. Lws |
| 492 | * must be built with LWS_WITH_CUSTOM_HEADERS (on by default) to use this api. |
| 493 | */ |
| 494 | LWS_VISIBLE LWS_EXTERN int |
| 495 | lws_hdr_custom_copy(struct lws *wsi, char *dst, int len, const char *name, |
| 496 | int nlen); |
| 497 | |
| 498 | typedef void (*lws_hdr_custom_fe_cb_t)(const char *name, int nlen, void *opaque); |
| 499 | /** |
| 500 | * lws_hdr_custom_name_foreach() - Iterate the custom header names |
| 501 | * |
| 502 | * \param wsi: websocket connection |
| 503 | * \param cb: callback for each custom header name |
| 504 | * \param opaque: ignored by lws except to pass to callback |
| 505 | * |
| 506 | * Lws knows about 100 common http headers, and parses them into indexes when |
| 507 | * it recognizes them. When it meets a header that it doesn't know, it stores |
| 508 | * the name and value directly, and you can look them up using |
| 509 | * lws_hdr_custom_length() and lws_hdr_custom_copy(). |
| 510 | * |
| 511 | * This api returns -1 on error else 0. Use lws_hdr_custom_copy() to get the |
| 512 | * values of headers. Lws must be built with LWS_WITH_CUSTOM_HEADERS (on by |
| 513 | * default) to use this api. |
| 514 | */ |
| 515 | LWS_VISIBLE LWS_EXTERN int |
| 516 | lws_hdr_custom_name_foreach(struct lws *wsi, lws_hdr_custom_fe_cb_t cb, void *opaque); |
| 517 | |
| 518 | /** |
| 519 | * lws_get_urlarg_by_name_safe() - get copy and return length of y for x=y urlargs |
| 520 | * |
| 521 | * \param wsi: the connection to check |
| 522 | * \param name: the arg name, like "token" or "token=" |
| 523 | * \param buf: the buffer to receive the urlarg (including the name= part) |
| 524 | * \param len: the length of the buffer to receive the urlarg |
| 525 | * |
| 526 | * Returns -1 if not present, else the length of y in the urlarg name=y. If |
| 527 | * zero or greater, then buf contains a copy of the string y. Any = after the |
| 528 | * name match is trimmed off if the name does not end with = itself. |
| 529 | * |
| 530 | * This returns the explicit length and so can deal with binary blobs that are |
| 531 | * percent-encoded. It also makes sure buf has a NUL just after the valid |
| 532 | * length so it can work with NUL-based apis if you don't care about truncation. |
| 533 | * |
| 534 | * buf may have been written even when -1 is returned indicating no match. |
| 535 | * |
| 536 | * Use this in place of lws_get_urlarg_by_name() that does not return an |
| 537 | * explicit length. |
| 538 | */ |
| 539 | LWS_VISIBLE LWS_EXTERN int |
| 540 | lws_get_urlarg_by_name_safe(struct lws *wsi, const char *name, char *buf, int len); |
| 541 | |
| 542 | /** |
| 543 | * lws_get_urlarg_by_name() - return pointer to arg value if present |
| 544 | * |
| 545 | * \param wsi: the connection to check |
| 546 | * \param name: the arg name, like "token=" |
| 547 | * \param buf: the buffer to receive the urlarg (including the name= part) |
| 548 | * \param len: the length of the buffer to receive the urlarg |
| 549 | * |
| 550 | * Returns NULL if not found or a pointer inside buf to just after the |
| 551 | * name= part. |
| 552 | * |
| 553 | * This assumed the argument can be represented with a NUL-terminated string. |
| 554 | * It can't correctly deal with binary values encoded with %XX, eg. %00 will |
| 555 | * be understood to terminate the string. |
| 556 | * |
| 557 | * Use lws_get_urlarg_by_name_safe() instead of this, which returns the length. |
| 558 | */ |
| 559 | LWS_VISIBLE LWS_EXTERN const char * |
| 560 | lws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len) |
| 561 | /* LWS_WARN_DEPRECATED */; |
| 562 | ///@} |
| 563 | |
| 564 | /*! \defgroup HTTP-headers-create HTTP headers: create |
| 565 | * |
| 566 | * ## HTTP headers: Create |
| 567 | * |
| 568 | * These apis allow you to create HTTP response headers in a way compatible with |
| 569 | * both HTTP/1.x and HTTP/2. |
| 570 | * |
| 571 | * They each append to a buffer taking care about the buffer end, which is |
| 572 | * passed in as a pointer. When data is written to the buffer, the current |
| 573 | * position p is updated accordingly. |
| 574 | * |
| 575 | * All of these apis are LWS_WARN_UNUSED_RESULT as they can run out of space |
| 576 | * and fail with nonzero return. |
| 577 | */ |
| 578 | ///@{ |
| 579 | |
| 580 | #define LWSAHH_CODE_MASK ((1 << 16) - 1) |
| 581 | #define LWSAHH_FLAG_NO_SERVER_NAME (1 << 30) |
| 582 | |
| 583 | /** |
| 584 | * lws_add_http_header_status() - add the HTTP response status code |
| 585 | * |
| 586 | * \param wsi: the connection to check |
| 587 | * \param code: an HTTP code like 200, 404 etc (see enum http_status) |
| 588 | * \param p: pointer to current position in buffer pointer |
| 589 | * \param end: pointer to end of buffer |
| 590 | * |
| 591 | * Adds the initial response code, so should be called first. |
| 592 | * |
| 593 | * Code may additionally take OR'd flags: |
| 594 | * |
| 595 | * LWSAHH_FLAG_NO_SERVER_NAME: don't apply server name header this time |
| 596 | */ |
| 597 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 598 | (struct lws *wsi, |
| 599 | unsigned int code, unsigned char **p, |
| 600 | unsigned char *end); |
| 601 | /** |
| 602 | * lws_add_http_header_by_name() - append named header and value |
| 603 | * |
| 604 | * \param wsi: the connection to check |
| 605 | * \param name: the hdr name, like "my-header:" |
| 606 | * \param value: the value after the = for this header |
| 607 | * \param length: the length of the value |
| 608 | * \param p: pointer to current position in buffer pointer |
| 609 | * \param end: pointer to end of buffer |
| 610 | * |
| 611 | * Appends name: value to the headers |
| 612 | */ |
| 613 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 614 | (struct lws *wsi, const unsigned char *name, |
| 615 | const unsigned char *value, int length, |
| 616 | unsigned char **p, unsigned char *end); |
| 617 | /** |
| 618 | * lws_add_http_header_by_token() - append given header and value |
| 619 | * |
| 620 | * \param wsi: the connection to check |
| 621 | * \param token: the token index for the hdr |
| 622 | * \param value: the value after the = for this header |
| 623 | * \param length: the length of the value |
| 624 | * \param p: pointer to current position in buffer pointer |
| 625 | * \param end: pointer to end of buffer |
| 626 | * |
| 627 | * Appends name=value to the headers, but is able to take advantage of better |
| 628 | * HTTP/2 coding mechanisms where possible. |
| 629 | */ |
| 630 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 631 | (struct lws *wsi, enum lws_token_indexes token, |
| 632 | const unsigned char *value, int length, |
| 633 | unsigned char **p, unsigned char *end); |
| 634 | /** |
| 635 | * lws_add_http_header_content_length() - append content-length helper |
| 636 | * |
| 637 | * \param wsi: the connection to check |
| 638 | * \param content_length: the content length to use |
| 639 | * \param p: pointer to current position in buffer pointer |
| 640 | * \param end: pointer to end of buffer |
| 641 | * |
| 642 | * Appends content-length: content_length to the headers |
| 643 | */ |
| 644 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 645 | (struct lws *wsi, |
| 646 | lws_filepos_t content_length, |
| 647 | unsigned char **p, unsigned char *end); |
| 648 | /** |
| 649 | * lws_finalize_http_header() - terminate header block |
| 650 | * |
| 651 | * \param wsi: the connection to check |
| 652 | * \param p: pointer to current position in buffer pointer |
| 653 | * \param end: pointer to end of buffer |
| 654 | * |
| 655 | * Indicates no more headers will be added |
| 656 | */ |
| 657 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 658 | (struct lws *wsi, unsigned char **p, |
| 659 | unsigned char *end); |
| 660 | |
| 661 | /** |
| 662 | * lws_finalize_write_http_header() - Helper finializing and writing http headers |
| 663 | * |
| 664 | * \param wsi: the connection to check |
| 665 | * \param start: pointer to the start of headers in the buffer, eg &buf[LWS_PRE] |
| 666 | * \param p: pointer to current position in buffer pointer |
| 667 | * \param end: pointer to end of buffer |
| 668 | * |
| 669 | * Terminates the headers correctly accoring to the protocol in use (h1 / h2) |
| 670 | * and writes the headers. Returns nonzero for error. |
| 671 | */ |
| 672 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 673 | (struct lws *wsi, unsigned char *start, |
| 674 | unsigned char **p, unsigned char *end); |
| 675 | |
| 676 | #define LWS_ILLEGAL_HTTP_CONTENT_LEN ((lws_filepos_t)-1ll) |
| 677 | |
| 678 | /** |
| 679 | * lws_add_http_common_headers() - Helper preparing common http headers |
| 680 | * |
| 681 | * \param wsi: the connection to check |
| 682 | * \param code: an HTTP code like 200, 404 etc (see enum http_status) |
| 683 | * \param content_type: the content type, like "text/html" |
| 684 | * \param content_len: the content length, in bytes |
| 685 | * \param p: pointer to current position in buffer pointer |
| 686 | * \param end: pointer to end of buffer |
| 687 | * |
| 688 | * Adds the initial response code, so should be called first. |
| 689 | * |
| 690 | * Code may additionally take OR'd flags: |
| 691 | * |
| 692 | * LWSAHH_FLAG_NO_SERVER_NAME: don't apply server name header this time |
| 693 | * |
| 694 | * This helper just calls public apis to simplify adding headers that are |
| 695 | * commonly needed. If it doesn't fit your case, or you want to add additional |
| 696 | * headers just call the public apis directly yourself for what you want. |
| 697 | * |
| 698 | * You can miss out the content length header by providing the constant |
| 699 | * LWS_ILLEGAL_HTTP_CONTENT_LEN for the content_len. |
| 700 | * |
| 701 | * It does not call lws_finalize_http_header(), to allow you to add further |
| 702 | * headers after calling this. You will need to call that yourself at the end. |
| 703 | */ |
| 704 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 705 | (struct lws *wsi, unsigned int code, |
| 706 | const char *content_type, lws_filepos_t content_len, |
| 707 | unsigned char **p, unsigned char *end); |
| 708 | |
| 709 | enum { |
| 710 | LWSHUMETH_GET, |
| 711 | LWSHUMETH_POST, |
| 712 | LWSHUMETH_OPTIONS, |
| 713 | LWSHUMETH_PUT, |
| 714 | LWSHUMETH_PATCH, |
| 715 | LWSHUMETH_DELETE, |
| 716 | LWSHUMETH_CONNECT, |
| 717 | LWSHUMETH_HEAD, |
| 718 | LWSHUMETH_COLON_PATH, |
| 719 | }; |
| 720 | |
| 721 | /** |
| 722 | * lws_http_get_uri_and_method() - Get information on method and url |
| 723 | * |
| 724 | * \param wsi: the connection to get information on |
| 725 | * \param puri_ptr: points to pointer to set to url |
| 726 | * \param puri_len: points to int to set to uri length |
| 727 | * |
| 728 | * Returns -1 or method index as one of the LWSHUMETH_ constants |
| 729 | * |
| 730 | * If returns method, *puri_ptr is set to the method's URI string and *puri_len |
| 731 | * to its length |
| 732 | */ |
| 733 | |
| 734 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 735 | lws_http_get_uri_and_method(struct lws *wsi, char **puri_ptr, int *puri_len); |
| 736 | |
| 737 | ///@} |
| 738 | |
| 739 | /*! \defgroup urlendec Urlencode and Urldecode |
| 740 | * \ingroup http |
| 741 | * |
| 742 | * ##HTML chunked Substitution |
| 743 | * |
| 744 | * APIs for receiving chunks of text, replacing a set of variable names via |
| 745 | * a callback, and then prepending and appending HTML chunked encoding |
| 746 | * headers. |
| 747 | */ |
| 748 | //@{ |
| 749 | |
| 750 | /** |
| 751 | * lws_urlencode() - like strncpy but with urlencoding |
| 752 | * |
| 753 | * \param escaped: output buffer |
| 754 | * \param string: input buffer ('/0' terminated) |
| 755 | * \param len: output buffer max length |
| 756 | * |
| 757 | * Because urlencoding expands the output string, it's not |
| 758 | * possible to do it in-place, ie, with escaped == string |
| 759 | */ |
| 760 | LWS_VISIBLE LWS_EXTERN const char * |
| 761 | lws_urlencode(char *escaped, const char *string, int len); |
| 762 | |
| 763 | /* |
| 764 | * URLDECODE 1 / 2 |
| 765 | * |
| 766 | * This simple urldecode only operates until the first '\0' and requires the |
| 767 | * data to exist all at once |
| 768 | */ |
| 769 | /** |
| 770 | * lws_urldecode() - like strncpy but with urldecoding |
| 771 | * |
| 772 | * \param string: output buffer |
| 773 | * \param escaped: input buffer ('\0' terminated) |
| 774 | * \param len: output buffer max length |
| 775 | * |
| 776 | * This is only useful for '\0' terminated strings |
| 777 | * |
| 778 | * Since urldecoding only shrinks the output string, it is possible to |
| 779 | * do it in-place, ie, string == escaped |
| 780 | * |
| 781 | * Returns 0 if completed OK or nonzero for urldecode violation (non-hex chars |
| 782 | * where hex required, etc) |
| 783 | */ |
| 784 | LWS_VISIBLE LWS_EXTERN int |
| 785 | lws_urldecode(char *string, const char *escaped, int len); |
| 786 | ///@} |
| 787 | |
| 788 | /** |
| 789 | * lws_http_date_render_from_unix() - render unixtime as RFC7231 date string |
| 790 | * |
| 791 | * \param buf: Destination string buffer |
| 792 | * \param len: avilable length of dest string buffer in bytes |
| 793 | * \param t: pointer to the time_t to render |
| 794 | * |
| 795 | * Returns 0 if time_t is rendered into the string buffer successfully, else |
| 796 | * nonzero. |
| 797 | */ |
| 798 | LWS_VISIBLE LWS_EXTERN int |
| 799 | lws_http_date_render_from_unix(char *buf, size_t len, const time_t *t); |
| 800 | |
| 801 | /** |
| 802 | * lws_http_date_parse_unix() - parse a RFC7231 date string into unixtime |
| 803 | * |
| 804 | * \param b: Source string buffer |
| 805 | * \param len: avilable length of source string buffer in bytes |
| 806 | * \param t: pointer to the destination time_t to set |
| 807 | * |
| 808 | * Returns 0 if string buffer parsed as RFC7231 time successfully, and |
| 809 | * *t set to the parsed unixtime, else return nonzero. |
| 810 | */ |
| 811 | LWS_VISIBLE LWS_EXTERN int |
| 812 | lws_http_date_parse_unix(const char *b, size_t len, time_t *t); |
| 813 | |
| 814 | /** |
| 815 | * lws_http_check_retry_after() - increase a timeout if retry-after present |
| 816 | * |
| 817 | * \param wsi: http stream this relates to |
| 818 | * \param us_interval_in_out: default us retry interval on entry may be updated |
| 819 | * |
| 820 | * This function may extend the incoming retry interval if the server has |
| 821 | * requested that using retry-after: header. It won't reduce the incoming |
| 822 | * retry interval, only leave it alone or increase it. |
| 823 | * |
| 824 | * *us_interval_in_out should be set to a default retry interval on entry, if |
| 825 | * the wsi has a retry-after time or interval that resolves to an interval |
| 826 | * longer than the entry *us_interval_in_out, that will be updated to the longer |
| 827 | * interval and return 0. |
| 828 | * |
| 829 | * If no usable retry-after or the time is now or in the past, |
| 830 | * *us_interval_in_out is left alone and the function returns nonzero. |
| 831 | */ |
| 832 | LWS_VISIBLE LWS_EXTERN int |
| 833 | lws_http_check_retry_after(struct lws *wsi, lws_usec_t *us_interval_in_out); |
| 834 | |
| 835 | /** |
| 836 | * lws_return_http_status() - Return simple http status |
| 837 | * \param wsi: Websocket instance (available from user callback) |
| 838 | * \param code: Status index, eg, 404 |
| 839 | * \param html_body: User-readable HTML description < 1KB, or NULL |
| 840 | * |
| 841 | * Helper to report HTTP errors back to the client cleanly and |
| 842 | * consistently |
| 843 | */ |
| 844 | LWS_VISIBLE LWS_EXTERN int |
| 845 | lws_return_http_status(struct lws *wsi, unsigned int code, |
| 846 | const char *html_body); |
| 847 | |
| 848 | /** |
| 849 | * lws_http_redirect() - write http redirect out on wsi |
| 850 | * |
| 851 | * \param wsi: websocket connection |
| 852 | * \param code: HTTP response code (eg, 301) |
| 853 | * \param loc: where to redirect to |
| 854 | * \param len: length of loc |
| 855 | * \param p: pointer current position in buffer (updated as we write) |
| 856 | * \param end: pointer to end of buffer |
| 857 | * |
| 858 | * Returns amount written, or < 0 indicating fatal write failure. |
| 859 | */ |
| 860 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 861 | lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len, |
| 862 | unsigned char **p, unsigned char *end); |
| 863 | |
| 864 | /** |
| 865 | * lws_http_transaction_completed() - wait for new http transaction or close |
| 866 | * \param wsi: websocket connection |
| 867 | * |
| 868 | * Returns nonzero if the HTTP connection must close now |
| 869 | * Returns 0 and resets connection to wait for new HTTP header / |
| 870 | * transaction if possible |
| 871 | */ |
| 872 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| 873 | lws_http_transaction_completed(struct lws *wsi); |
| 874 | |
| 875 | /** |
| 876 | * lws_http_headers_detach() - drop the associated headers storage and allow |
| 877 | * it to be reused by another connection |
| 878 | * \param wsi: http connection |
| 879 | * |
| 880 | * If the wsi has an ah headers struct attached, detach it. |
| 881 | */ |
| 882 | LWS_VISIBLE LWS_EXTERN int |
| 883 | (struct lws *wsi); |
| 884 | |
| 885 | /** |
| 886 | * lws_http_mark_sse() - called to indicate this http stream is now doing SSE |
| 887 | * |
| 888 | * \param wsi: http connection |
| 889 | * |
| 890 | * Cancel any timeout on the wsi, and for h2, mark the network connection as |
| 891 | * containing an immortal stream for the duration the SSE stream is open. |
| 892 | */ |
| 893 | LWS_VISIBLE LWS_EXTERN int |
| 894 | lws_http_mark_sse(struct lws *wsi); |
| 895 | |
| 896 | /** |
| 897 | * lws_h2_client_stream_long_poll_rxonly() - h2 stream to immortal read-only |
| 898 | * |
| 899 | * \param wsi: h2 stream client wsi |
| 900 | * |
| 901 | * Send END_STREAM-flagged zero-length DATA frame to set client stream wsi into |
| 902 | * half-closed (local) and remote into half-closed (remote). Set the client |
| 903 | * stream wsi to be immortal (not subject to timeouts). |
| 904 | * |
| 905 | * Used if the remote server supports immortal long poll to put the stream into |
| 906 | * a read-only state where it can wait as long as needed for rx. |
| 907 | * |
| 908 | * Returns 0 if the process (which happens asynchronously) started or non-zero |
| 909 | * if it wasn't an h2 stream. |
| 910 | */ |
| 911 | LWS_VISIBLE LWS_EXTERN int |
| 912 | lws_h2_client_stream_long_poll_rxonly(struct lws *wsi); |
| 913 | |
| 914 | /** |
| 915 | * lws_http_compression_apply() - apply an http compression transform |
| 916 | * |
| 917 | * \param wsi: the wsi to apply the compression transform to |
| 918 | * \param name: NULL, or the name of the compression transform, eg, "deflate" |
| 919 | * \param p: pointer to pointer to headers buffer |
| 920 | * \param end: pointer to end of headers buffer |
| 921 | * \param decomp: 0 = add compressor to wsi, 1 = add decompressor |
| 922 | * |
| 923 | * This allows transparent compression of dynamically generated HTTP. The |
| 924 | * requested compression (eg, "deflate") is only applied if the client headers |
| 925 | * indicated it was supported (and it has support in lws), otherwise it's a NOP. |
| 926 | * |
| 927 | * If the requested compression method is NULL, then the supported compression |
| 928 | * formats are tried, and for non-decompression (server) mode the first that's |
| 929 | * found on the client's accept-encoding header is chosen. |
| 930 | * |
| 931 | * NOTE: the compression transform, same as h2 support, relies on the user |
| 932 | * code using LWS_WRITE_HTTP and then LWS_WRITE_HTTP_FINAL on the last part |
| 933 | * written. The internal lws fileserving code already does this. |
| 934 | * |
| 935 | * If the library was built without the cmake option |
| 936 | * LWS_WITH_HTTP_STREAM_COMPRESSION set, then a NOP is provided for this api, |
| 937 | * allowing user code to build either way and use compression if available. |
| 938 | */ |
| 939 | LWS_VISIBLE LWS_EXTERN int |
| 940 | lws_http_compression_apply(struct lws *wsi, const char *name, |
| 941 | unsigned char **p, unsigned char *end, char decomp); |
| 942 | |
| 943 | /** |
| 944 | * lws_http_is_redirected_to_get() - true if redirected to GET |
| 945 | * |
| 946 | * \param wsi: the wsi to check |
| 947 | * |
| 948 | * Check if the wsi is currently in GET mode, after, eg, doing a POST and |
| 949 | * receiving a 303. |
| 950 | */ |
| 951 | LWS_VISIBLE LWS_EXTERN int |
| 952 | lws_http_is_redirected_to_get(struct lws *wsi); |
| 953 | |
| 954 | /** |
| 955 | * lws_http_cookie_get() - return copy of named cookie if present |
| 956 | * |
| 957 | * \param wsi: the wsi to check |
| 958 | * \param name: name of the cookie |
| 959 | * \param buf: buffer to store the cookie contents into |
| 960 | * \param max_len: on entry, maximum length of buf... on exit, used len of buf |
| 961 | * |
| 962 | * If no cookie header, or no cookie of the requested name, or the value is |
| 963 | * larger than can fit in buf, returns nonzero. |
| 964 | * |
| 965 | * If the cookie is found, copies its value into buf with a terminating NUL, |
| 966 | * sets *max_len to the used length, and returns 0. |
| 967 | * |
| 968 | * This handles the parsing of the possibly multi-cookie header string and |
| 969 | * terminating the requested cookie at the next ; if present. |
| 970 | */ |
| 971 | LWS_VISIBLE LWS_EXTERN int |
| 972 | lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, size_t *max); |
| 973 | |
| 974 | /** |
| 975 | * lws_http_client_http_error() - determine if the response code indicates an error |
| 976 | * |
| 977 | * \param code: the response code to test |
| 978 | * |
| 979 | * Returns nonzero if the code indicates an error, else zero if reflects a |
| 980 | * non-error condition |
| 981 | */ |
| 982 | #define lws_http_client_http_resp_is_error(code) (!(code < 400)) |
| 983 | |
| 984 | /** |
| 985 | * lws_h2_update_peer_txcredit() - manually update stream peer tx credit |
| 986 | * |
| 987 | * \param wsi: the h2 child stream whose peer credit to change |
| 988 | * \param sid: the stream ID, or LWS_H2_STREAM_SID for the wsi stream ID |
| 989 | * \param bump: signed change to confer upon peer tx credit for sid |
| 990 | * |
| 991 | * In conjunction with LCCSCF_H2_MANUAL_RXFLOW flag, allows the user code to |
| 992 | * selectively starve the remote peer of the ability to send us data on a client |
| 993 | * connection. |
| 994 | * |
| 995 | * Normally lws sends an initial window size for the peer to send to it of 0, |
| 996 | * but during the header phase it sends a WINDOW_UPDATE to increase the amount |
| 997 | * available. LCCSCF_H2_MANUAL_RXFLOW restricts this initial increase in tx |
| 998 | * credit for the stream, before it has been asked to send us anything, to the |
| 999 | * amount specified in the client info .manual_initial_tx_credit member, and |
| 1000 | * this api can be called to send the other side permission to send us up to |
| 1001 | * \p bump additional bytes. |
| 1002 | * |
| 1003 | * The nwsi tx credit is updated automatically for exactly what was sent to us |
| 1004 | * on a stream with LCCSCF_H2_MANUAL_RXFLOW flag, but the stream's own tx credit |
| 1005 | * must be handled manually by user code via this api. |
| 1006 | * |
| 1007 | * Returns 0 for success or nonzero for failure. |
| 1008 | */ |
| 1009 | #define LWS_H2_STREAM_SID -1 |
| 1010 | LWS_VISIBLE LWS_EXTERN int |
| 1011 | lws_h2_update_peer_txcredit(struct lws *wsi, unsigned int sid, int bump); |
| 1012 | |
| 1013 | |
| 1014 | /** |
| 1015 | * lws_h2_get_peer_txcredit_estimate() - return peer tx credit estimate |
| 1016 | * |
| 1017 | * \param wsi: the h2 child stream whose peer credit estimate to return |
| 1018 | * |
| 1019 | * Returns the estimated amount of tx credit at the peer, in other words the |
| 1020 | * number of bytes the peer is authorized to send to us. |
| 1021 | * |
| 1022 | * It's an 'estimate' because we don't know how much is already in flight |
| 1023 | * towards us and actually already used. |
| 1024 | */ |
| 1025 | LWS_VISIBLE LWS_EXTERN int |
| 1026 | lws_h2_get_peer_txcredit_estimate(struct lws *wsi); |
| 1027 | |
| 1028 | ///@} |
| 1029 | |
| 1030 | |