dummy-callback.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  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. #include "private-lib-core.h"
  25. /* max individual proxied header payload size */
  26. #define MAXHDRVAL 1024
  27. #if defined(LWS_WITH_HTTP_PROXY)
  28. static int
  29. proxy_header(struct lws *wsi, struct lws *par, unsigned char *temp,
  30. int temp_len, int index, unsigned char **p, unsigned char *end)
  31. {
  32. int n = lws_hdr_total_length(par, index);
  33. if (n < 1) {
  34. lwsl_debug("%s: no index %d:\n", __func__, index);
  35. return 0;
  36. }
  37. if (lws_hdr_copy(par, (char *)temp, temp_len, index) < 0) {
  38. lwsl_notice("%s: unable to copy par hdr idx %d (len %d)\n",
  39. __func__, index, n);
  40. return -1;
  41. }
  42. lwsl_debug("%s: index %d: %s\n", __func__, index, (char *)temp);
  43. if (lws_add_http_header_by_token(wsi, index, temp, n, p, end)) {
  44. lwsl_notice("%s: unable to append par hdr idx %d (len %d)\n",
  45. __func__, index, n);
  46. return -1;
  47. }
  48. return 0;
  49. }
  50. static int
  51. stream_close(struct lws *wsi)
  52. {
  53. char buf[LWS_PRE + 6], *out = buf + LWS_PRE;
  54. if (wsi->http.did_stream_close)
  55. return 0;
  56. wsi->http.did_stream_close = 1;
  57. if (wsi->mux_substream) {
  58. if (lws_write(wsi, (unsigned char *)buf + LWS_PRE, 0,
  59. LWS_WRITE_HTTP_FINAL) < 0) {
  60. lwsl_info("%s: COMPL_CLIENT_HTTP: h2 fin wr failed\n",
  61. __func__);
  62. return -1;
  63. }
  64. } else {
  65. *out++ = '0';
  66. *out++ = '\x0d';
  67. *out++ = '\x0a';
  68. *out++ = '\x0d';
  69. *out++ = '\x0a';
  70. if (lws_write(wsi, (unsigned char *)buf + LWS_PRE, 5,
  71. LWS_WRITE_HTTP_FINAL) < 0) {
  72. lwsl_err("%s: COMPL_CLIENT_HTTP: "
  73. "h2 final write failed\n", __func__);
  74. return -1;
  75. }
  76. }
  77. return 0;
  78. }
  79. #endif
  80. struct lws_proxy_pkt {
  81. struct lws_dll2 pkt_list;
  82. size_t len;
  83. char binary;
  84. char first;
  85. char final;
  86. /* data follows */
  87. };
  88. #if defined(LWS_WITH_HTTP_PROXY) && defined(LWS_ROLE_WS)
  89. int
  90. lws_callback_ws_proxy(struct lws *wsi, enum lws_callback_reasons reason,
  91. void *user, void *in, size_t len)
  92. {
  93. struct lws_proxy_pkt *pkt;
  94. struct lws_dll2 *dll;
  95. switch (reason) {
  96. /* h1 ws proxying... child / client / onward */
  97. case LWS_CALLBACK_CLIENT_ESTABLISHED:
  98. if (!wsi->h1_ws_proxied || !wsi->parent)
  99. break;
  100. if (lws_process_ws_upgrade2(wsi->parent))
  101. return -1;
  102. #if defined(LWS_WITH_HTTP2)
  103. if (wsi->parent->mux_substream)
  104. lwsl_info("%s: proxied h2 -> h1 ws established\n", __func__);
  105. #endif
  106. break;
  107. case LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:
  108. return 1;
  109. case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
  110. case LWS_CALLBACK_CLIENT_CLOSED:
  111. lwsl_info("%s: client closed: parent %p\n", __func__, wsi->parent);
  112. if (wsi->parent)
  113. lws_set_timeout(wsi->parent, 1, LWS_TO_KILL_ASYNC);
  114. break;
  115. case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
  116. {
  117. unsigned char **p = (unsigned char **)in, *end = (*p) + len,
  118. tmp[MAXHDRVAL];
  119. proxy_header(wsi, wsi->parent, tmp, sizeof(tmp),
  120. WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, p, end);
  121. proxy_header(wsi, wsi->parent, tmp, sizeof(tmp),
  122. WSI_TOKEN_HTTP_COOKIE, p, end);
  123. proxy_header(wsi, wsi->parent, tmp, sizeof(tmp),
  124. WSI_TOKEN_HTTP_SET_COOKIE, p, end);
  125. break;
  126. }
  127. case LWS_CALLBACK_CLIENT_RECEIVE:
  128. wsi->parent->ws->proxy_buffered += len;
  129. if (wsi->parent->ws->proxy_buffered > 10 * 1024 * 1024) {
  130. lwsl_err("%s: proxied ws connection excessive buffering: dropping\n",
  131. __func__);
  132. return -1;
  133. }
  134. pkt = lws_zalloc(sizeof(*pkt) + LWS_PRE + len, __func__);
  135. if (!pkt)
  136. return -1;
  137. pkt->len = len;
  138. pkt->first = lws_is_first_fragment(wsi);
  139. pkt->final = lws_is_final_fragment(wsi);
  140. pkt->binary = lws_frame_is_binary(wsi);
  141. memcpy(((uint8_t *)&pkt[1]) + LWS_PRE, in, len);
  142. lws_dll2_add_tail(&pkt->pkt_list, &wsi->parent->ws->proxy_owner);
  143. lws_callback_on_writable(wsi->parent);
  144. break;
  145. case LWS_CALLBACK_CLIENT_WRITEABLE:
  146. dll = lws_dll2_get_head(&wsi->ws->proxy_owner);
  147. if (!dll)
  148. break;
  149. pkt = (struct lws_proxy_pkt *)dll;
  150. if (lws_write(wsi, ((unsigned char *)&pkt[1]) +
  151. LWS_PRE, pkt->len, lws_write_ws_flags(
  152. pkt->binary ? LWS_WRITE_BINARY : LWS_WRITE_TEXT,
  153. pkt->first, pkt->final)) < 0)
  154. return -1;
  155. lws_dll2_remove(dll);
  156. lws_free(pkt);
  157. if (lws_dll2_get_head(&wsi->ws->proxy_owner))
  158. lws_callback_on_writable(wsi);
  159. break;
  160. /* h1 ws proxying... parent / server / incoming */
  161. case LWS_CALLBACK_CONFIRM_EXTENSION_OKAY:
  162. return 1;
  163. case LWS_CALLBACK_CLOSED:
  164. lwsl_info("%s: closed\n", __func__);
  165. return -1;
  166. case LWS_CALLBACK_RECEIVE:
  167. pkt = lws_zalloc(sizeof(*pkt) + LWS_PRE + len, __func__);
  168. if (!pkt)
  169. return -1;
  170. pkt->len = len;
  171. pkt->first = lws_is_first_fragment(wsi);
  172. pkt->final = lws_is_final_fragment(wsi);
  173. pkt->binary = lws_frame_is_binary(wsi);
  174. memcpy(((uint8_t *)&pkt[1]) + LWS_PRE, in, len);
  175. lws_dll2_add_tail(&pkt->pkt_list, &wsi->child_list->ws->proxy_owner);
  176. lws_callback_on_writable(wsi->child_list);
  177. break;
  178. case LWS_CALLBACK_SERVER_WRITEABLE:
  179. dll = lws_dll2_get_head(&wsi->ws->proxy_owner);
  180. if (!dll)
  181. break;
  182. pkt = (struct lws_proxy_pkt *)dll;
  183. if (lws_write(wsi, ((unsigned char *)&pkt[1]) +
  184. LWS_PRE, pkt->len, lws_write_ws_flags(
  185. pkt->binary ? LWS_WRITE_BINARY : LWS_WRITE_TEXT,
  186. pkt->first, pkt->final)) < 0)
  187. return -1;
  188. wsi->ws->proxy_buffered -= pkt->len;
  189. lws_dll2_remove(dll);
  190. lws_free(pkt);
  191. if (lws_dll2_get_head(&wsi->ws->proxy_owner))
  192. lws_callback_on_writable(wsi);
  193. break;
  194. default:
  195. return 0;
  196. }
  197. return 0;
  198. }
  199. const struct lws_protocols lws_ws_proxy = {
  200. "lws-ws-proxy",
  201. lws_callback_ws_proxy,
  202. 0,
  203. 8192,
  204. 8192, NULL, 0
  205. };
  206. #endif
  207. int
  208. lws_callback_http_dummy(struct lws *wsi, enum lws_callback_reasons reason,
  209. void *user, void *in, size_t len)
  210. {
  211. struct lws_ssl_info *si;
  212. #ifdef LWS_WITH_CGI
  213. struct lws_cgi_args *args;
  214. #endif
  215. #if defined(LWS_WITH_CGI) || defined(LWS_WITH_HTTP_PROXY)
  216. char buf[LWS_PRE + 32 + 8192];
  217. int n;
  218. #endif
  219. #if defined(LWS_WITH_HTTP_PROXY)
  220. unsigned char **p, *end;
  221. struct lws *parent;
  222. #endif
  223. switch (reason) {
  224. #if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2)
  225. case LWS_CALLBACK_HTTP:
  226. #if defined(LWS_WITH_SERVER)
  227. if (lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL))
  228. return -1;
  229. if (lws_http_transaction_completed(wsi))
  230. #endif
  231. return -1;
  232. break;
  233. #if defined(LWS_WITH_SERVER)
  234. case LWS_CALLBACK_HTTP_BODY_COMPLETION:
  235. #if defined(LWS_WITH_HTTP_PROXY)
  236. if (wsi->child_list) {
  237. lwsl_user("%s: LWS_CALLBACK_HTTP_BODY_COMPLETION: %d\n", __func__, (int)len);
  238. break;
  239. }
  240. #endif
  241. /* fallthru */
  242. case LWS_CALLBACK_HTTP_FILE_COMPLETION:
  243. if (lws_http_transaction_completed(wsi))
  244. return -1;
  245. break;
  246. #endif
  247. #if defined(LWS_WITH_HTTP_PROXY)
  248. case LWS_CALLBACK_HTTP_BODY:
  249. if (wsi->child_list) {
  250. lwsl_user("%s: LWS_CALLBACK_HTTP_BODY: stashing %d\n", __func__, (int)len);
  251. if (lws_buflist_append_segment(&wsi->http.buflist_post_body, in, len) < 0)
  252. return -1;
  253. lws_callback_on_writable(wsi->child_list);
  254. }
  255. break;
  256. #endif
  257. case LWS_CALLBACK_HTTP_WRITEABLE:
  258. // lwsl_err("%s: LWS_CALLBACK_HTTP_WRITEABLE\n", __func__);
  259. #ifdef LWS_WITH_CGI
  260. if (wsi->reason_bf & (LWS_CB_REASON_AUX_BF__CGI_HEADERS |
  261. LWS_CB_REASON_AUX_BF__CGI)) {
  262. n = lws_cgi_write_split_stdout_headers(wsi);
  263. if (n < 0) {
  264. lwsl_debug("AUX_BF__CGI forcing close\n");
  265. return -1;
  266. }
  267. if (!n && wsi->http.cgi && wsi->http.cgi->lsp &&
  268. wsi->http.cgi->lsp->stdwsi[LWS_STDOUT])
  269. lws_rx_flow_control(
  270. wsi->http.cgi->lsp->stdwsi[LWS_STDOUT], 1);
  271. if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_HEADERS)
  272. wsi->reason_bf &=
  273. ~LWS_CB_REASON_AUX_BF__CGI_HEADERS;
  274. else
  275. wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__CGI;
  276. if (wsi->http.cgi && wsi->http.cgi->cgi_transaction_over) {
  277. lwsl_info("%s: txn over\n", __func__);
  278. return -1;
  279. }
  280. break;
  281. }
  282. if ((wsi->http.cgi && wsi->http.cgi->cgi_transaction_over) ||
  283. (wsi->reason_bf & LWS_CB_REASON_AUX_BF__CGI_CHUNK_END)) {
  284. if (!wsi->mux_substream) {
  285. memcpy(buf + LWS_PRE, "0\x0d\x0a\x0d\x0a", 5);
  286. lwsl_debug("writing chunk term and exiting\n");
  287. lws_write(wsi, (unsigned char *)buf +
  288. LWS_PRE, 5, LWS_WRITE_HTTP);
  289. } else
  290. lws_write(wsi, (unsigned char *)buf +
  291. LWS_PRE, 0,
  292. LWS_WRITE_HTTP_FINAL);
  293. /* always close after sending it */
  294. if (lws_http_transaction_completed(wsi))
  295. return -1;
  296. return 0;
  297. }
  298. #endif
  299. #if defined(LWS_WITH_HTTP_PROXY)
  300. if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__PROXY_HEADERS) {
  301. wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__PROXY_HEADERS;
  302. n = LWS_WRITE_HTTP_HEADERS;
  303. if (!wsi->http.prh_content_length)
  304. n |= LWS_WRITE_H2_STREAM_END;
  305. lwsl_debug("%s: %p: issuing proxy headers: clen %d\n",
  306. __func__, wsi, (int)wsi->http.prh_content_length);
  307. n = lws_write(wsi, wsi->http.pending_return_headers +
  308. LWS_PRE,
  309. wsi->http.pending_return_headers_len, n);
  310. lws_free_set_NULL(wsi->http.pending_return_headers);
  311. if (n < 0) {
  312. lwsl_err("%s: EST_CLIENT_HTTP: write failed\n",
  313. __func__);
  314. return -1;
  315. }
  316. lws_callback_on_writable(wsi);
  317. break;
  318. }
  319. if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__PROXY) {
  320. char *px = buf + LWS_PRE;
  321. int lenx = sizeof(buf) - LWS_PRE - 32;
  322. /*
  323. * our sink is writeable and our source has something
  324. * to read. So read a lump of source material of
  325. * suitable size to send or what's available, whichever
  326. * is the smaller.
  327. */
  328. wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__PROXY;
  329. if (!lws_get_child(wsi))
  330. break;
  331. /* this causes LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ */
  332. if (lws_http_client_read(lws_get_child(wsi), &px,
  333. &lenx) < 0) {
  334. lwsl_info("%s: LWS_CB_REASON_AUX_BF__PROXY: "
  335. "client closed\n", __func__);
  336. stream_close(wsi);
  337. return -1;
  338. }
  339. break;
  340. }
  341. if (wsi->reason_bf & LWS_CB_REASON_AUX_BF__PROXY_TRANS_END) {
  342. lwsl_info("%s: LWS_CB_REASON_AUX_BF__PROXY_TRANS_END\n",
  343. __func__);
  344. wsi->reason_bf &= ~LWS_CB_REASON_AUX_BF__PROXY_TRANS_END;
  345. if (stream_close(wsi))
  346. return -1;
  347. if (lws_http_transaction_completed(wsi))
  348. return -1;
  349. }
  350. #endif
  351. break;
  352. #if defined(LWS_WITH_HTTP_PROXY)
  353. case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
  354. assert(lws_get_parent(wsi));
  355. if (!lws_get_parent(wsi))
  356. break;
  357. lws_get_parent(wsi)->reason_bf |= LWS_CB_REASON_AUX_BF__PROXY;
  358. lws_callback_on_writable(lws_get_parent(wsi));
  359. break;
  360. case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: {
  361. char *out = buf + LWS_PRE;
  362. assert(lws_get_parent(wsi));
  363. if (wsi->http.proxy_parent_chunked) {
  364. if (len > sizeof(buf) - LWS_PRE - 16) {
  365. lwsl_err("oversize buf %d %d\n", (int)len,
  366. (int)sizeof(buf) - LWS_PRE - 16);
  367. return -1;
  368. }
  369. /*
  370. * this only needs dealing with on http/1.1 to allow
  371. * pipelining
  372. */
  373. n = lws_snprintf(out, 14, "%X\x0d\x0a", (int)len);
  374. out += n;
  375. memcpy(out, in, len);
  376. out += len;
  377. *out++ = '\x0d';
  378. *out++ = '\x0a';
  379. n = lws_write(lws_get_parent(wsi),
  380. (unsigned char *)buf + LWS_PRE,
  381. len + n + 2, LWS_WRITE_HTTP);
  382. } else
  383. n = lws_write(lws_get_parent(wsi), (unsigned char *)in,
  384. len, LWS_WRITE_HTTP);
  385. if (n < 0)
  386. return -1;
  387. break; }
  388. /* h1 http proxying... */
  389. case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: {
  390. unsigned char *start, *p, *end;
  391. /*
  392. * We want to proxy these headers, but we are being called
  393. * at the point the onward client was established, which is
  394. * unrelated to the state or writability of our proxy
  395. * connection.
  396. *
  397. * Therefore produce the headers using the onward client ah
  398. * while we have it, and stick them on the output buflist to be
  399. * written on the proxy connection as soon as convenient.
  400. */
  401. parent = lws_get_parent(wsi);
  402. if (!parent)
  403. return 0;
  404. start = p = (unsigned char *)buf + LWS_PRE;
  405. end = p + sizeof(buf) - LWS_PRE - MAXHDRVAL;
  406. if (lws_add_http_header_status(lws_get_parent(wsi),
  407. lws_http_client_http_response(wsi), &p, end))
  408. return 1;
  409. /*
  410. * copy these headers from the client connection to the parent
  411. */
  412. proxy_header(parent, wsi, end, MAXHDRVAL,
  413. WSI_TOKEN_HTTP_CONTENT_LENGTH, &p, end);
  414. proxy_header(parent, wsi, end, MAXHDRVAL,
  415. WSI_TOKEN_HTTP_CONTENT_TYPE, &p, end);
  416. proxy_header(parent, wsi, end, MAXHDRVAL,
  417. WSI_TOKEN_HTTP_ETAG, &p, end);
  418. proxy_header(parent, wsi, end, MAXHDRVAL,
  419. WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, &p, end);
  420. proxy_header(parent, wsi, end, MAXHDRVAL,
  421. WSI_TOKEN_HTTP_CONTENT_ENCODING, &p, end);
  422. proxy_header(parent, wsi, end, MAXHDRVAL,
  423. WSI_TOKEN_HTTP_CACHE_CONTROL, &p, end);
  424. proxy_header(parent, wsi, end, MAXHDRVAL,
  425. WSI_TOKEN_HTTP_SET_COOKIE, &p, end);
  426. proxy_header(parent, wsi, end, MAXHDRVAL,
  427. WSI_TOKEN_HTTP_LOCATION, &p, end);
  428. if (!parent->mux_substream)
  429. if (lws_add_http_header_by_token(parent,
  430. WSI_TOKEN_CONNECTION, (unsigned char *)"close",
  431. 5, &p, end))
  432. return -1;
  433. /*
  434. * We proxy using h1 only atm, and strip any chunking so it
  435. * can go back out on h2 just fine.
  436. *
  437. * However if we are actually going out on h1, we need to add
  438. * our own chunking since we still don't know the size.
  439. */
  440. if (!parent->mux_substream &&
  441. !lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH)) {
  442. lwsl_debug("downstream parent chunked\n");
  443. if (lws_add_http_header_by_token(parent,
  444. WSI_TOKEN_HTTP_TRANSFER_ENCODING,
  445. (unsigned char *)"chunked", 7, &p, end))
  446. return -1;
  447. wsi->http.proxy_parent_chunked = 1;
  448. }
  449. if (lws_finalize_http_header(parent, &p, end))
  450. return 1;
  451. parent->http.prh_content_length = -1;
  452. if (lws_hdr_simple_ptr(wsi, WSI_TOKEN_HTTP_CONTENT_LENGTH))
  453. parent->http.prh_content_length = atoll(
  454. lws_hdr_simple_ptr(wsi,
  455. WSI_TOKEN_HTTP_CONTENT_LENGTH));
  456. parent->http.pending_return_headers_len = lws_ptr_diff(p, start);
  457. parent->http.pending_return_headers =
  458. lws_malloc(parent->http.pending_return_headers_len +
  459. LWS_PRE, "return proxy headers");
  460. if (!parent->http.pending_return_headers)
  461. return -1;
  462. memcpy(parent->http.pending_return_headers + LWS_PRE, start,
  463. parent->http.pending_return_headers_len);
  464. parent->reason_bf |= LWS_CB_REASON_AUX_BF__PROXY_HEADERS;
  465. lwsl_debug("%s: LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: "
  466. "prepared %d headers (len %d)\n", __func__,
  467. lws_http_client_http_response(wsi),
  468. (int)parent->http.prh_content_length);
  469. /*
  470. * so at this point, the onward client connection can bear
  471. * traffic. We might be doing a POST and have pending cached
  472. * inbound stuff to send, it can go now.
  473. */
  474. lws_callback_on_writable(parent);
  475. break; }
  476. case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
  477. lwsl_info("%s: COMPLETED_CLIENT_HTTP: %p (parent %p)\n",
  478. __func__, wsi, lws_get_parent(wsi));
  479. if (!lws_get_parent(wsi))
  480. break;
  481. lws_get_parent(wsi)->reason_bf |=
  482. LWS_CB_REASON_AUX_BF__PROXY_TRANS_END;
  483. lws_callback_on_writable(lws_get_parent(wsi));
  484. break;
  485. case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
  486. if (!lws_get_parent(wsi))
  487. break;
  488. // lwsl_err("%s: LWS_CALLBACK_CLOSED_CLIENT_HTTP\n", __func__);
  489. lws_set_timeout(lws_get_parent(wsi), LWS_TO_KILL_ASYNC,
  490. PENDING_TIMEOUT_KILLED_BY_PROXY_CLIENT_CLOSE);
  491. break;
  492. case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
  493. parent = lws_get_parent(wsi);
  494. if (!parent)
  495. break;
  496. p = (unsigned char **)in;
  497. end = (*p) + len;
  498. /*
  499. * copy these headers from the parent request to the client
  500. * connection's request
  501. */
  502. proxy_header(wsi, parent, (unsigned char *)buf, sizeof(buf),
  503. WSI_TOKEN_HTTP_ETAG, p, end);
  504. proxy_header(wsi, parent, (unsigned char *)buf, sizeof(buf),
  505. WSI_TOKEN_HTTP_IF_MODIFIED_SINCE, p, end);
  506. proxy_header(wsi, parent, (unsigned char *)buf, sizeof(buf),
  507. WSI_TOKEN_HTTP_ACCEPT_LANGUAGE, p, end);
  508. proxy_header(wsi, parent, (unsigned char *)buf, sizeof(buf),
  509. WSI_TOKEN_HTTP_ACCEPT_ENCODING, p, end);
  510. proxy_header(wsi, parent, (unsigned char *)buf, sizeof(buf),
  511. WSI_TOKEN_HTTP_CACHE_CONTROL, p, end);
  512. proxy_header(wsi, parent, (unsigned char *)buf, sizeof(buf),
  513. WSI_TOKEN_HTTP_COOKIE, p, end);
  514. buf[0] = '\0';
  515. lws_get_peer_simple(parent, buf, sizeof(buf));
  516. if (lws_add_http_header_by_token(wsi, WSI_TOKEN_X_FORWARDED_FOR,
  517. (unsigned char *)buf, (int)strlen(buf), p, end))
  518. return -1;
  519. break;
  520. #endif
  521. #ifdef LWS_WITH_CGI
  522. /* CGI IO events (POLLIN/OUT) appear here, our default policy is:
  523. *
  524. * - POST data goes on subprocess stdin
  525. * - subprocess stdout goes on http via writeable callback
  526. * - subprocess stderr goes to the logs
  527. */
  528. case LWS_CALLBACK_CGI:
  529. args = (struct lws_cgi_args *)in;
  530. switch (args->ch) { /* which of stdin/out/err ? */
  531. case LWS_STDIN:
  532. /* TBD stdin rx flow control */
  533. break;
  534. case LWS_STDOUT:
  535. if (args->stdwsi[LWS_STDOUT])
  536. /* quench POLLIN on STDOUT until MASTER got writeable */
  537. lws_rx_flow_control(args->stdwsi[LWS_STDOUT], 0);
  538. wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI;
  539. /* when writing to MASTER would not block */
  540. lws_callback_on_writable(wsi);
  541. break;
  542. case LWS_STDERR:
  543. n = lws_get_socket_fd(args->stdwsi[LWS_STDERR]);
  544. if (n < 0)
  545. break;
  546. n = read(n, buf, sizeof(buf) - 2);
  547. if (n > 0) {
  548. if (buf[n - 1] != '\n')
  549. buf[n++] = '\n';
  550. buf[n] = '\0';
  551. lwsl_notice("CGI-stderr: %s\n", buf);
  552. }
  553. break;
  554. }
  555. break;
  556. case LWS_CALLBACK_CGI_TERMINATED:
  557. lwsl_debug("LWS_CALLBACK_CGI_TERMINATED: %d %" PRIu64 "\n",
  558. wsi->http.cgi->explicitly_chunked,
  559. (uint64_t)wsi->http.cgi->content_length);
  560. if (!(wsi->http.cgi->explicitly_chunked && wsi->mux_substream) &&
  561. !wsi->http.cgi->content_length) {
  562. /* send terminating chunk */
  563. lwsl_debug("LWS_CALLBACK_CGI_TERMINATED: ending\n");
  564. wsi->reason_bf |= LWS_CB_REASON_AUX_BF__CGI_CHUNK_END;
  565. lws_callback_on_writable(wsi);
  566. lws_set_timeout(wsi, PENDING_TIMEOUT_CGI, 3);
  567. break;
  568. }
  569. if (wsi->mux_substream && !wsi->cgi_stdout_zero_length)
  570. lws_write(wsi, (unsigned char *)buf + LWS_PRE, 0,
  571. LWS_WRITE_HTTP_FINAL);
  572. if (lws_http_transaction_completed(wsi))
  573. return -1;
  574. return 0;
  575. case LWS_CALLBACK_CGI_STDIN_DATA: /* POST body for stdin */
  576. args = (struct lws_cgi_args *)in;
  577. args->data[args->len] = '\0';
  578. if (!args->stdwsi[LWS_STDIN])
  579. return -1;
  580. n = lws_get_socket_fd(args->stdwsi[LWS_STDIN]);
  581. if (n < 0)
  582. return -1;
  583. #if defined(LWS_WITH_ZLIB)
  584. if (wsi->http.cgi->gzip_inflate) {
  585. /* gzip handling */
  586. if (!wsi->http.cgi->gzip_init) {
  587. lwsl_info("inflating gzip\n");
  588. memset(&wsi->http.cgi->inflate, 0,
  589. sizeof(wsi->http.cgi->inflate));
  590. if (inflateInit2(&wsi->http.cgi->inflate,
  591. 16 + 15) != Z_OK) {
  592. lwsl_err("%s: iniflateInit failed\n",
  593. __func__);
  594. return -1;
  595. }
  596. wsi->http.cgi->gzip_init = 1;
  597. }
  598. wsi->http.cgi->inflate.next_in = args->data;
  599. wsi->http.cgi->inflate.avail_in = args->len;
  600. do {
  601. wsi->http.cgi->inflate.next_out =
  602. wsi->http.cgi->inflate_buf;
  603. wsi->http.cgi->inflate.avail_out =
  604. sizeof(wsi->http.cgi->inflate_buf);
  605. n = inflate(&wsi->http.cgi->inflate,
  606. Z_SYNC_FLUSH);
  607. switch (n) {
  608. case Z_NEED_DICT:
  609. case Z_STREAM_ERROR:
  610. case Z_DATA_ERROR:
  611. case Z_MEM_ERROR:
  612. inflateEnd(&wsi->http.cgi->inflate);
  613. wsi->http.cgi->gzip_init = 0;
  614. lwsl_err("zlib error inflate %d\n", n);
  615. return -1;
  616. }
  617. if (wsi->http.cgi->inflate.avail_out !=
  618. sizeof(wsi->http.cgi->inflate_buf)) {
  619. int written;
  620. written = write(args->stdwsi[LWS_STDIN]->desc.filefd,
  621. wsi->http.cgi->inflate_buf,
  622. sizeof(wsi->http.cgi->inflate_buf) -
  623. wsi->http.cgi->inflate.avail_out);
  624. if (written != (int)(
  625. sizeof(wsi->http.cgi->inflate_buf) -
  626. wsi->http.cgi->inflate.avail_out)) {
  627. lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: "
  628. "sent %d only %d went", n, args->len);
  629. }
  630. if (n == Z_STREAM_END) {
  631. lwsl_err("gzip inflate end\n");
  632. inflateEnd(&wsi->http.cgi->inflate);
  633. wsi->http.cgi->gzip_init = 0;
  634. break;
  635. }
  636. } else
  637. break;
  638. if (wsi->http.cgi->inflate.avail_out)
  639. break;
  640. } while (1);
  641. return args->len;
  642. }
  643. #endif /* WITH_ZLIB */
  644. n = write(n, args->data, args->len);
  645. // lwsl_hexdump_notice(args->data, args->len);
  646. if (n < args->len)
  647. lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: "
  648. "sent %d only %d went", n, args->len);
  649. lwsl_notice("%s: proxied %d bytes\n", __func__, n);
  650. if (wsi->http.cgi->post_in_expected && args->stdwsi[LWS_STDIN] &&
  651. args->stdwsi[LWS_STDIN]->desc.filefd > 0) {
  652. wsi->http.cgi->post_in_expected -= n;
  653. if (!wsi->http.cgi->post_in_expected) {
  654. struct lws *siwsi = args->stdwsi[LWS_STDIN];
  655. /*
  656. * The situation here is that we finished
  657. * proxying the incoming body from the net to
  658. * the STDIN stdwsi... and we want to close it
  659. * so it can understand we are done (necessary
  660. * if no content-length)...
  661. */
  662. lwsl_notice("%s: expected POST in end: "
  663. "closing stdin wsi %p, fd %d\n",
  664. __func__, siwsi,
  665. siwsi->desc.sockfd);
  666. /*
  667. * We don't want the child / parent relationship
  668. * to be handled in close, since we want the
  669. * rest of the cgi and children to stay up
  670. */
  671. lws_remove_child_from_any_parent(siwsi);
  672. lws_wsi_close(siwsi, LWS_TO_KILL_ASYNC);
  673. wsi->http.cgi->lsp->stdwsi[LWS_STDIN] = NULL;
  674. lws_spawn_stdwsi_closed(wsi->http.cgi->lsp, siwsi);
  675. }
  676. }
  677. return n;
  678. #endif /* WITH_CGI */
  679. #endif /* ROLE_ H1 / H2 */
  680. case LWS_CALLBACK_SSL_INFO:
  681. si = in;
  682. (void)si;
  683. lwsl_notice("LWS_CALLBACK_SSL_INFO: where: 0x%x, ret: 0x%x\n",
  684. si->where, si->ret);
  685. break;
  686. #if LWS_MAX_SMP > 1
  687. case LWS_CALLBACK_GET_THREAD_ID:
  688. return (int)(lws_intptr_t)pthread_self();
  689. #endif
  690. default:
  691. break;
  692. }
  693. return 0;
  694. }