Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
{"schema":"libjg2-1", "vpath":"/git/", "avatar":"/git/avatar/", "alang":"", "gen_ut":1750141416, "reponame":"libwebsockets", "desc":"libwebsockets lightweight C networking library", "owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://libwebsockets.org/repo/libwebsockets", "f":3, "items": [ {"schema":"libjg2-1", "cid":"be1306d91f96ed88c6f1735dc0dd0ee3", "commit": {"type":"commit", "time": 1458379305, "time_ofs": 480, "oid_tree": { "oid": "2083743e8971c50593d654380a4e01c75f34b21a", "alias": []}, "oid":{ "oid": "5c8906e93163d314eba9dc42e24cfa419d28a0cb", "alias": []}, "msg": "client chunked transfer encoding", "sig_commit": { "git_time": { "time": 1458379305, "offset": 480 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }, "sig_author": { "git_time": { "time": 1457858659, "offset": 480 }, "name": "Andy Green", "email": "andy.green@linaro.org", "md5": "4863edaebb4491aa6049a4d2d9c98c2c" }}, "body": "client chunked transfer encoding\n\nSigned-off-by: Andy Green \u003candy.green@linaro.org\u003e\n" , "diff": "diff --git a/changelog b/changelog\nindex fc87206..ef5a406 100644\n--- a/changelog\n+++ b/changelog\n@@ -79,7 +79,7 @@ just deferred until an ah becomes available.\n 8) The test client pays attention to if you give it an http:/ or https://\n protocol string to its argument in URL format. If so, it stays in http[s]\n client mode and doesn't upgrade to ws[s], allowing you to do generic http client\n-operations.\n+operations. Receiving transfer-encoding: chunked is supported.\n \n 9) The test server has a new URI path http://localhost:7681/proxytest\n If you visit here, a client connection to http://example.com:80 is spawned,\ndiff --git a/lib/client.c b/lib/client.c\nindex fdf1eff..37779be 100644\n--- a/lib/client.c\n+++ b/lib/client.c\n@@ -628,6 +628,17 @@ lws_client_interpret_server_handshake(struct lws *wsi)\n \t\t\tgoto bail2;\n \t\t}\n \n+\t\t/* he may choose to send us stuff in chunked transfer-coding */\n+\t\twsi-\u003echunked \u003d 0;\n+\t\twsi-\u003echunk_remaining \u003d 0; /* ie, next thing is chunk size */\n+\t\tif (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_TRANSFER_ENCODING)) {\n+\t\t\twsi-\u003echunked \u003d !strcmp(lws_hdr_simple_ptr(wsi,\n+\t\t\t\t\t WSI_TOKEN_HTTP_TRANSFER_ENCODING),\n+\t\t\t\t\t\u0022chunked\u0022);\n+\t\t\t/* first thing is hex, after payload there is crlf */\n+\t\t\twsi-\u003echunk_parser \u003d ELCP_HEX;\n+\t\t}\n+\n \t\tif (lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {\n \t\t\twsi-\u003eu.http.content_length \u003d\n \t\t\t\t\tatoi(lws_hdr_simple_ptr(wsi,\n@@ -635,8 +646,9 @@ lws_client_interpret_server_handshake(struct lws *wsi)\n \t\t\tlwsl_notice(\u0022%s: incoming content length %d\u005cn\u0022, __func__,\n \t\t\t\t\twsi-\u003eu.http.content_length);\n \t\t\twsi-\u003eu.http.content_remain \u003d wsi-\u003eu.http.content_length;\n-\t\t} else /* can't do 1.1 without a content length */\n-\t\t\twsi-\u003eu.http.connection_type \u003d HTTP_CONNECTION_CLOSE;\n+\t\t} else /* can't do 1.1 without a content length or chunked */\n+\t\t\tif (!wsi-\u003echunked)\n+\t\t\t\twsi-\u003eu.http.connection_type \u003d HTTP_CONNECTION_CLOSE;\n \n \t\t/*\n \t\t * we seem to be good to go, give client last chance to check\ndiff --git a/lib/parsers.c b/lib/parsers.c\nindex 96be75d..879db99 100644\n--- a/lib/parsers.c\n+++ b/lib/parsers.c\n@@ -496,7 +496,7 @@ lws_hdr_simple_create(struct lws *wsi, enum lws_token_indexes h, const char *s)\n \treturn 0;\n }\n \n-static signed char char_to_hex(const char c)\n+signed char char_to_hex(const char c)\n {\n \tif (c \u003e\u003d '0' \u0026\u0026 c \u003c\u003d '9')\n \t\treturn c - '0';\ndiff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h\nindex 5f118ad..4d69bd5 100644\n--- a/lib/private-libwebsockets.h\n+++ b/lib/private-libwebsockets.h\n@@ -1054,7 +1054,18 @@ struct lws_cgi {\n \n \tunsigned int being_closed:1;\n };\n+#endif\n+\n+signed char char_to_hex(const char c);\n \n+#ifndef LWS_NO_CLIENT\n+enum lws_chunk_parser {\n+\tELCP_HEX,\n+\tELCP_CR,\n+\tELCP_CONTENT,\n+\tELCP_POST_CR,\n+\tELCP_POST_LF,\n+};\n #endif\n \n struct lws {\n@@ -1121,6 +1132,9 @@ struct lws {\n \tunsigned int trunc_alloc_len; /* size of malloc */\n \tunsigned int trunc_offset; /* where we are in terms of spilling */\n \tunsigned int trunc_len; /* how much is buffered */\n+#ifndef LWS_NO_CLIENT\n+\tint chunk_remaining;\n+#endif\n \n \tunsigned int hdr_parsing_completed:1;\n \tunsigned int user_space_externally_allocated:1;\n@@ -1129,6 +1143,7 @@ struct lws {\n \tunsigned int more_rx_waiting:1; /* has to live here since ah may stick to end */\n #ifndef LWS_NO_CLIENT\n \tunsigned int do_ws:1; /* whether we are doing http or ws flow */\n+\tunsigned int chunked:1; /* if the clientside connection is chunked */\n #endif\n #ifndef LWS_NO_EXTENSIONS\n \tunsigned int extension_data_pending:1;\n@@ -1161,6 +1176,9 @@ struct lws {\n \tchar cgi_channel; /* which of stdin/out/err */\n \tchar hdr_state;\n #endif\n+#ifndef LWS_NO_CLIENT\n+\tchar chunk_parser; /* enum lws_chunk_parser */\n+#endif\n };\n \n LWS_EXTERN int log_level;\ndiff --git a/lib/service.c b/lib/service.c\nindex ee872fe..9acdcb1 100644\n--- a/lib/service.c\n+++ b/lib/service.c\n@@ -760,24 +760,110 @@ read:\n \t\t */\n drain:\n \t\tif (wsi-\u003emode \u003d\u003d LWSCM_HTTP_CLIENT_ACCEPTED) {\n-\t\t\tlwsl_notice(\u0022%s: calling LWS_CALLBACK_RECEIVE_CLIENT_HTTP, \u0022\n-\t\t\t\t \u0022rem %d len %d\u005cn\u0022, __func__,\n-\t\t\t\t wsi-\u003eu.http.content_remain, eff_buf.token_len);\n-\t\t\tif ((int)wsi-\u003eu.http.content_remain \u003c eff_buf.token_len)\n+\t\t\t/*\n+\t\t\t * server may insist on transfer-encoding: chunked,\n+\t\t\t * so http client must deal with it\n+\t\t\t */\n+spin_chunks:\n+\t\t\twhile (wsi-\u003echunked \u0026\u0026\n+\t\t\t (wsi-\u003echunk_parser !\u003d ELCP_CONTENT) \u0026\u0026\n+\t\t\t eff_buf.token_len) {\n+\t\t\t\tswitch (wsi-\u003echunk_parser) {\n+\t\t\t\tcase ELCP_HEX:\n+\t\t\t\t\tif (eff_buf.token[0] \u003d\u003d '\u005cx0d') {\n+\t\t\t\t\t\twsi-\u003echunk_parser \u003d ELCP_CR;\n+\t\t\t\t\t\tbreak;\n+\t\t\t\t\t}\n+\t\t\t\t\tn \u003d char_to_hex(eff_buf.token[0]);\n+\t\t\t\t\tif (n \u003c 0)\n+\t\t\t\t\t\tgoto close_and_handled;\n+\t\t\t\t\twsi-\u003echunk_remaining \u003c\u003c\u003d 4;\n+\t\t\t\t\twsi-\u003echunk_remaining |\u003d n;\n+\t\t\t\t\tbreak;\n+\t\t\t\tcase ELCP_CR:\n+\t\t\t\t\tif (eff_buf.token[0] !\u003d '\u005cx0a')\n+\t\t\t\t\t\tgoto close_and_handled;\n+\t\t\t\t\twsi-\u003echunk_parser \u003d ELCP_CONTENT;\n+\t\t\t\t\tlwsl_info(\u0022chunk %d\u005cn\u0022,\n+\t\t\t\t\t\t wsi-\u003echunk_remaining);\n+\t\t\t\t\tif (wsi-\u003echunk_remaining)\n+\t\t\t\t\t\tbreak;\n+\t\t\t\t\tlwsl_info(\u0022final chunk\u005cn\u0022);\n+\t\t\t\t\tif (user_callback_handle_rxflow(\n+\t\t\t\t\t\t wsi-\u003eprotocol-\u003ecallback,\n+\t\t\t\t\t\t wsi, LWS_CALLBACK_COMPLETED_CLIENT_HTTP,\n+\t\t\t\t\t\t wsi-\u003euser_space, NULL, 0))\n+\t\t\t\t\t\tgoto close_and_handled;\n+\t\t\t\t\tif (lws_http_transaction_completed(wsi))\n+\t\t\t\t\t\tgoto close_and_handled;\n+\t\t\t\t\tn \u003d 0;\n+\t\t\t\t\tgoto handled;\n+\n+\t\t\t\tcase ELCP_CONTENT:\n+\t\t\t\t\tbreak;\n+\n+\t\t\t\tcase ELCP_POST_CR:\n+\t\t\t\t\tif (eff_buf.token[0] \u003d\u003d '\u005cx0d') {\n+\t\t\t\t\t\twsi-\u003echunk_parser \u003d ELCP_POST_LF;\n+\t\t\t\t\t\tbreak;\n+\t\t\t\t\t}\n+\t\t\t\t\tgoto close_and_handled;\n+\n+\t\t\t\tcase ELCP_POST_LF:\n+\t\t\t\t\tif (eff_buf.token[0] \u003d\u003d '\u005cx0a') {\n+\t\t\t\t\t\twsi-\u003echunk_parser \u003d ELCP_HEX;\n+\t\t\t\t\t\twsi-\u003echunk_remaining \u003d 0;\n+\t\t\t\t\t\tbreak;\n+\t\t\t\t\t}\n+\t\t\t\t\tgoto close_and_handled;\n+\t\t\t\t}\n+\t\t\t\teff_buf.token++;\n+\t\t\t\teff_buf.token_len--;\n+\t\t\t}\n+\n+\t\t\tif (wsi-\u003echunked \u0026\u0026 !wsi-\u003echunk_remaining) {\n+\t\t\t\tn \u003d 0;\n+\t\t\t\tgoto handled;\n+\t\t\t}\n+\n+\t\t\tif (wsi-\u003eu.http.content_remain \u0026\u0026\n+\t\t\t wsi-\u003eu.http.content_remain \u003c eff_buf.token_len)\n \t\t\t\tn \u003d wsi-\u003eu.http.content_remain;\n \t\t\telse\n \t\t\t\tn \u003d eff_buf.token_len;\n+\n+\t\t\tif (wsi-\u003echunked \u0026\u0026 wsi-\u003echunk_remaining \u0026\u0026\n+\t\t\t wsi-\u003echunk_remaining \u003c n)\n+\t\t\t\tn \u003d wsi-\u003echunk_remaining;\n+\n \t\t\tif (user_callback_handle_rxflow(wsi-\u003eprotocol-\u003ecallback,\n \t\t\t\t\twsi, LWS_CALLBACK_RECEIVE_CLIENT_HTTP,\n \t\t\t\t\twsi-\u003euser_space, (void *)eff_buf.token,\n-\t\t\t\t\teff_buf.token_len))\n+\t\t\t\t\tn))\n \t\t\t\tgoto close_and_handled;\n+\n+\t\t\tif (wsi-\u003echunked \u0026\u0026 wsi-\u003echunk_remaining) {\n+\t\t\t\teff_buf.token +\u003d n;\n+\t\t\t\twsi-\u003echunk_remaining -\u003d n;\n+\t\t\t\teff_buf.token_len -\u003d n;\n+\t\t\t}\n+\n+\t\t\tif (wsi-\u003echunked \u0026\u0026 !wsi-\u003echunk_remaining)\n+\t\t\t\twsi-\u003echunk_parser \u003d ELCP_POST_CR;\n+\n+\t\t\tif (wsi-\u003echunked \u0026\u0026 eff_buf.token_len) {\n+\t\t\t\tgoto spin_chunks;\n+\t\t\t}\n+\n+\t\t\tif (wsi-\u003echunked) {\n+\t\t\t\tn \u003d 0;\n+\t\t\t\tgoto handled;\n+\t\t\t}\n+\n \t\t\twsi-\u003eu.http.content_remain -\u003d n;\n \t\t\tif (wsi-\u003eu.http.content_remain)\n \t\t\t\tgoto handled;\n \n-\t\t\tlwsl_notice(\u0022%s: client http receved all content\u005cn\u0022,\n-\t\t\t\t __func__);\n \t\t\tif (user_callback_handle_rxflow(wsi-\u003eprotocol-\u003ecallback,\n \t\t\t\t\twsi, LWS_CALLBACK_COMPLETED_CLIENT_HTTP,\n \t\t\t\t\twsi-\u003euser_space, NULL, 0))\n@@ -821,7 +907,7 @@ drain:\n \t\t} while (more);\n \n \t\tif (wsi-\u003eu.hdr.ah) {\n-\t\t\tlwsl_err(\u0022%s: %p: detaching inherited used ah\u005cn\u0022,\n+\t\t\tlwsl_info(\u0022%s: %p: detaching inherited used ah\u005cn\u0022,\n \t\t\t\t __func__, wsi);\n \t\t\t/* show we used all the pending rx up */\n \t\t\twsi-\u003eu.hdr.ah-\u003erxpos \u003d wsi-\u003eu.hdr.ah-\u003erxlen;\n","s":{"c":1750141416,"u": 8989}} ],"g": 11227,"chitpc": 0,"ehitpc": 0,"indexed":0 , "ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}