| /* |
| * libwebsockets - small server side websockets and web server implementation |
| * |
| * Copyright (C) 2010-2018 Andy Green <andy@warmcat.com> |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation: |
| * version 2.1 of the License. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
| * MA 02110-1301 USA |
| * |
| * included from libwebsockets.h |
| */ |
| |
| /* minimal space for typical headers and CSP stuff */ |
| |
| #define LWS_RECOMMENDED_MIN_HEADER_SPACE 2048 |
| |
| /*! \defgroup http HTTP |
| |
| Modules related to handling HTTP |
| */ |
| //@{ |
| |
| /*! \defgroup httpft HTTP File transfer |
| * \ingroup http |
| |
| APIs for sending local files in response to HTTP requests |
| */ |
| //@{ |
| |
| /** |
| * lws_get_mimetype() - Determine mimetype to use from filename |
| * |
| * \param file: filename |
| * \param m: NULL, or mount context |
| * |
| * This uses a canned list of known filetypes first, if no match and m is |
| * non-NULL, then tries a list of per-mount file suffix to mimtype mappings. |
| * |
| * Returns either NULL or a pointer to the mimetype matching the file. |
| */ |
| LWS_VISIBLE LWS_EXTERN const char * |
| lws_get_mimetype(const char *file, const struct lws_http_mount *m); |
| |
| /** |
| * lws_serve_http_file() - Send a file back to the client using http |
| * \param wsi: Websocket instance (available from user callback) |
| * \param file: The file to issue over http |
| * \param content_type: The http content type, eg, text/html |
| * \param other_headers: NULL or pointer to header string |
| * \param other_headers_len: length of the other headers if non-NULL |
| * |
| * This function is intended to be called from the callback in response |
| * to http requests from the client. It allows the callback to issue |
| * local files down the http link in a single step. |
| * |
| * Returning <0 indicates error and the wsi should be closed. Returning |
| * >0 indicates the file was completely sent and |
| * lws_http_transaction_completed() called on the wsi (and close if != 0) |
| * ==0 indicates the file transfer is started and needs more service later, |
| * the wsi should be left alone. |
| */ |
| LWS_VISIBLE LWS_EXTERN int |
| lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type, |
| const char *other_headers, int other_headers_len); |
| |
| LWS_VISIBLE LWS_EXTERN int |
| lws_serve_http_file_fragment(struct lws *wsi); |
| //@} |
| |
| |
| enum http_status { |
| HTTP_STATUS_CONTINUE = 100, |
| |
| HTTP_STATUS_OK = 200, |
| HTTP_STATUS_NO_CONTENT = 204, |
| HTTP_STATUS_PARTIAL_CONTENT = 206, |
| |
| HTTP_STATUS_MOVED_PERMANENTLY = 301, |
| HTTP_STATUS_FOUND = 302, |
| HTTP_STATUS_SEE_OTHER = 303, |
| HTTP_STATUS_NOT_MODIFIED = 304, |
| |
| HTTP_STATUS_BAD_REQUEST = 400, |
| HTTP_STATUS_UNAUTHORIZED, |
| HTTP_STATUS_PAYMENT_REQUIRED, |
| HTTP_STATUS_FORBIDDEN, |
| HTTP_STATUS_NOT_FOUND, |
| HTTP_STATUS_METHOD_NOT_ALLOWED, |
| HTTP_STATUS_NOT_ACCEPTABLE, |
| HTTP_STATUS_PROXY_AUTH_REQUIRED, |
| HTTP_STATUS_REQUEST_TIMEOUT, |
| HTTP_STATUS_CONFLICT, |
| HTTP_STATUS_GONE, |
| HTTP_STATUS_LENGTH_REQUIRED, |
| HTTP_STATUS_PRECONDITION_FAILED, |
| HTTP_STATUS_REQ_ENTITY_TOO_LARGE, |
| HTTP_STATUS_REQ_URI_TOO_LONG, |
| HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE, |
| HTTP_STATUS_REQ_RANGE_NOT_SATISFIABLE, |
| HTTP_STATUS_EXPECTATION_FAILED, |
| |
| HTTP_STATUS_INTERNAL_SERVER_ERROR = 500, |
| HTTP_STATUS_NOT_IMPLEMENTED, |
| HTTP_STATUS_BAD_GATEWAY, |
| HTTP_STATUS_SERVICE_UNAVAILABLE, |
| HTTP_STATUS_GATEWAY_TIMEOUT, |
| HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED, |
| }; |
| /*! \defgroup html-chunked-substitution HTML Chunked Substitution |
| * \ingroup http |
| * |
| * ##HTML chunked Substitution |
| * |
| * APIs for receiving chunks of text, replacing a set of variable names via |
| * a callback, and then prepending and appending HTML chunked encoding |
| * headers. |
| */ |
| //@{ |
| |
| struct lws_process_html_args { |
| char *p; /**< pointer to the buffer containing the data */ |
| int len; /**< length of the original data at p */ |
| int max_len; /**< maximum length we can grow the data to */ |
| int final; /**< set if this is the last chunk of the file */ |
| int chunked; /**< 0 == unchunked, 1 == produce chunk headers |
| (incompatible with HTTP/2) */ |
| }; |
| |
| typedef const char *(*lws_process_html_state_cb)(void *data, int index); |
| |
| struct lws_process_html_state { |
| char *start; /**< pointer to start of match */ |
| char swallow[16]; /**< matched character buffer */ |
| int pos; /**< position in match */ |
| void *data; /**< opaque pointer */ |
| const char * const *vars; /**< list of variable names */ |
| int count_vars; /**< count of variable names */ |
| |
| lws_process_html_state_cb replace; |
| /**< called on match to perform substitution */ |
| }; |
| |
| /*! lws_chunked_html_process() - generic chunked substitution |
| * \param args: buffer to process using chunked encoding |
| * \param s: current processing state |
| */ |
| LWS_VISIBLE LWS_EXTERN int |
| lws_chunked_html_process(struct lws_process_html_args *args, |
| struct lws_process_html_state *s); |
| //@} |
| |
| /** \defgroup HTTP-headers-read HTTP headers: read |
| * \ingroup http |
| * |
| * ##HTTP header releated functions |
| * |
| * In lws the client http headers are temporarily stored in a pool, only for the |
| * duration of the http part of the handshake. It's because in most cases, |
| * the header content is ignored for the whole rest of the connection lifetime |
| * and would then just be taking up space needlessly. |
| * |
| * During LWS_CALLBACK_HTTP when the URI path is delivered is the last time |
| * the http headers are still allocated, you can use these apis then to |
| * look at and copy out interesting header content (cookies, etc) |
| * |
| * Notice that the header total length reported does not include a terminating |
| * '\0', however you must allocate for it when using the _copy apis. So the |
| * length reported for a header containing "123" is 3, but you must provide |
| * a buffer of length 4 so that "123\0" may be copied into it, or the copy |
| * will fail with a nonzero return code. |
| * |
| * In the special case of URL arguments, like ?x=1&y=2, the arguments are |
| * stored in a token named for the method, eg, WSI_TOKEN_GET_URI if it |
| * was a GET or WSI_TOKEN_POST_URI if POST. You can check the total |
| * length to confirm the method. |
| * |
| * For URL arguments, each argument is stored urldecoded in a "fragment", so |
| * you can use the fragment-aware api lws_hdr_copy_fragment() to access each |
| * argument in turn: the fragments contain urldecoded strings like x=1 or y=2. |
| * |
| * As a convenience, lws has an api that will find the fragment with a |
| * given name= part, lws_get_urlarg_by_name(). |
| */ |
| ///@{ |
| |
| /** struct lws_tokens |
| * you need these to look at headers that have been parsed if using the |
| * LWS_CALLBACK_FILTER_CONNECTION callback. If a header from the enum |
| * list below is absent, .token = NULL and len = 0. Otherwise .token |
| * points to .len chars containing that header content. |
| */ |
| struct lws_tokens { |
| char *token; /**< pointer to start of the token */ |
| int len; /**< length of the token's value */ |
| }; |
| |
| /* enum lws_token_indexes |
| * these have to be kept in sync with lextable.h / minilex.c |
| * |
| * NOTE: These public enums are part of the abi. If you want to add one, |
| * add it at where specified so existing users are unaffected. |
| */ |
| enum lws_token_indexes { |
| WSI_TOKEN_GET_URI = 0, |
| WSI_TOKEN_POST_URI = 1, |
| WSI_TOKEN_OPTIONS_URI = 2, |
| WSI_TOKEN_HOST = 3, |
| WSI_TOKEN_CONNECTION = 4, |
| WSI_TOKEN_UPGRADE = 5, |
| WSI_TOKEN_ORIGIN = 6, |
| WSI_TOKEN_DRAFT = 7, |
| WSI_TOKEN_CHALLENGE = 8, |
| WSI_TOKEN_EXTENSIONS = 9, |
| WSI_TOKEN_KEY1 = 10, |
| WSI_TOKEN_KEY2 = 11, |
| WSI_TOKEN_PROTOCOL = 12, |
| WSI_TOKEN_ACCEPT = 13, |
| WSI_TOKEN_NONCE = 14, |
| WSI_TOKEN_HTTP = 15, |
| WSI_TOKEN_HTTP2_SETTINGS = 16, |
| WSI_TOKEN_HTTP_ACCEPT = 17, |
| WSI_TOKEN_HTTP_AC_REQUEST_HEADERS = 18, |
| WSI_TOKEN_HTTP_IF_MODIFIED_SINCE = 19, |
| WSI_TOKEN_HTTP_IF_NONE_MATCH = 20, |
| WSI_TOKEN_HTTP_ACCEPT_ENCODING = 21, |
| WSI_TOKEN_HTTP_ACCEPT_LANGUAGE = 22, |
| WSI_TOKEN_HTTP_PRAGMA = 23, |
| WSI_TOKEN_HTTP_CACHE_CONTROL = 24, |
| WSI_TOKEN_HTTP_AUTHORIZATION = 25, |
| WSI_TOKEN_HTTP_COOKIE = 26, |
| WSI_TOKEN_HTTP_CONTENT_LENGTH = 27, |
| WSI_TOKEN_HTTP_CONTENT_TYPE = 28, |
| WSI_TOKEN_HTTP_DATE = 29, |
| WSI_TOKEN_HTTP_RANGE = 30, |
| WSI_TOKEN_HTTP_REFERER = 31, |
| WSI_TOKEN_KEY = 32, |
| WSI_TOKEN_VERSION = 33, |
| WSI_TOKEN_SWORIGIN = 34, |
| |
| WSI_TOKEN_HTTP_COLON_AUTHORITY = 35, |
| WSI_TOKEN_HTTP_COLON_METHOD = 36, |
| WSI_TOKEN_HTTP_COLON_PATH = 37, |
| WSI_TOKEN_HTTP_COLON_SCHEME = 38, |
| WSI_TOKEN_HTTP_COLON_STATUS = 39, |
| |
| WSI_TOKEN_HTTP_ACCEPT_CHARSET = 40, |
| WSI_TOKEN_HTTP_ACCEPT_RANGES = 41, |
| WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN = 42, |
| WSI_TOKEN_HTTP_AGE = 43, |
| WSI_TOKEN_HTTP_ALLOW = 44, |
| WSI_TOKEN_HTTP_CONTENT_DISPOSITION = 45, |
| WSI_TOKEN_HTTP_CONTENT_ENCODING = 46, |
| WSI_TOKEN_HTTP_CONTENT_LANGUAGE = 47, |
| WSI_TOKEN_HTTP_CONTENT_LOCATION = 48, |
| WSI_TOKEN_HTTP_CONTENT_RANGE = 49, |
| WSI_TOKEN_HTTP_ETAG = 50, |
| WSI_TOKEN_HTTP_EXPECT = 51, |
| WSI_TOKEN_HTTP_EXPIRES = 52, |
| WSI_TOKEN_HTTP_FROM = 53, |
| WSI_TOKEN_HTTP_IF_MATCH = 54, |
| WSI_TOKEN_HTTP_IF_RANGE = 55, |
| WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE = 56, |
| WSI_TOKEN_HTTP_LAST_MODIFIED = 57, |
| WSI_TOKEN_HTTP_LINK = 58, |
| WSI_TOKEN_HTTP_LOCATION = 59, |
| WSI_TOKEN_HTTP_MAX_FORWARDS = 60, |
| WSI_TOKEN_HTTP_PROXY_AUTHENTICATE = 61, |
| WSI_TOKEN_HTTP_PROXY_AUTHORIZATION = 62, |
| WSI_TOKEN_HTTP_REFRESH = 63, |
| WSI_TOKEN_HTTP_RETRY_AFTER = 64, |
| WSI_TOKEN_HTTP_SERVER = 65, |
| WSI_TOKEN_HTTP_SET_COOKIE = 66, |
| WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY = 67, |
| WSI_TOKEN_HTTP_TRANSFER_ENCODING = 68, |
| WSI_TOKEN_HTTP_USER_AGENT = 69, |
| WSI_TOKEN_HTTP_VARY = 70, |
| WSI_TOKEN_HTTP_VIA = 71, |
| WSI_TOKEN_HTTP_WWW_AUTHENTICATE = 72, |
| |
| WSI_TOKEN_PATCH_URI = 73, |
| WSI_TOKEN_PUT_URI = 74, |
| WSI_TOKEN_DELETE_URI = 75, |
| |
| WSI_TOKEN_HTTP_URI_ARGS = 76, |
| WSI_TOKEN_PROXY = 77, |
| WSI_TOKEN_HTTP_X_REAL_IP = 78, |
| WSI_TOKEN_HTTP1_0 = 79, |
| WSI_TOKEN_X_FORWARDED_FOR = 80, |
| WSI_TOKEN_CONNECT = 81, |
| WSI_TOKEN_HEAD_URI = 82, |
| WSI_TOKEN_TE = 83, |
| WSI_TOKEN_REPLAY_NONCE = 84, |
| WSI_TOKEN_COLON_PROTOCOL = 85, |
| WSI_TOKEN_X_AUTH_TOKEN = 86, |
| |
| /****** add new things just above ---^ ******/ |
| |
| /* use token storage to stash these internally, not for |
| * user use */ |
| |
| _WSI_TOKEN_CLIENT_SENT_PROTOCOLS, |
| _WSI_TOKEN_CLIENT_PEER_ADDRESS, |
| _WSI_TOKEN_CLIENT_URI, |
| _WSI_TOKEN_CLIENT_HOST, |
| _WSI_TOKEN_CLIENT_ORIGIN, |
| _WSI_TOKEN_CLIENT_METHOD, |
| _WSI_TOKEN_CLIENT_IFACE, |
| _WSI_TOKEN_CLIENT_ALPN, |
| |
| /* always last real token index*/ |
| WSI_TOKEN_COUNT, |
| |
| /* parser state additions, no storage associated */ |
| WSI_TOKEN_NAME_PART, |
| #if defined(LWS_WITH_CUSTOM_HEADERS) |
| WSI_TOKEN_UNKNOWN_VALUE_PART, |
| #endif |
| WSI_TOKEN_SKIPPING, |
| WSI_TOKEN_SKIPPING_SAW_CR, |
| WSI_PARSING_COMPLETE, |
| WSI_INIT_TOKEN_MUXURL, |
| }; |
| |
| struct lws_token_limits { |
| unsigned short token_limit[WSI_TOKEN_COUNT]; /**< max chars for this token */ |
| }; |
| |
| /** |
| * lws_token_to_string() - returns a textual representation of a hdr token index |
| * |
| * \param token: token index |
| */ |
| LWS_VISIBLE LWS_EXTERN const unsigned char * |
| lws_token_to_string(enum lws_token_indexes token); |
| |
| /** |
| * lws_hdr_total_length: report length of all fragments of a header totalled up |
| * The returned length does not include the space for a |
| * terminating '\0' |
| * |
| * \param wsi: websocket connection |
| * \param h: which header index we are interested in |
| */ |
| LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h); |
| |
| /** |
| * lws_hdr_fragment_length: report length of a single fragment of a header |
| * The returned length does not include the space for a |
| * terminating '\0' |
| * |
| * \param wsi: websocket connection |
| * \param h: which header index we are interested in |
| * \param frag_idx: which fragment of h we want to get the length of |
| */ |
| LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, |
| int frag_idx); |
| |
| /** |
| * lws_hdr_copy() - copy all fragments of the given header to a buffer |
| * The buffer length len must include space for an additional |
| * terminating '\0', or it will fail returning -1. |
| * |
| * \param wsi: websocket connection |
| * \param dest: destination buffer |
| * \param len: length of destination buffer |
| * \param h: which header index we are interested in |
| * |
| * copies the whole, aggregated header, even if it was delivered in |
| * several actual headers piece by piece. Returns -1 or length of the whole |
| * header. |
| */ |
| LWS_VISIBLE LWS_EXTERN int |
| lws_hdr_copy(struct lws *wsi, char *dest, int len, enum lws_token_indexes h); |
| |
| /** |
| * lws_hdr_copy_fragment() - copy a single fragment of the given header to a buffer |
| * The buffer length len must include space for an additional |
| * terminating '\0', or it will fail returning -1. |
| * If the requested fragment index is not present, it fails |
| * returning -1. |
| * |
| * \param wsi: websocket connection |
| * \param dest: destination buffer |
| * \param len: length of destination buffer |
| * \param h: which header index we are interested in |
| * \param frag_idx: which fragment of h we want to copy |
| * |
| * Normally this is only useful |
| * to parse URI arguments like ?x=1&y=2, token index WSI_TOKEN_HTTP_URI_ARGS |
| * fragment 0 will contain "x=1" and fragment 1 "y=2" |
| */ |
| LWS_VISIBLE LWS_EXTERN int |
| lws_hdr_copy_fragment(struct lws *wsi, char *dest, int len, |
| enum lws_token_indexes h, int frag_idx); |
| |
| /** |
| * lws_hdr_custom_length() - return length of a custom header |
| * |
| * \param wsi: websocket connection |
| * \param name: header string (including terminating :) |
| * \param nlen: length of name |
| * |
| * Lws knows about 100 common http headers, and parses them into indexes when |
| * it recognizes them. When it meets a header that it doesn't know, it stores |
| * the name and value directly, and you can look them up using |
| * lws_hdr_custom_length() and lws_hdr_custom_copy(). |
| * |
| * This api returns -1, or the length of the value part of the header if it |
| * exists. Lws must be built with LWS_WITH_CUSTOM_HEADERS (on by default) to |
| * use this api. |
| */ |
| LWS_VISIBLE LWS_EXTERN int |
| lws_hdr_custom_length(struct lws *wsi, const char *name, int nlen); |
| |
| /** |
| * lws_hdr_custom_copy() - copy value part of a custom header |
| * |
| * \param wsi: websocket connection |
| * \param dst: pointer to buffer to receive the copy |
| * \param len: number of bytes available at dst |
| * \param name: header string (including terminating :) |
| * \param nlen: length of name |
| * |
| * Lws knows about 100 common http headers, and parses them into indexes when |
| * it recognizes them. When it meets a header that it doesn't know, it stores |
| * the name and value directly, and you can look them up using |
| * lws_hdr_custom_length() and lws_hdr_custom_copy(). |
| * |
| * This api returns -1, or the length of the string it copied into dst if it |
| * was big enough to contain both the string and an extra terminating NUL. Lws |
| * must be built with LWS_WITH_CUSTOM_HEADERS (on by default) to use this api. |
| */ |
| LWS_VISIBLE LWS_EXTERN int |
| lws_hdr_custom_copy(struct lws *wsi, char *dst, int len, const char *name, |
| int nlen); |
| |
| /** |
| * lws_get_urlarg_by_name() - return pointer to arg value if present |
| * \param wsi: the connection to check |
| * \param name: the arg name, like "token=" |
| * \param buf: the buffer to receive the urlarg (including the name= part) |
| * \param len: the length of the buffer to receive the urlarg |
| * |
| * Returns NULL if not found or a pointer inside buf to just after the |
| * name= part. |
| */ |
| LWS_VISIBLE LWS_EXTERN const char * |
| lws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len); |
| ///@} |
| |
| /*! \defgroup HTTP-headers-create HTTP headers: create |
| * |
| * ## HTTP headers: Create |
| * |
| * These apis allow you to create HTTP response headers in a way compatible with |
| * both HTTP/1.x and HTTP/2. |
| * |
| * They each append to a buffer taking care about the buffer end, which is |
| * passed in as a pointer. When data is written to the buffer, the current |
| * position p is updated accordingly. |
| * |
| * All of these apis are LWS_WARN_UNUSED_RESULT as they can run out of space |
| * and fail with nonzero return. |
| */ |
| ///@{ |
| |
| #define LWSAHH_CODE_MASK ((1 << 16) - 1) |
| #define LWSAHH_FLAG_NO_SERVER_NAME (1 << 30) |
| |
| /** |
| * lws_add_http_header_status() - add the HTTP response status code |
| * |
| * \param wsi: the connection to check |
| * \param code: an HTTP code like 200, 404 etc (see enum http_status) |
| * \param p: pointer to current position in buffer pointer |
| * \param end: pointer to end of buffer |
| * |
| * Adds the initial response code, so should be called first. |
| * |
| * Code may additionally take OR'd flags: |
| * |
| * LWSAHH_FLAG_NO_SERVER_NAME: don't apply server name header this time |
| */ |
| LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| lws_add_http_header_status(struct lws *wsi, |
| unsigned int code, unsigned char **p, |
| unsigned char *end); |
| /** |
| * lws_add_http_header_by_name() - append named header and value |
| * |
| * \param wsi: the connection to check |
| * \param name: the hdr name, like "my-header" |
| * \param value: the value after the = for this header |
| * \param length: the length of the value |
| * \param p: pointer to current position in buffer pointer |
| * \param end: pointer to end of buffer |
| * |
| * Appends name: value to the headers |
| */ |
| LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| lws_add_http_header_by_name(struct lws *wsi, const unsigned char *name, |
| const unsigned char *value, int length, |
| unsigned char **p, unsigned char *end); |
| /** |
| * lws_add_http_header_by_token() - append given header and value |
| * |
| * \param wsi: the connection to check |
| * \param token: the token index for the hdr |
| * \param value: the value after the = for this header |
| * \param length: the length of the value |
| * \param p: pointer to current position in buffer pointer |
| * \param end: pointer to end of buffer |
| * |
| * Appends name=value to the headers, but is able to take advantage of better |
| * HTTP/2 coding mechanisms where possible. |
| */ |
| LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| lws_add_http_header_by_token(struct lws *wsi, enum lws_token_indexes token, |
| const unsigned char *value, int length, |
| unsigned char **p, unsigned char *end); |
| /** |
| * lws_add_http_header_content_length() - append content-length helper |
| * |
| * \param wsi: the connection to check |
| * \param content_length: the content length to use |
| * \param p: pointer to current position in buffer pointer |
| * \param end: pointer to end of buffer |
| * |
| * Appends content-length: content_length to the headers |
| */ |
| LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| lws_add_http_header_content_length(struct lws *wsi, |
| lws_filepos_t content_length, |
| unsigned char **p, unsigned char *end); |
| /** |
| * lws_finalize_http_header() - terminate header block |
| * |
| * \param wsi: the connection to check |
| * \param p: pointer to current position in buffer pointer |
| * \param end: pointer to end of buffer |
| * |
| * Indicates no more headers will be added |
| */ |
| LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| lws_finalize_http_header(struct lws *wsi, unsigned char **p, |
| unsigned char *end); |
| |
| /** |
| * lws_finalize_write_http_header() - Helper finializing and writing http headers |
| * |
| * \param wsi: the connection to check |
| * \param start: pointer to the start of headers in the buffer, eg &buf[LWS_PRE] |
| * \param p: pointer to current position in buffer pointer |
| * \param end: pointer to end of buffer |
| * |
| * Terminates the headers correctly accoring to the protocol in use (h1 / h2) |
| * and writes the headers. Returns nonzero for error. |
| */ |
| LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| lws_finalize_write_http_header(struct lws *wsi, unsigned char *start, |
| unsigned char **p, unsigned char *end); |
| |
| #define LWS_ILLEGAL_HTTP_CONTENT_LEN ((lws_filepos_t)-1ll) |
| |
| /** |
| * lws_add_http_common_headers() - Helper preparing common http headers |
| * |
| * \param wsi: the connection to check |
| * \param code: an HTTP code like 200, 404 etc (see enum http_status) |
| * \param content_type: the content type, like "text/html" |
| * \param content_len: the content length, in bytes |
| * \param p: pointer to current position in buffer pointer |
| * \param end: pointer to end of buffer |
| * |
| * Adds the initial response code, so should be called first. |
| * |
| * Code may additionally take OR'd flags: |
| * |
| * LWSAHH_FLAG_NO_SERVER_NAME: don't apply server name header this time |
| * |
| * This helper just calls public apis to simplify adding headers that are |
| * commonly needed. If it doesn't fit your case, or you want to add additional |
| * headers just call the public apis directly yourself for what you want. |
| * |
| * You can miss out the content length header by providing the constant |
| * LWS_ILLEGAL_HTTP_CONTENT_LEN for the content_len. |
| * |
| * It does not call lws_finalize_http_header(), to allow you to add further |
| * headers after calling this. You will need to call that yourself at the end. |
| */ |
| LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| lws_add_http_common_headers(struct lws *wsi, unsigned int code, |
| const char *content_type, lws_filepos_t content_len, |
| unsigned char **p, unsigned char *end); |
| |
| ///@} |
| |
| /*! \defgroup urlendec Urlencode and Urldecode |
| * \ingroup http |
| * |
| * ##HTML chunked Substitution |
| * |
| * APIs for receiving chunks of text, replacing a set of variable names via |
| * a callback, and then prepending and appending HTML chunked encoding |
| * headers. |
| */ |
| //@{ |
| |
| /** |
| * lws_urlencode() - like strncpy but with urlencoding |
| * |
| * \param escaped: output buffer |
| * \param string: input buffer ('/0' terminated) |
| * \param len: output buffer max length |
| * |
| * Because urlencoding expands the output string, it's not |
| * possible to do it in-place, ie, with escaped == string |
| */ |
| LWS_VISIBLE LWS_EXTERN const char * |
| lws_urlencode(char *escaped, const char *string, int len); |
| |
| /* |
| * URLDECODE 1 / 2 |
| * |
| * This simple urldecode only operates until the first '\0' and requires the |
| * data to exist all at once |
| */ |
| /** |
| * lws_urldecode() - like strncpy but with urldecoding |
| * |
| * \param string: output buffer |
| * \param escaped: input buffer ('\0' terminated) |
| * \param len: output buffer max length |
| * |
| * This is only useful for '\0' terminated strings |
| * |
| * Since urldecoding only shrinks the output string, it is possible to |
| * do it in-place, ie, string == escaped |
| * |
| * Returns 0 if completed OK or nonzero for urldecode violation (non-hex chars |
| * where hex required, etc) |
| */ |
| LWS_VISIBLE LWS_EXTERN int |
| lws_urldecode(char *string, const char *escaped, int len); |
| ///@} |
| |
| /** |
| * lws_return_http_status() - Return simple http status |
| * \param wsi: Websocket instance (available from user callback) |
| * \param code: Status index, eg, 404 |
| * \param html_body: User-readable HTML description < 1KB, or NULL |
| * |
| * Helper to report HTTP errors back to the client cleanly and |
| * consistently |
| */ |
| LWS_VISIBLE LWS_EXTERN int |
| lws_return_http_status(struct lws *wsi, unsigned int code, |
| const char *html_body); |
| |
| /** |
| * lws_http_redirect() - write http redirect out on wsi |
| * |
| * \param wsi: websocket connection |
| * \param code: HTTP response code (eg, 301) |
| * \param loc: where to redirect to |
| * \param len: length of loc |
| * \param p: pointer current position in buffer (updated as we write) |
| * \param end: pointer to end of buffer |
| * |
| * Returns amount written, or < 0 indicating fatal write failure. |
| */ |
| LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len, |
| unsigned char **p, unsigned char *end); |
| |
| /** |
| * lws_http_transaction_completed() - wait for new http transaction or close |
| * \param wsi: websocket connection |
| * |
| * Returns 1 if the HTTP connection must close now |
| * Returns 0 and resets connection to wait for new HTTP header / |
| * transaction if possible |
| */ |
| LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
| lws_http_transaction_completed(struct lws *wsi); |
| |
| /** |
| * lws_http_headers_detach() - drop the associated headers storage and allow |
| * it to be reused by another connection |
| * \param wsi: http connection |
| * |
| * If the wsi has an ah headers struct attached, detach it. |
| */ |
| LWS_VISIBLE LWS_EXTERN int |
| lws_http_headers_detach(struct lws *wsi); |
| |
| /** |
| * lws_http_mark_sse() - called to indicate this http stream is now doing SSE |
| * |
| * \param wsi: http connection |
| * |
| * Cancel any timeout on the wsi, and for h2, mark the network connection as |
| * containing an immortal stream for the duration the SSE stream is open. |
| */ |
| LWS_VISIBLE LWS_EXTERN int |
| lws_http_mark_sse(struct lws *wsi); |
| |
| /** |
| * lws_http_compression_apply() - apply an http compression transform |
| * |
| * \param wsi: the wsi to apply the compression transform to |
| * \param name: NULL, or the name of the compression transform, eg, "deflate" |
| * \param p: pointer to pointer to headers buffer |
| * \param end: pointer to end of headers buffer |
| * \param decomp: 0 = add compressor to wsi, 1 = add decompressor |
| * |
| * This allows transparent compression of dynamically generated HTTP. The |
| * requested compression (eg, "deflate") is only applied if the client headers |
| * indicated it was supported (and it has support in lws), otherwise it's a NOP. |
| * |
| * If the requested compression method is NULL, then the supported compression |
| * formats are tried, and for non-decompression (server) mode the first that's |
| * found on the client's accept-encoding header is chosen. |
| * |
| * NOTE: the compression transform, same as h2 support, relies on the user |
| * code using LWS_WRITE_HTTP and then LWS_WRITE_HTTP_FINAL on the last part |
| * written. The internal lws fileserving code already does this. |
| * |
| * If the library was built without the cmake option |
| * LWS_WITH_HTTP_STREAM_COMPRESSION set, then a NOP is provided for this api, |
| * allowing user code to build either way and use compression if available. |
| */ |
| LWS_VISIBLE int |
| lws_http_compression_apply(struct lws *wsi, const char *name, |
| unsigned char **p, unsigned char *end, char decomp); |
| ///@} |
| |