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_ALPN, |
354 | |
355 | /* always last real token index*/ |
356 | WSI_TOKEN_COUNT, |
357 | |
358 | /* parser state additions, no storage associated */ |
359 | WSI_TOKEN_NAME_PART, |
360 | #if defined(LWS_WITH_CUSTOM_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) |
361 | WSI_TOKEN_UNKNOWN_VALUE_PART, |
362 | #endif |
363 | WSI_TOKEN_SKIPPING, |
364 | WSI_TOKEN_SKIPPING_SAW_CR, |
365 | WSI_PARSING_COMPLETE, |
366 | WSI_INIT_TOKEN_MUXURL, |
367 | }; |
368 | |
369 | struct lws_token_limits { |
370 | unsigned short token_limit[WSI_TOKEN_COUNT]; /**< max chars for this token */ |
371 | }; |
372 | |
373 | enum lws_h2_settings { |
374 | = 1, |
375 | H2SET_ENABLE_PUSH, |
376 | H2SET_MAX_CONCURRENT_STREAMS, |
377 | H2SET_INITIAL_WINDOW_SIZE, |
378 | H2SET_MAX_FRAME_SIZE, |
379 | , |
380 | H2SET_RESERVED7, |
381 | H2SET_ENABLE_CONNECT_PROTOCOL, /* defined in mcmanus-httpbis-h2-ws-02 */ |
382 | |
383 | H2SET_COUNT /* always last */ |
384 | }; |
385 | |
386 | /** |
387 | * lws_token_to_string() - returns a textual representation of a hdr token index |
388 | * |
389 | * \param token: token index |
390 | */ |
391 | LWS_VISIBLE LWS_EXTERN const unsigned char * |
392 | lws_token_to_string(enum lws_token_indexes token); |
393 | |
394 | /** |
395 | * lws_hdr_total_length: report length of all fragments of a header totalled up |
396 | * The returned length does not include the space for a |
397 | * terminating '\0' |
398 | * |
399 | * \param wsi: websocket connection |
400 | * \param h: which header index we are interested in |
401 | */ |
402 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
403 | lws_hdr_total_length(struct lws *wsi, enum lws_token_indexes h); |
404 | |
405 | /** |
406 | * lws_hdr_fragment_length: report length of a single fragment of a header |
407 | * The returned length does not include the space for a |
408 | * terminating '\0' |
409 | * |
410 | * \param wsi: websocket connection |
411 | * \param h: which header index we are interested in |
412 | * \param frag_idx: which fragment of h we want to get the length of |
413 | */ |
414 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
415 | lws_hdr_fragment_length(struct lws *wsi, enum lws_token_indexes h, |
416 | int frag_idx); |
417 | |
418 | /** |
419 | * lws_hdr_copy() - copy all fragments of the given header to a buffer |
420 | * The buffer length len must include space for an additional |
421 | * terminating '\0', or it will fail returning -1. |
422 | * |
423 | * \param wsi: websocket connection |
424 | * \param dest: destination buffer |
425 | * \param len: length of destination buffer |
426 | * \param h: which header index we are interested in |
427 | * |
428 | * copies the whole, aggregated header, even if it was delivered in |
429 | * several actual headers piece by piece. Returns -1 or length of the whole |
430 | * header. |
431 | */ |
432 | LWS_VISIBLE LWS_EXTERN int |
433 | lws_hdr_copy(struct lws *wsi, char *dest, int len, enum lws_token_indexes h); |
434 | |
435 | /** |
436 | * lws_hdr_copy_fragment() - copy a single fragment of the given header to a buffer |
437 | * The buffer length len must include space for an additional |
438 | * terminating '\0', or it will fail returning -1. |
439 | * If the requested fragment index is not present, it fails |
440 | * returning -1. |
441 | * |
442 | * \param wsi: websocket connection |
443 | * \param dest: destination buffer |
444 | * \param len: length of destination buffer |
445 | * \param h: which header index we are interested in |
446 | * \param frag_idx: which fragment of h we want to copy |
447 | * |
448 | * Normally this is only useful |
449 | * to parse URI arguments like ?x=1&y=2, token index WSI_TOKEN_HTTP_URI_ARGS |
450 | * fragment 0 will contain "x=1" and fragment 1 "y=2" |
451 | */ |
452 | LWS_VISIBLE LWS_EXTERN int |
453 | lws_hdr_copy_fragment(struct lws *wsi, char *dest, int len, |
454 | enum lws_token_indexes h, int frag_idx); |
455 | |
456 | /** |
457 | * lws_hdr_custom_length() - return length of a custom header |
458 | * |
459 | * \param wsi: websocket connection |
460 | * \param name: header string (including terminating :) |
461 | * \param nlen: length of name |
462 | * |
463 | * Lws knows about 100 common http headers, and parses them into indexes when |
464 | * it recognizes them. When it meets a header that it doesn't know, it stores |
465 | * the name and value directly, and you can look them up using |
466 | * lws_hdr_custom_length() and lws_hdr_custom_copy(). |
467 | * |
468 | * This api returns -1, or the length of the value part of the header if it |
469 | * exists. Lws must be built with LWS_WITH_CUSTOM_HEADERS (on by default) to |
470 | * use this api. |
471 | */ |
472 | LWS_VISIBLE LWS_EXTERN int |
473 | lws_hdr_custom_length(struct lws *wsi, const char *name, int nlen); |
474 | |
475 | /** |
476 | * lws_hdr_custom_copy() - copy value part of a custom header |
477 | * |
478 | * \param wsi: websocket connection |
479 | * \param dst: pointer to buffer to receive the copy |
480 | * \param len: number of bytes available at dst |
481 | * \param name: header string (including terminating :) |
482 | * \param nlen: length of name |
483 | * |
484 | * Lws knows about 100 common http headers, and parses them into indexes when |
485 | * it recognizes them. When it meets a header that it doesn't know, it stores |
486 | * the name and value directly, and you can look them up using |
487 | * lws_hdr_custom_length() and lws_hdr_custom_copy(). |
488 | * |
489 | * This api returns -1, or the length of the string it copied into dst if it |
490 | * was big enough to contain both the string and an extra terminating NUL. Lws |
491 | * must be built with LWS_WITH_CUSTOM_HEADERS (on by default) to use this api. |
492 | */ |
493 | LWS_VISIBLE LWS_EXTERN int |
494 | lws_hdr_custom_copy(struct lws *wsi, char *dst, int len, const char *name, |
495 | int nlen); |
496 | |
497 | typedef void (*lws_hdr_custom_fe_cb_t)(const char *name, int nlen, void *opaque); |
498 | /** |
499 | * lws_hdr_custom_name_foreach() - Iterate the custom header names |
500 | * |
501 | * \param wsi: websocket connection |
502 | * \param cb: callback for each custom header name |
503 | * \param opaque: ignored by lws except to pass to callback |
504 | * |
505 | * Lws knows about 100 common http headers, and parses them into indexes when |
506 | * it recognizes them. When it meets a header that it doesn't know, it stores |
507 | * the name and value directly, and you can look them up using |
508 | * lws_hdr_custom_length() and lws_hdr_custom_copy(). |
509 | * |
510 | * This api returns -1 on error else 0. Use lws_hdr_custom_copy() to get the |
511 | * values of headers. Lws must be built with LWS_WITH_CUSTOM_HEADERS (on by |
512 | * default) to use this api. |
513 | */ |
514 | LWS_VISIBLE LWS_EXTERN int |
515 | lws_hdr_custom_name_foreach(struct lws *wsi, lws_hdr_custom_fe_cb_t cb, void *opaque); |
516 | |
517 | /** |
518 | * lws_get_urlarg_by_name_safe() - get copy and return length of y for x=y urlargs |
519 | * |
520 | * \param wsi: the connection to check |
521 | * \param name: the arg name, like "token" or "token=" |
522 | * \param buf: the buffer to receive the urlarg (including the name= part) |
523 | * \param len: the length of the buffer to receive the urlarg |
524 | * |
525 | * Returns -1 if not present, else the length of y in the urlarg name=y. If |
526 | * zero or greater, then buf contains a copy of the string y. Any = after the |
527 | * name match is trimmed off if the name does not end with = itself. |
528 | * |
529 | * This returns the explicit length and so can deal with binary blobs that are |
530 | * percent-encoded. It also makes sure buf has a NUL just after the valid |
531 | * length so it can work with NUL-based apis if you don't care about truncation. |
532 | * |
533 | * buf may have been written even when -1 is returned indicating no match. |
534 | * |
535 | * Use this in place of lws_get_urlarg_by_name() that does not return an |
536 | * explicit length. |
537 | */ |
538 | LWS_VISIBLE LWS_EXTERN int |
539 | lws_get_urlarg_by_name_safe(struct lws *wsi, const char *name, char *buf, int len); |
540 | |
541 | /** |
542 | * lws_get_urlarg_by_name() - return pointer to arg value if present |
543 | * |
544 | * \param wsi: the connection to check |
545 | * \param name: the arg name, like "token=" |
546 | * \param buf: the buffer to receive the urlarg (including the name= part) |
547 | * \param len: the length of the buffer to receive the urlarg |
548 | * |
549 | * Returns NULL if not found or a pointer inside buf to just after the |
550 | * name= part. |
551 | * |
552 | * This assumed the argument can be represented with a NUL-terminated string. |
553 | * It can't correctly deal with binary values encoded with %XX, eg. %00 will |
554 | * be understood to terminate the string. |
555 | * |
556 | * Use lws_get_urlarg_by_name_safe() instead of this, which returns the length. |
557 | */ |
558 | LWS_VISIBLE LWS_EXTERN const char * |
559 | lws_get_urlarg_by_name(struct lws *wsi, const char *name, char *buf, int len) |
560 | /* LWS_WARN_DEPRECATED */; |
561 | ///@} |
562 | |
563 | /*! \defgroup HTTP-headers-create HTTP headers: create |
564 | * |
565 | * ## HTTP headers: Create |
566 | * |
567 | * These apis allow you to create HTTP response headers in a way compatible with |
568 | * both HTTP/1.x and HTTP/2. |
569 | * |
570 | * They each append to a buffer taking care about the buffer end, which is |
571 | * passed in as a pointer. When data is written to the buffer, the current |
572 | * position p is updated accordingly. |
573 | * |
574 | * All of these apis are LWS_WARN_UNUSED_RESULT as they can run out of space |
575 | * and fail with nonzero return. |
576 | */ |
577 | ///@{ |
578 | |
579 | #define LWSAHH_CODE_MASK ((1 << 16) - 1) |
580 | #define LWSAHH_FLAG_NO_SERVER_NAME (1 << 30) |
581 | |
582 | /** |
583 | * lws_add_http_header_status() - add the HTTP response status code |
584 | * |
585 | * \param wsi: the connection to check |
586 | * \param code: an HTTP code like 200, 404 etc (see enum http_status) |
587 | * \param p: pointer to current position in buffer pointer |
588 | * \param end: pointer to end of buffer |
589 | * |
590 | * Adds the initial response code, so should be called first. |
591 | * |
592 | * Code may additionally take OR'd flags: |
593 | * |
594 | * LWSAHH_FLAG_NO_SERVER_NAME: don't apply server name header this time |
595 | */ |
596 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
597 | (struct lws *wsi, |
598 | unsigned int code, unsigned char **p, |
599 | unsigned char *end); |
600 | /** |
601 | * lws_add_http_header_by_name() - append named header and value |
602 | * |
603 | * \param wsi: the connection to check |
604 | * \param name: the hdr name, like "my-header:" |
605 | * \param value: the value after the = for this header |
606 | * \param length: the length of the value |
607 | * \param p: pointer to current position in buffer pointer |
608 | * \param end: pointer to end of buffer |
609 | * |
610 | * Appends name: value to the headers |
611 | */ |
612 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
613 | (struct lws *wsi, const unsigned char *name, |
614 | const unsigned char *value, int length, |
615 | unsigned char **p, unsigned char *end); |
616 | /** |
617 | * lws_add_http_header_by_token() - append given header and value |
618 | * |
619 | * \param wsi: the connection to check |
620 | * \param token: the token index for the hdr |
621 | * \param value: the value after the = for this header |
622 | * \param length: the length of the value |
623 | * \param p: pointer to current position in buffer pointer |
624 | * \param end: pointer to end of buffer |
625 | * |
626 | * Appends name=value to the headers, but is able to take advantage of better |
627 | * HTTP/2 coding mechanisms where possible. |
628 | */ |
629 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
630 | (struct lws *wsi, enum lws_token_indexes token, |
631 | const unsigned char *value, int length, |
632 | unsigned char **p, unsigned char *end); |
633 | /** |
634 | * lws_add_http_header_content_length() - append content-length helper |
635 | * |
636 | * \param wsi: the connection to check |
637 | * \param content_length: the content length to use |
638 | * \param p: pointer to current position in buffer pointer |
639 | * \param end: pointer to end of buffer |
640 | * |
641 | * Appends content-length: content_length to the headers |
642 | */ |
643 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
644 | (struct lws *wsi, |
645 | lws_filepos_t content_length, |
646 | unsigned char **p, unsigned char *end); |
647 | /** |
648 | * lws_finalize_http_header() - terminate header block |
649 | * |
650 | * \param wsi: the connection to check |
651 | * \param p: pointer to current position in buffer pointer |
652 | * \param end: pointer to end of buffer |
653 | * |
654 | * Indicates no more headers will be added |
655 | */ |
656 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
657 | (struct lws *wsi, unsigned char **p, |
658 | unsigned char *end); |
659 | |
660 | /** |
661 | * lws_finalize_write_http_header() - Helper finializing and writing http headers |
662 | * |
663 | * \param wsi: the connection to check |
664 | * \param start: pointer to the start of headers in the buffer, eg &buf[LWS_PRE] |
665 | * \param p: pointer to current position in buffer pointer |
666 | * \param end: pointer to end of buffer |
667 | * |
668 | * Terminates the headers correctly accoring to the protocol in use (h1 / h2) |
669 | * and writes the headers. Returns nonzero for error. |
670 | */ |
671 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
672 | (struct lws *wsi, unsigned char *start, |
673 | unsigned char **p, unsigned char *end); |
674 | |
675 | #define LWS_ILLEGAL_HTTP_CONTENT_LEN ((lws_filepos_t)-1ll) |
676 | |
677 | /** |
678 | * lws_add_http_common_headers() - Helper preparing common http headers |
679 | * |
680 | * \param wsi: the connection to check |
681 | * \param code: an HTTP code like 200, 404 etc (see enum http_status) |
682 | * \param content_type: the content type, like "text/html" |
683 | * \param content_len: the content length, in bytes |
684 | * \param p: pointer to current position in buffer pointer |
685 | * \param end: pointer to end of buffer |
686 | * |
687 | * Adds the initial response code, so should be called first. |
688 | * |
689 | * Code may additionally take OR'd flags: |
690 | * |
691 | * LWSAHH_FLAG_NO_SERVER_NAME: don't apply server name header this time |
692 | * |
693 | * This helper just calls public apis to simplify adding headers that are |
694 | * commonly needed. If it doesn't fit your case, or you want to add additional |
695 | * headers just call the public apis directly yourself for what you want. |
696 | * |
697 | * You can miss out the content length header by providing the constant |
698 | * LWS_ILLEGAL_HTTP_CONTENT_LEN for the content_len. |
699 | * |
700 | * It does not call lws_finalize_http_header(), to allow you to add further |
701 | * headers after calling this. You will need to call that yourself at the end. |
702 | */ |
703 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
704 | (struct lws *wsi, unsigned int code, |
705 | const char *content_type, lws_filepos_t content_len, |
706 | unsigned char **p, unsigned char *end); |
707 | |
708 | enum { |
709 | LWSHUMETH_GET, |
710 | LWSHUMETH_POST, |
711 | LWSHUMETH_OPTIONS, |
712 | LWSHUMETH_PUT, |
713 | LWSHUMETH_PATCH, |
714 | LWSHUMETH_DELETE, |
715 | LWSHUMETH_CONNECT, |
716 | LWSHUMETH_HEAD, |
717 | LWSHUMETH_COLON_PATH, |
718 | }; |
719 | |
720 | /** |
721 | * lws_http_get_uri_and_method() - Get information on method and url |
722 | * |
723 | * \param wsi: the connection to get information on |
724 | * \param puri_ptr: points to pointer to set to url |
725 | * \param puri_len: points to int to set to uri length |
726 | * |
727 | * Returns -1 or method index as one of the LWSHUMETH_ constants |
728 | * |
729 | * If returns method, *puri_ptr is set to the method's URI string and *puri_len |
730 | * to its length |
731 | */ |
732 | |
733 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
734 | lws_http_get_uri_and_method(struct lws *wsi, char **puri_ptr, int *puri_len); |
735 | |
736 | ///@} |
737 | |
738 | /*! \defgroup urlendec Urlencode and Urldecode |
739 | * \ingroup http |
740 | * |
741 | * ##HTML chunked Substitution |
742 | * |
743 | * APIs for receiving chunks of text, replacing a set of variable names via |
744 | * a callback, and then prepending and appending HTML chunked encoding |
745 | * headers. |
746 | */ |
747 | //@{ |
748 | |
749 | /** |
750 | * lws_urlencode() - like strncpy but with urlencoding |
751 | * |
752 | * \param escaped: output buffer |
753 | * \param string: input buffer ('/0' terminated) |
754 | * \param len: output buffer max length |
755 | * |
756 | * Because urlencoding expands the output string, it's not |
757 | * possible to do it in-place, ie, with escaped == string |
758 | */ |
759 | LWS_VISIBLE LWS_EXTERN const char * |
760 | lws_urlencode(char *escaped, const char *string, int len); |
761 | |
762 | /* |
763 | * URLDECODE 1 / 2 |
764 | * |
765 | * This simple urldecode only operates until the first '\0' and requires the |
766 | * data to exist all at once |
767 | */ |
768 | /** |
769 | * lws_urldecode() - like strncpy but with urldecoding |
770 | * |
771 | * \param string: output buffer |
772 | * \param escaped: input buffer ('\0' terminated) |
773 | * \param len: output buffer max length |
774 | * |
775 | * This is only useful for '\0' terminated strings |
776 | * |
777 | * Since urldecoding only shrinks the output string, it is possible to |
778 | * do it in-place, ie, string == escaped |
779 | * |
780 | * Returns 0 if completed OK or nonzero for urldecode violation (non-hex chars |
781 | * where hex required, etc) |
782 | */ |
783 | LWS_VISIBLE LWS_EXTERN int |
784 | lws_urldecode(char *string, const char *escaped, int len); |
785 | ///@} |
786 | |
787 | /** |
788 | * lws_http_date_render_from_unix() - render unixtime as RFC7231 date string |
789 | * |
790 | * \param buf: Destination string buffer |
791 | * \param len: avilable length of dest string buffer in bytes |
792 | * \param t: pointer to the time_t to render |
793 | * |
794 | * Returns 0 if time_t is rendered into the string buffer successfully, else |
795 | * nonzero. |
796 | */ |
797 | LWS_VISIBLE LWS_EXTERN int |
798 | lws_http_date_render_from_unix(char *buf, size_t len, const time_t *t); |
799 | |
800 | /** |
801 | * lws_http_date_parse_unix() - parse a RFC7231 date string into unixtime |
802 | * |
803 | * \param b: Source string buffer |
804 | * \param len: avilable length of source string buffer in bytes |
805 | * \param t: pointer to the destination time_t to set |
806 | * |
807 | * Returns 0 if string buffer parsed as RFC7231 time successfully, and |
808 | * *t set to the parsed unixtime, else return nonzero. |
809 | */ |
810 | LWS_VISIBLE LWS_EXTERN int |
811 | lws_http_date_parse_unix(const char *b, size_t len, time_t *t); |
812 | |
813 | /** |
814 | * lws_http_check_retry_after() - increase a timeout if retry-after present |
815 | * |
816 | * \param wsi: http stream this relates to |
817 | * \param us_interval_in_out: default us retry interval on entry may be updated |
818 | * |
819 | * This function may extend the incoming retry interval if the server has |
820 | * requested that using retry-after: header. It won't reduce the incoming |
821 | * retry interval, only leave it alone or increase it. |
822 | * |
823 | * *us_interval_in_out should be set to a default retry interval on entry, if |
824 | * the wsi has a retry-after time or interval that resolves to an interval |
825 | * longer than the entry *us_interval_in_out, that will be updated to the longer |
826 | * interval and return 0. |
827 | * |
828 | * If no usable retry-after or the time is now or in the past, |
829 | * *us_interval_in_out is left alone and the function returns nonzero. |
830 | */ |
831 | LWS_VISIBLE LWS_EXTERN int |
832 | lws_http_check_retry_after(struct lws *wsi, lws_usec_t *us_interval_in_out); |
833 | |
834 | /** |
835 | * lws_return_http_status() - Return simple http status |
836 | * \param wsi: Websocket instance (available from user callback) |
837 | * \param code: Status index, eg, 404 |
838 | * \param html_body: User-readable HTML description < 1KB, or NULL |
839 | * |
840 | * Helper to report HTTP errors back to the client cleanly and |
841 | * consistently |
842 | */ |
843 | LWS_VISIBLE LWS_EXTERN int |
844 | lws_return_http_status(struct lws *wsi, unsigned int code, |
845 | const char *html_body); |
846 | |
847 | /** |
848 | * lws_http_redirect() - write http redirect out on wsi |
849 | * |
850 | * \param wsi: websocket connection |
851 | * \param code: HTTP response code (eg, 301) |
852 | * \param loc: where to redirect to |
853 | * \param len: length of loc |
854 | * \param p: pointer current position in buffer (updated as we write) |
855 | * \param end: pointer to end of buffer |
856 | * |
857 | * Returns amount written, or < 0 indicating fatal write failure. |
858 | */ |
859 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
860 | lws_http_redirect(struct lws *wsi, int code, const unsigned char *loc, int len, |
861 | unsigned char **p, unsigned char *end); |
862 | |
863 | /** |
864 | * lws_http_transaction_completed() - wait for new http transaction or close |
865 | * \param wsi: websocket connection |
866 | * |
867 | * Returns nonzero if the HTTP connection must close now |
868 | * Returns 0 and resets connection to wait for new HTTP header / |
869 | * transaction if possible |
870 | */ |
871 | LWS_VISIBLE LWS_EXTERN int LWS_WARN_UNUSED_RESULT |
872 | lws_http_transaction_completed(struct lws *wsi); |
873 | |
874 | /** |
875 | * lws_http_headers_detach() - drop the associated headers storage and allow |
876 | * it to be reused by another connection |
877 | * \param wsi: http connection |
878 | * |
879 | * If the wsi has an ah headers struct attached, detach it. |
880 | */ |
881 | LWS_VISIBLE LWS_EXTERN int |
882 | (struct lws *wsi); |
883 | |
884 | /** |
885 | * lws_http_mark_sse() - called to indicate this http stream is now doing SSE |
886 | * |
887 | * \param wsi: http connection |
888 | * |
889 | * Cancel any timeout on the wsi, and for h2, mark the network connection as |
890 | * containing an immortal stream for the duration the SSE stream is open. |
891 | */ |
892 | LWS_VISIBLE LWS_EXTERN int |
893 | lws_http_mark_sse(struct lws *wsi); |
894 | |
895 | /** |
896 | * lws_h2_client_stream_long_poll_rxonly() - h2 stream to immortal read-only |
897 | * |
898 | * \param wsi: h2 stream client wsi |
899 | * |
900 | * Send END_STREAM-flagged zero-length DATA frame to set client stream wsi into |
901 | * half-closed (local) and remote into half-closed (remote). Set the client |
902 | * stream wsi to be immortal (not subject to timeouts). |
903 | * |
904 | * Used if the remote server supports immortal long poll to put the stream into |
905 | * a read-only state where it can wait as long as needed for rx. |
906 | * |
907 | * Returns 0 if the process (which happens asynchronously) started or non-zero |
908 | * if it wasn't an h2 stream. |
909 | */ |
910 | LWS_VISIBLE LWS_EXTERN int |
911 | lws_h2_client_stream_long_poll_rxonly(struct lws *wsi); |
912 | |
913 | /** |
914 | * lws_http_compression_apply() - apply an http compression transform |
915 | * |
916 | * \param wsi: the wsi to apply the compression transform to |
917 | * \param name: NULL, or the name of the compression transform, eg, "deflate" |
918 | * \param p: pointer to pointer to headers buffer |
919 | * \param end: pointer to end of headers buffer |
920 | * \param decomp: 0 = add compressor to wsi, 1 = add decompressor |
921 | * |
922 | * This allows transparent compression of dynamically generated HTTP. The |
923 | * requested compression (eg, "deflate") is only applied if the client headers |
924 | * indicated it was supported (and it has support in lws), otherwise it's a NOP. |
925 | * |
926 | * If the requested compression method is NULL, then the supported compression |
927 | * formats are tried, and for non-decompression (server) mode the first that's |
928 | * found on the client's accept-encoding header is chosen. |
929 | * |
930 | * NOTE: the compression transform, same as h2 support, relies on the user |
931 | * code using LWS_WRITE_HTTP and then LWS_WRITE_HTTP_FINAL on the last part |
932 | * written. The internal lws fileserving code already does this. |
933 | * |
934 | * If the library was built without the cmake option |
935 | * LWS_WITH_HTTP_STREAM_COMPRESSION set, then a NOP is provided for this api, |
936 | * allowing user code to build either way and use compression if available. |
937 | */ |
938 | LWS_VISIBLE LWS_EXTERN int |
939 | lws_http_compression_apply(struct lws *wsi, const char *name, |
940 | unsigned char **p, unsigned char *end, char decomp); |
941 | |
942 | /** |
943 | * lws_http_is_redirected_to_get() - true if redirected to GET |
944 | * |
945 | * \param wsi: the wsi to check |
946 | * |
947 | * Check if the wsi is currently in GET mode, after, eg, doing a POST and |
948 | * receiving a 303. |
949 | */ |
950 | LWS_VISIBLE LWS_EXTERN int |
951 | lws_http_is_redirected_to_get(struct lws *wsi); |
952 | |
953 | /** |
954 | * lws_http_cookie_get() - return copy of named cookie if present |
955 | * |
956 | * \param wsi: the wsi to check |
957 | * \param name: name of the cookie |
958 | * \param buf: buffer to store the cookie contents into |
959 | * \param max_len: on entry, maximum length of buf... on exit, used len of buf |
960 | * |
961 | * If no cookie header, or no cookie of the requested name, or the value is |
962 | * larger than can fit in buf, returns nonzero. |
963 | * |
964 | * If the cookie is found, copies its value into buf with a terminating NUL, |
965 | * sets *max_len to the used length, and returns 0. |
966 | * |
967 | * This handles the parsing of the possibly multi-cookie header string and |
968 | * terminating the requested cookie at the next ; if present. |
969 | */ |
970 | LWS_VISIBLE LWS_EXTERN int |
971 | lws_http_cookie_get(struct lws *wsi, const char *name, char *buf, size_t *max); |
972 | |
973 | /** |
974 | * lws_http_client_http_error() - determine if the response code indicates an error |
975 | * |
976 | * \param code: the response code to test |
977 | * |
978 | * Returns nonzero if the code indicates an error, else zero if reflects a |
979 | * non-error condition |
980 | */ |
981 | #define lws_http_client_http_resp_is_error(code) (!(code < 400)) |
982 | |
983 | /** |
984 | * lws_h2_update_peer_txcredit() - manually update stream peer tx credit |
985 | * |
986 | * \param wsi: the h2 child stream whose peer credit to change |
987 | * \param sid: the stream ID, or LWS_H2_STREAM_SID for the wsi stream ID |
988 | * \param bump: signed change to confer upon peer tx credit for sid |
989 | * |
990 | * In conjunction with LCCSCF_H2_MANUAL_RXFLOW flag, allows the user code to |
991 | * selectively starve the remote peer of the ability to send us data on a client |
992 | * connection. |
993 | * |
994 | * Normally lws sends an initial window size for the peer to send to it of 0, |
995 | * but during the header phase it sends a WINDOW_UPDATE to increase the amount |
996 | * available. LCCSCF_H2_MANUAL_RXFLOW restricts this initial increase in tx |
997 | * credit for the stream, before it has been asked to send us anything, to the |
998 | * amount specified in the client info .manual_initial_tx_credit member, and |
999 | * this api can be called to send the other side permission to send us up to |
1000 | * \p bump additional bytes. |
1001 | * |
1002 | * The nwsi tx credit is updated automatically for exactly what was sent to us |
1003 | * on a stream with LCCSCF_H2_MANUAL_RXFLOW flag, but the stream's own tx credit |
1004 | * must be handled manually by user code via this api. |
1005 | * |
1006 | * Returns 0 for success or nonzero for failure. |
1007 | */ |
1008 | #define LWS_H2_STREAM_SID -1 |
1009 | LWS_VISIBLE LWS_EXTERN int |
1010 | lws_h2_update_peer_txcredit(struct lws *wsi, unsigned int sid, int bump); |
1011 | |
1012 | |
1013 | /** |
1014 | * lws_h2_get_peer_txcredit_estimate() - return peer tx credit estimate |
1015 | * |
1016 | * \param wsi: the h2 child stream whose peer credit estimate to return |
1017 | * |
1018 | * Returns the estimated amount of tx credit at the peer, in other words the |
1019 | * number of bytes the peer is authorized to send to us. |
1020 | * |
1021 | * It's an 'estimate' because we don't know how much is already in flight |
1022 | * towards us and actually already used. |
1023 | */ |
1024 | LWS_VISIBLE LWS_EXTERN int |
1025 | lws_h2_get_peer_txcredit_estimate(struct lws *wsi); |
1026 | |
1027 | ///@} |
1028 | |
1029 | |