1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-23 00:00:06 +01:00
libwebsockets/include/libwebsockets/lws-http.h
Andy Green c9731c5f17 type comparisons: fixes
This is a huge patch that should be a global NOP.

For unix type platforms it enables -Wconversion to issue warnings (-> error)
for all automatic casts that seem less than ideal but are normally concealed
by the toolchain.

This is things like passing an int to a size_t argument.  Once enabled, I
went through all args on my default build (which build most things) and
tried to make the removed default cast explicit.

With that approach it neither change nor bloat the code, since it compiles
to whatever it was doing before, just with the casts made explicit... in a
few cases I changed some length args from int to size_t but largely left
the causes alone.

From now on, new code that is relying on less than ideal casting
will complain and nudge me to improve it by warnings.
2021-01-05 10:56:38 +00:00

975 lines
33 KiB
C

/*
* libwebsockets - small server side websockets and web server implementation
*
* Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/* 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 {
unsigned 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,
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_OPTIONS_URI,
#endif
WSI_TOKEN_HOST,
WSI_TOKEN_CONNECTION,
WSI_TOKEN_UPGRADE, /* 5 */
WSI_TOKEN_ORIGIN,
#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_DRAFT,
#endif
WSI_TOKEN_CHALLENGE,
#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_EXTENSIONS,
WSI_TOKEN_KEY1, /* 10 */
WSI_TOKEN_KEY2,
WSI_TOKEN_PROTOCOL,
WSI_TOKEN_ACCEPT,
WSI_TOKEN_NONCE,
#endif
WSI_TOKEN_HTTP,
#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_HTTP2_SETTINGS, /* 16 */
#endif
WSI_TOKEN_HTTP_ACCEPT,
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_HTTP_AC_REQUEST_HEADERS,
#endif
WSI_TOKEN_HTTP_IF_MODIFIED_SINCE,
WSI_TOKEN_HTTP_IF_NONE_MATCH, /* 20 */
WSI_TOKEN_HTTP_ACCEPT_ENCODING,
WSI_TOKEN_HTTP_ACCEPT_LANGUAGE,
WSI_TOKEN_HTTP_PRAGMA,
WSI_TOKEN_HTTP_CACHE_CONTROL,
WSI_TOKEN_HTTP_AUTHORIZATION,
WSI_TOKEN_HTTP_COOKIE,
WSI_TOKEN_HTTP_CONTENT_LENGTH, /* 27 */
WSI_TOKEN_HTTP_CONTENT_TYPE,
WSI_TOKEN_HTTP_DATE,
WSI_TOKEN_HTTP_RANGE,
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_HTTP_REFERER,
#endif
#if defined(LWS_ROLE_WS) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_KEY,
WSI_TOKEN_VERSION,
WSI_TOKEN_SWORIGIN,
#endif
#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_HTTP_COLON_AUTHORITY,
WSI_TOKEN_HTTP_COLON_METHOD,
WSI_TOKEN_HTTP_COLON_PATH,
WSI_TOKEN_HTTP_COLON_SCHEME,
WSI_TOKEN_HTTP_COLON_STATUS,
#endif
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_HTTP_ACCEPT_CHARSET,
#endif
WSI_TOKEN_HTTP_ACCEPT_RANGES,
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_HTTP_ACCESS_CONTROL_ALLOW_ORIGIN,
#endif
WSI_TOKEN_HTTP_AGE,
WSI_TOKEN_HTTP_ALLOW,
WSI_TOKEN_HTTP_CONTENT_DISPOSITION,
WSI_TOKEN_HTTP_CONTENT_ENCODING,
WSI_TOKEN_HTTP_CONTENT_LANGUAGE,
WSI_TOKEN_HTTP_CONTENT_LOCATION,
WSI_TOKEN_HTTP_CONTENT_RANGE,
WSI_TOKEN_HTTP_ETAG,
WSI_TOKEN_HTTP_EXPECT,
WSI_TOKEN_HTTP_EXPIRES,
WSI_TOKEN_HTTP_FROM,
WSI_TOKEN_HTTP_IF_MATCH,
WSI_TOKEN_HTTP_IF_RANGE,
WSI_TOKEN_HTTP_IF_UNMODIFIED_SINCE,
WSI_TOKEN_HTTP_LAST_MODIFIED,
WSI_TOKEN_HTTP_LINK,
WSI_TOKEN_HTTP_LOCATION,
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_HTTP_MAX_FORWARDS,
WSI_TOKEN_HTTP_PROXY_AUTHENTICATE,
WSI_TOKEN_HTTP_PROXY_AUTHORIZATION,
#endif
WSI_TOKEN_HTTP_REFRESH,
WSI_TOKEN_HTTP_RETRY_AFTER,
WSI_TOKEN_HTTP_SERVER,
WSI_TOKEN_HTTP_SET_COOKIE,
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_HTTP_STRICT_TRANSPORT_SECURITY,
#endif
WSI_TOKEN_HTTP_TRANSFER_ENCODING,
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_HTTP_USER_AGENT,
WSI_TOKEN_HTTP_VARY,
WSI_TOKEN_HTTP_VIA,
WSI_TOKEN_HTTP_WWW_AUTHENTICATE,
#endif
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_PATCH_URI,
WSI_TOKEN_PUT_URI,
WSI_TOKEN_DELETE_URI,
#endif
WSI_TOKEN_HTTP_URI_ARGS,
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_PROXY,
WSI_TOKEN_HTTP_X_REAL_IP,
#endif
WSI_TOKEN_HTTP1_0,
WSI_TOKEN_X_FORWARDED_FOR,
WSI_TOKEN_CONNECT,
WSI_TOKEN_HEAD_URI,
#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_TE,
WSI_TOKEN_REPLAY_NONCE, /* ACME */
#endif
#if defined(LWS_ROLE_H2) || defined(LWS_HTTP_HEADERS_ALL)
WSI_TOKEN_COLON_PROTOCOL,
#endif
WSI_TOKEN_X_AUTH_TOKEN,
/****** 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) || defined(LWS_HTTP_HEADERS_ALL)
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 */
};
enum lws_h2_settings {
H2SET_HEADER_TABLE_SIZE = 1,
H2SET_ENABLE_PUSH,
H2SET_MAX_CONCURRENT_STREAMS,
H2SET_INITIAL_WINDOW_SIZE,
H2SET_MAX_FRAME_SIZE,
H2SET_MAX_HEADER_LIST_SIZE,
H2SET_RESERVED7,
H2SET_ENABLE_CONNECT_PROTOCOL, /* defined in mcmanus-httpbis-h2-ws-02 */
H2SET_COUNT /* always last */
};
/**
* 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);
enum {
LWSHUMETH_GET,
LWSHUMETH_POST,
LWSHUMETH_OPTIONS,
LWSHUMETH_PUT,
LWSHUMETH_PATCH,
LWSHUMETH_DELETE,
LWSHUMETH_CONNECT,
LWSHUMETH_HEAD,
LWSHUMETH_COLON_PATH,
};
/**
* lws_http_get_uri_and_method() - Get information on method and url
*
* \param wsi: the connection to get information on
* \param puri_ptr: points to pointer to set to url
* \param puri_len: points to int to set to uri length
*
* Returns -1 or method index as one of the LWSHUMETH_ constants
*
* If returns method, *puri_ptr is set to the method's URI string and *puri_len
* to its length
*/
LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT
lws_http_get_uri_and_method(struct lws *wsi, char **puri_ptr, int *puri_len);
///@}
/*! \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_http_date_render_from_unix() - render unixtime as RFC7231 date string
*
* \param buf: Destination string buffer
* \param len: avilable length of dest string buffer in bytes
* \param t: pointer to the time_t to render
*
* Returns 0 if time_t is rendered into the string buffer successfully, else
* nonzero.
*/
LWS_VISIBLE LWS_EXTERN int
lws_http_date_render_from_unix(char *buf, size_t len, const time_t *t);
/**
* lws_http_date_parse_unix() - parse a RFC7231 date string into unixtime
*
* \param b: Source string buffer
* \param len: avilable length of source string buffer in bytes
* \param t: pointer to the destination time_t to set
*
* Returns 0 if string buffer parsed as RFC7231 time successfully, and
* *t set to the parsed unixtime, else return nonzero.
*/
LWS_VISIBLE LWS_EXTERN int
lws_http_date_parse_unix(const char *b, size_t len, time_t *t);
/**
* lws_http_check_retry_after() - increase a timeout if retry-after present
*
* \param wsi: http stream this relates to
* \param us_interval_in_out: default us retry interval on entry may be updated
*
* This function may extend the incoming retry interval if the server has
* requested that using retry-after: header. It won't reduce the incoming
* retry interval, only leave it alone or increase it.
*
* *us_interval_in_out should be set to a default retry interval on entry, if
* the wsi has a retry-after time or interval that resolves to an interval
* longer than the entry *us_interval_in_out, that will be updated to the longer
* interval and return 0.
*
* If no usable retry-after or the time is now or in the past,
* *us_interval_in_out is left alone and the function returns nonzero.
*/
LWS_VISIBLE LWS_EXTERN int
lws_http_check_retry_after(struct lws *wsi, lws_usec_t *us_interval_in_out);
/**
* 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_h2_client_stream_long_poll_rxonly() - h2 stream to immortal read-only
*
* \param wsi: h2 stream client wsi
*
* Send END_STREAM-flagged zero-length DATA frame to set client stream wsi into
* half-closed (local) and remote into half-closed (remote). Set the client
* stream wsi to be immortal (not subject to timeouts).
*
* Used if the remote server supports immortal long poll to put the stream into
* a read-only state where it can wait as long as needed for rx.
*
* Returns 0 if the process (which happens asynchronously) started or non-zero
* if it wasn't an h2 stream.
*/
LWS_VISIBLE LWS_EXTERN int
lws_h2_client_stream_long_poll_rxonly(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 LWS_EXTERN int
lws_http_compression_apply(struct lws *wsi, const char *name,
unsigned char **p, unsigned char *end, char decomp);
/**
* lws_http_is_redirected_to_get() - true if redirected to GET
*
* \param wsi: the wsi to check
*
* Check if the wsi is currently in GET mode, after, eg, doing a POST and
* receiving a 303.
*/
LWS_VISIBLE LWS_EXTERN int
lws_http_is_redirected_to_get(struct lws *wsi);
/**
* lws_http_cookie_get() - return copy of named cookie if present
*
* \param wsi: the wsi to check
* \param name: name of the cookie
* \param buf: buffer to store the cookie contents into
* \param max_len: on entry, maximum length of buf... on exit, used len of buf
*
* If no cookie header, or no cookie of the requested name, or the value is
* larger than can fit in buf, returns nonzero.
*
* If the cookie is found, copies its value into buf with a terminating NUL,
* sets *max_len to the used length, and returns 0.
*
* This handles the parsing of the possibly multi-cookie header string and
* terminating the requested cookie at the next ; if present.
*/
LWS_VISIBLE LWS_EXTERN int
lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, size_t *max);
/**
* lws_http_client_http_error() - determine if the response code indicates an error
*
* \param code: the response code to test
*
* Returns nonzero if the code indicates an error, else zero if reflects a
* non-error condition
*/
#define lws_http_client_http_resp_is_error(code) (!(code < 400))
/**
* lws_h2_update_peer_txcredit() - manually update stream peer tx credit
*
* \param wsi: the h2 child stream whose peer credit to change
* \param sid: the stream ID, or LWS_H2_STREAM_SID for the wsi stream ID
* \param bump: signed change to confer upon peer tx credit for sid
*
* In conjunction with LCCSCF_H2_MANUAL_RXFLOW flag, allows the user code to
* selectively starve the remote peer of the ability to send us data on a client
* connection.
*
* Normally lws sends an initial window size for the peer to send to it of 0,
* but during the header phase it sends a WINDOW_UPDATE to increase the amount
* available. LCCSCF_H2_MANUAL_RXFLOW restricts this initial increase in tx
* credit for the stream, before it has been asked to send us anything, to the
* amount specified in the client info .manual_initial_tx_credit member, and
* this api can be called to send the other side permission to send us up to
* \p bump additional bytes.
*
* The nwsi tx credit is updated automatically for exactly what was sent to us
* on a stream with LCCSCF_H2_MANUAL_RXFLOW flag, but the stream's own tx credit
* must be handled manually by user code via this api.
*
* Returns 0 for success or nonzero for failure.
*/
#define LWS_H2_STREAM_SID -1
LWS_VISIBLE LWS_EXTERN int
lws_h2_update_peer_txcredit(struct lws *wsi, unsigned int sid, int bump);
/**
* lws_h2_get_peer_txcredit_estimate() - return peer tx credit estimate
*
* \param wsi: the h2 child stream whose peer credit estimate to return
*
* Returns the estimated amount of tx credit at the peer, in other words the
* number of bytes the peer is authorized to send to us.
*
* It's an 'estimate' because we don't know how much is already in flight
* towards us and actually already used.
*/
LWS_VISIBLE LWS_EXTERN int
lws_h2_get_peer_txcredit_estimate(struct lws *wsi);
///@}