ss-h1.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2019 - 2020 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. * This is the glue that wires up h1 to Secure Streams.
  25. */
  26. #include <private-lib-core.h>
  27. #if !defined(LWS_PLAT_FREERTOS) || defined(LWS_ROLE_H2)
  28. #define LWS_WITH_SS_RIDESHARE
  29. #endif
  30. #if defined(LWS_WITH_SS_RIDESHARE)
  31. static int
  32. ss_http_multipart_parser(lws_ss_handle_t *h, void *in, size_t len)
  33. {
  34. uint8_t *q = (uint8_t *)in;
  35. int pending_issue = 0, n = 0;
  36. /* let's stick it in the boundary state machine first */
  37. while (n < (int)len) {
  38. if (h->u.http.boundary_seq != h->u.http.boundary_len) {
  39. if (q[n] == h->u.http.boundary[h->u.http.boundary_seq])
  40. h->u.http.boundary_seq++;
  41. else {
  42. h->u.http.boundary_seq = 0;
  43. h->u.http.boundary_dashes = 0;
  44. h->u.http.boundary_post = 0;
  45. }
  46. goto around;
  47. }
  48. /*
  49. * We already matched the boundary string, now we're
  50. * looking if there's a -- afterwards
  51. */
  52. if (h->u.http.boundary_dashes < 2) {
  53. if (q[n] == '-') {
  54. h->u.http.boundary_dashes++;
  55. goto around;
  56. }
  57. /* there was no final -- ... */
  58. }
  59. if (h->u.http.boundary_dashes == 2) {
  60. /*
  61. * It's an EOM boundary: issue pending + multipart EOP
  62. */
  63. lwsl_debug("%s: seen EOP, n %d pi %d\n",
  64. __func__, n, pending_issue);
  65. /*
  66. * It's possible we already started the decode before
  67. * the end of the last packet. Then there is no
  68. * remainder to send.
  69. */
  70. if (n >= pending_issue + h->u.http.boundary_len +
  71. (h->u.http.any ? 2 : 0) + 1)
  72. h->info.rx(ss_to_userobj(h),
  73. &q[pending_issue],
  74. n - pending_issue -
  75. h->u.http.boundary_len - 1 -
  76. (h->u.http.any ? 2 : 0) /* crlf */,
  77. (!h->u.http.som ? LWSSS_FLAG_SOM : 0) |
  78. LWSSS_FLAG_EOM | LWSSS_FLAG_RELATED_END);
  79. /*
  80. * Peer may not END_STREAM us
  81. */
  82. return 0;
  83. //return -1;
  84. }
  85. /* how about --boundaryCRLF */
  86. if (h->u.http.boundary_post < 2) {
  87. if ((!h->u.http.boundary_post && q[n] == '\x0d') ||
  88. (h->u.http.boundary_post && q[n] == '\x0a')) {
  89. h->u.http.boundary_post++;
  90. goto around;
  91. }
  92. /* there was no final CRLF ... it's wrong */
  93. return -1;
  94. }
  95. if (h->u.http.boundary_post != 2)
  96. goto around;
  97. /*
  98. * We have a starting "--boundaryCRLF" or intermediate
  99. * "CRLF--boundaryCRLF" boundary
  100. */
  101. lwsl_debug("%s: b_post = 2 (pi %d)\n", __func__, pending_issue);
  102. h->u.http.boundary_seq = 0;
  103. h->u.http.boundary_post = 0;
  104. if (n >= pending_issue && (h->u.http.any || !h->u.http.som)) {
  105. /* Intermediate... do the EOM */
  106. lwsl_debug("%s: seen interm EOP n %d pi %d\n", __func__,
  107. n, pending_issue);
  108. /*
  109. * It's possible we already started the decode before
  110. * the end of the last packet. Then there is no
  111. * remainder to send.
  112. */
  113. if (n >= pending_issue + h->u.http.boundary_len +
  114. (h->u.http.any ? 2 : 0))
  115. h->info.rx(ss_to_userobj(h), &q[pending_issue],
  116. n - pending_issue -
  117. h->u.http.boundary_len -
  118. (h->u.http.any ? 2 /* crlf */ : 0),
  119. (!h->u.http.som ? LWSSS_FLAG_SOM : 0) |
  120. LWSSS_FLAG_EOM);
  121. }
  122. /* Next message starts after this boundary */
  123. pending_issue = n;
  124. h->u.http.som = 0;
  125. around:
  126. n++;
  127. }
  128. if (pending_issue != n) {
  129. h->info.rx(ss_to_userobj(h), &q[pending_issue], n - pending_issue,
  130. (!h->u.http.som ? LWSSS_FLAG_SOM : 0));
  131. h->u.http.any = 1;
  132. h->u.http.som = 1;
  133. }
  134. return 0;
  135. }
  136. #endif
  137. static int
  138. lws_apply_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf,
  139. uint8_t **pp, uint8_t *end)
  140. {
  141. int m;
  142. for (m = 0; m < h->policy->metadata_count; m++) {
  143. lws_ss_metadata_t *polmd;
  144. /* has to have a header string listed */
  145. if (!h->metadata[m].value)
  146. continue;
  147. polmd = lws_ss_policy_metadata_index(h->policy, m);
  148. assert(polmd);
  149. if (!polmd)
  150. return -1;
  151. /* has to have a value */
  152. if (polmd->value && ((uint8_t *)polmd->value)[0]) {
  153. if (lws_add_http_header_by_name(wsi,
  154. polmd->value,
  155. h->metadata[m].value,
  156. (int)h->metadata[m].length, pp, end))
  157. return -1;
  158. }
  159. }
  160. /*
  161. * Content-length on POST / PUT if we have the length information
  162. */
  163. if (h->policy->u.http.method && (
  164. (!strcmp(h->policy->u.http.method, "POST") ||
  165. !strcmp(h->policy->u.http.method, "PUT"))) &&
  166. wsi->http.writeable_len) {
  167. if (!(h->policy->flags &
  168. LWSSSPOLF_HTTP_NO_CONTENT_LENGTH)) {
  169. int n = lws_snprintf((char *)buf, 20, "%u",
  170. (unsigned int)wsi->http.writeable_len);
  171. if (lws_add_http_header_by_token(wsi,
  172. WSI_TOKEN_HTTP_CONTENT_LENGTH,
  173. buf, n, pp, end))
  174. return -1;
  175. }
  176. lws_client_http_body_pending(wsi, 1);
  177. }
  178. return 0;
  179. }
  180. static const uint8_t blob_idx[] = {
  181. LWS_SYSBLOB_TYPE_AUTH,
  182. LWS_SYSBLOB_TYPE_DEVICE_SERIAL,
  183. LWS_SYSBLOB_TYPE_DEVICE_FW_VERSION,
  184. LWS_SYSBLOB_TYPE_DEVICE_TYPE,
  185. };
  186. int
  187. secstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user,
  188. void *in, size_t len)
  189. {
  190. lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi);
  191. uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE],
  192. #if defined(LWS_WITH_SERVER)
  193. *start = p,
  194. #endif
  195. *end = &buf[sizeof(buf) - 1];
  196. lws_ss_state_return_t r;
  197. int f = 0, m, status;
  198. char conceal_eom = 0;
  199. size_t buflen;
  200. switch (reason) {
  201. case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
  202. if (!h)
  203. break;
  204. assert(h->policy);
  205. lwsl_info("%s: h: %p, %s CLIENT_CONNECTION_ERROR: %s\n", __func__,
  206. h, h->policy->streamtype, in ? (char *)in : "(null)");
  207. /* already disconnected, no action for DISCONNECT_ME */
  208. r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE);
  209. if (r)
  210. return _lws_ss_handle_state_ret(r, wsi, &h);
  211. h->wsi = NULL;
  212. r = lws_ss_backoff(h);
  213. if (r != LWSSSSRET_OK)
  214. return _lws_ss_handle_state_ret(r, wsi, &h);
  215. break;
  216. case LWS_CALLBACK_CLIENT_HTTP_REDIRECT:
  217. if (h->policy->u.http.fail_redirect)
  218. lws_system_cpd_set(lws_get_context(wsi),
  219. LWS_CPD_CAPTIVE_PORTAL);
  220. /* unless it's explicitly allowed, reject to follow it */
  221. return !(h->policy->flags & LWSSSPOLF_ALLOW_REDIRECTS);
  222. case LWS_CALLBACK_CLOSED_HTTP: /* server */
  223. case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
  224. if (!h)
  225. break;
  226. lws_sul_cancel(&h->sul_timeout);
  227. lwsl_info("%s: h: %p, %s LWS_CALLBACK_CLOSED_CLIENT_HTTP\n",
  228. __func__, h,
  229. h->policy ? h->policy->streamtype : "no policy");
  230. h->wsi = NULL;
  231. if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) &&
  232. #if defined(LWS_WITH_SERVER)
  233. !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not server */
  234. #endif
  235. !h->txn_ok && !wsi->a.context->being_destroyed) {
  236. r = lws_ss_backoff(h);
  237. if (r != LWSSSSRET_OK)
  238. return _lws_ss_handle_state_ret(r, wsi, &h);
  239. break;
  240. } else
  241. h->seqstate = SSSEQ_IDLE;
  242. /* already disconnected, no action for DISCONNECT_ME */
  243. r = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED);
  244. if (r != LWSSSSRET_OK)
  245. return _lws_ss_handle_state_ret(r, wsi, &h);
  246. break;
  247. case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP:
  248. status = lws_http_client_http_response(wsi);
  249. lwsl_info("%s: LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: %d\n", __func__, status);
  250. // if (!status)
  251. /* it's just telling use we connected / joined the nwsi */
  252. // break;
  253. if (h->policy->u.http.resp_expect)
  254. h->u.http.good_respcode =
  255. status == h->policy->u.http.resp_expect;
  256. else
  257. h->u.http.good_respcode = (status >= 200 && status < 300);
  258. // lwsl_err("%s: good resp %d %d\n", __func__, status, h->u.http.good_respcode);
  259. if (h->u.http.good_respcode)
  260. lwsl_info("%s: Connected streamtype %s, %d\n", __func__,
  261. h->policy->streamtype, status);
  262. else
  263. if (h->u.http.good_respcode)
  264. lwsl_warn("%s: Connected streamtype %s, BAD %d\n",
  265. __func__, h->policy->streamtype,
  266. status);
  267. h->hanging_som = 0;
  268. h->retry = 0;
  269. h->seqstate = SSSEQ_CONNECTED;
  270. lws_sul_cancel(&h->sul);
  271. r = lws_ss_event_helper(h, LWSSSCS_CONNECTED);
  272. if (r != LWSSSSRET_OK)
  273. return _lws_ss_handle_state_ret(r, wsi, &h);
  274. /*
  275. * Since it's an http transaction we initiated... this is
  276. * proof of connection validity
  277. */
  278. lws_validity_confirmed(wsi);
  279. #if defined(LWS_WITH_SS_RIDESHARE)
  280. /*
  281. * There are two ways we might want to deal with multipart,
  282. * one is pass it through raw (although the user code needs
  283. * a helping hand for learning the boundary), and the other
  284. * is to deframe it and provide basically submessages in the
  285. * different parts.
  286. */
  287. if (lws_hdr_copy(wsi, (char *)buf, sizeof(buf),
  288. WSI_TOKEN_HTTP_CONTENT_TYPE) > 0 &&
  289. /* multipart/form-data;
  290. * boundary=----WebKitFormBoundarycc7YgAPEIHvgE9Bf */
  291. (!strncmp((char *)buf, "multipart/form-data", 19) ||
  292. !strncmp((char *)buf, "multipart/related", 17))) {
  293. struct lws_tokenize ts;
  294. lws_tokenize_elem e;
  295. // puts((const char *)buf);
  296. memset(&ts, 0, sizeof(ts));
  297. ts.start = (char *)buf;
  298. ts.len = strlen(ts.start);
  299. ts.flags = LWS_TOKENIZE_F_RFC7230_DELIMS |
  300. LWS_TOKENIZE_F_SLASH_NONTERM |
  301. LWS_TOKENIZE_F_MINUS_NONTERM;
  302. h->u.http.boundary[0] = '\0';
  303. do {
  304. e = lws_tokenize(&ts);
  305. if (e == LWS_TOKZE_TOKEN_NAME_EQUALS &&
  306. !strncmp(ts.token, "boundary", 8) &&
  307. ts.token_len == 8) {
  308. e = lws_tokenize(&ts);
  309. if (e != LWS_TOKZE_TOKEN)
  310. goto malformed;
  311. h->u.http.boundary[0] = '\x0d';
  312. h->u.http.boundary[1] = '\x0a';
  313. h->u.http.boundary[2] = '-';
  314. h->u.http.boundary[3] = '-';
  315. lws_strnncpy(h->u.http.boundary + 4,
  316. ts.token, ts.token_len,
  317. sizeof(h->u.http.boundary) - 4);
  318. h->u.http.boundary_len =
  319. (uint8_t)(ts.token_len + 4);
  320. h->u.http.boundary_seq = 2;
  321. h->u.http.boundary_dashes = 0;
  322. }
  323. } while (e > 0);
  324. lwsl_info("%s: multipart boundary '%s' len %d\n", __func__,
  325. h->u.http.boundary, h->u.http.boundary_len);
  326. /* inform the ss that a related message group begins */
  327. if ((h->policy->flags & LWSSSPOLF_HTTP_MULTIPART_IN) &&
  328. h->u.http.boundary[0])
  329. h->info.rx(ss_to_userobj(h), NULL, 0,
  330. LWSSS_FLAG_RELATED_START);
  331. // lws_header_table_detach(wsi, 0);
  332. }
  333. break;
  334. malformed:
  335. lwsl_notice("%s: malformed multipart header\n", __func__);
  336. return -1;
  337. #else
  338. break;
  339. #endif
  340. case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
  341. if (h->writeable_len)
  342. wsi->http.writeable_len = h->writeable_len;
  343. {
  344. uint8_t **p = (uint8_t **)in, *end = (*p) + len,
  345. *oin = *(uint8_t **)in;
  346. /*
  347. * blob-based headers
  348. */
  349. for (m = 0; m < _LWSSS_HBI_COUNT; m++) {
  350. lws_system_blob_t *ab;
  351. int o = 0, n;
  352. if (!h->policy->u.http.blob_header[m])
  353. continue;
  354. if (m == LWSSS_HBI_AUTH &&
  355. h->policy->u.http.auth_preamble)
  356. o = lws_snprintf((char *)buf, sizeof(buf), "%s",
  357. h->policy->u.http.auth_preamble);
  358. if (o > (int)sizeof(buf) - 2)
  359. return -1;
  360. ab = lws_system_get_blob(wsi->a.context, blob_idx[m], 0);
  361. if (!ab)
  362. return -1;
  363. buflen = sizeof(buf) - o - 2;
  364. n = lws_system_blob_get(ab, buf + o, &buflen, 0);
  365. if (n < 0)
  366. return -1;
  367. buf[o + buflen] = '\0';
  368. lwsl_debug("%s: adding blob %d: %s\n", __func__, m, buf);
  369. if (lws_add_http_header_by_name(wsi,
  370. (uint8_t *)h->policy->u.http.blob_header[m],
  371. buf, (int)(buflen + o), p, end))
  372. return -1;
  373. }
  374. /*
  375. * metadata-based headers
  376. */
  377. if (lws_apply_metadata(h, wsi, buf, p, end))
  378. return -1;
  379. (void)oin;
  380. // if (*p != oin)
  381. // lwsl_hexdump_notice(oin, lws_ptr_diff(*p, oin));
  382. }
  383. /*
  384. * So when proxied, for POST we have to synthesize a CONNECTED
  385. * state, so it can request a writeable and deliver the POST
  386. * body
  387. */
  388. if ((h->policy->protocol == LWSSSP_H1 ||
  389. h->policy->protocol == LWSSSP_H2) &&
  390. h->being_serialized && (
  391. !strcmp(h->policy->u.http.method, "PUT") ||
  392. !strcmp(h->policy->u.http.method, "POST"))) {
  393. r = lws_ss_event_helper(h, LWSSSCS_CONNECTED);
  394. if (r)
  395. return _lws_ss_handle_state_ret(r, wsi, &h);
  396. }
  397. break;
  398. /* chunks of chunked content, with header removed */
  399. case LWS_CALLBACK_HTTP_BODY:
  400. case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ:
  401. lwsl_debug("%s: RECEIVE_CLIENT_HTTP_READ: read %d\n",
  402. __func__, (int)len);
  403. if (!h || !h->info.rx)
  404. return 0;
  405. #if defined(LWS_WITH_SS_RIDESHARE)
  406. if ((h->policy->flags & LWSSSPOLF_HTTP_MULTIPART_IN) &&
  407. h->u.http.boundary[0])
  408. return ss_http_multipart_parser(h, in, len);
  409. #endif
  410. if (!h->subseq) {
  411. f |= LWSSS_FLAG_SOM;
  412. h->hanging_som = 1;
  413. h->subseq = 1;
  414. }
  415. // lwsl_notice("%s: HTTP_READ: client side sent len %d fl 0x%x\n",
  416. // __func__, (int)len, (int)f);
  417. r = h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f);
  418. if (r != LWSSSSRET_OK)
  419. return _lws_ss_handle_state_ret(r, wsi, &h);
  420. return 0; /* don't passthru */
  421. /* uninterpreted http content */
  422. case LWS_CALLBACK_RECEIVE_CLIENT_HTTP:
  423. {
  424. char *px = (char *)buf + LWS_PRE; /* guarantees LWS_PRE */
  425. int lenx = sizeof(buf) - LWS_PRE;
  426. m = lws_http_client_read(wsi, &px, &lenx);
  427. if (m < 0)
  428. return m;
  429. }
  430. lws_set_timeout(wsi, 99, 30);
  431. return 0; /* don't passthru */
  432. case LWS_CALLBACK_COMPLETED_CLIENT_HTTP:
  433. lwsl_debug("%s: LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n", __func__);
  434. if (h->hanging_som)
  435. h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_EOM);
  436. wsi->http.writeable_len = h->writeable_len = 0;
  437. lws_sul_cancel(&h->sul_timeout);
  438. h->txn_ok = 1;
  439. r = lws_ss_event_helper(h, h->u.http.good_respcode ?
  440. LWSSSCS_QOS_ACK_REMOTE :
  441. LWSSSCS_QOS_NACK_REMOTE);
  442. if (r != LWSSSSRET_OK)
  443. return _lws_ss_handle_state_ret(r, wsi, &h);
  444. lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */
  445. break;
  446. case LWS_CALLBACK_HTTP_WRITEABLE:
  447. case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE:
  448. //lwsl_info("%s: wsi %p, par %p, HTTP_WRITEABLE\n", __func__,
  449. // wsi, wsi->mux.parent_wsi);
  450. if (!h || !h->info.tx) {
  451. lwsl_notice("%s: no handle / tx %p\n", __func__, h);
  452. return 0;
  453. }
  454. #if defined(LWS_WITH_SERVER)
  455. if (h->txn_resp_pending) {
  456. /*
  457. * If we're going to start sending something, we need to
  458. * to take care of the http response header for it first
  459. */
  460. h->txn_resp_pending = 0;
  461. if (lws_add_http_common_headers(wsi,
  462. h->txn_resp_set ?
  463. (h->txn_resp ? h->txn_resp : 200) :
  464. HTTP_STATUS_NOT_FOUND,
  465. NULL, h->wsi->http.writeable_len,
  466. &p, end))
  467. return 1;
  468. /*
  469. * metadata-based headers
  470. */
  471. if (lws_apply_metadata(h, wsi, buf, &p, end))
  472. return -1;
  473. if (lws_finalize_write_http_header(wsi, start, &p, end))
  474. return 1;
  475. /* write the body separately */
  476. lws_callback_on_writable(wsi);
  477. return 0;
  478. }
  479. #endif
  480. if (
  481. #if defined(LWS_WITH_SERVER)
  482. !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not accepted */
  483. #endif
  484. !h->rideshare)
  485. h->rideshare = h->policy;
  486. #if defined(LWS_WITH_SS_RIDESHARE)
  487. if (
  488. #if defined(LWS_WITH_SERVER)
  489. !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not accepted */
  490. #endif
  491. !h->inside_msg && h->rideshare->u.http.multipart_name)
  492. lws_client_http_multipart(wsi,
  493. h->rideshare->u.http.multipart_name,
  494. h->rideshare->u.http.multipart_filename,
  495. h->rideshare->u.http.multipart_content_type,
  496. (char **)&p, (char *)end);
  497. buflen = lws_ptr_diff(end, p);
  498. if (h->policy->u.http.multipart_name)
  499. buflen -= 24; /* allow space for end of multipart */
  500. #else
  501. buflen = lws_ptr_diff(end, p);
  502. #endif
  503. r = h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f);
  504. if (r == LWSSSSRET_TX_DONT_SEND)
  505. return 0;
  506. if (r < 0)
  507. return _lws_ss_handle_state_ret(r, wsi, &h);
  508. // lwsl_notice("%s: WRITEABLE: user tx says len %d fl 0x%x\n",
  509. // __func__, (int)buflen, (int)f);
  510. p += buflen;
  511. if (f & LWSSS_FLAG_EOM) {
  512. #if defined(LWS_WITH_SERVER)
  513. if (!(h->info.flags & LWSSSINFLAGS_ACCEPTED)) {
  514. #endif
  515. conceal_eom = 1;
  516. /* end of rideshares */
  517. if (!h->rideshare->rideshare_streamtype) {
  518. lws_client_http_body_pending(wsi, 0);
  519. #if defined(LWS_WITH_SS_RIDESHARE)
  520. if (h->rideshare->u.http.multipart_name)
  521. lws_client_http_multipart(wsi, NULL, NULL, NULL,
  522. (char **)&p, (char *)end);
  523. conceal_eom = 0;
  524. #endif
  525. } else {
  526. h->rideshare = lws_ss_policy_lookup(wsi->a.context,
  527. h->rideshare->rideshare_streamtype);
  528. lws_callback_on_writable(wsi);
  529. }
  530. #if defined(LWS_WITH_SERVER)
  531. }
  532. #endif
  533. h->inside_msg = 0;
  534. } else {
  535. /* otherwise we can spin with zero length writes */
  536. if (!f && !lws_ptr_diff(p, buf + LWS_PRE))
  537. break;
  538. h->inside_msg = 1;
  539. lws_callback_on_writable(wsi);
  540. }
  541. lwsl_info("%s: lws_write %d %d\n", __func__,
  542. lws_ptr_diff(p, buf + LWS_PRE), f);
  543. if (lws_write(wsi, buf + LWS_PRE, lws_ptr_diff(p, buf + LWS_PRE),
  544. (!conceal_eom && (f & LWSSS_FLAG_EOM)) ?
  545. LWS_WRITE_HTTP_FINAL : LWS_WRITE_HTTP) !=
  546. (int)lws_ptr_diff(p, buf + LWS_PRE)) {
  547. lwsl_err("%s: write failed\n", __func__);
  548. return -1;
  549. }
  550. #if defined(LWS_WITH_SERVER)
  551. if (!(h->info.flags & LWSSSINFLAGS_ACCEPTED) &&
  552. (f & LWSSS_FLAG_EOM) &&
  553. lws_http_transaction_completed(wsi))
  554. return -1;
  555. #else
  556. lws_set_timeout(wsi, 0, 0);
  557. #endif
  558. break;
  559. #if defined(LWS_WITH_SERVER)
  560. case LWS_CALLBACK_HTTP:
  561. lwsl_notice("%s: LWS_CALLBACK_HTTP\n", __func__);
  562. {
  563. h->txn_resp_set = 0;
  564. h->txn_resp_pending = 1;
  565. h->writeable_len = 0;
  566. #if defined(LWS_ROLE_H2)
  567. m = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_METHOD);
  568. if (m) {
  569. lws_ss_set_metadata(h, "method",
  570. lws_hdr_simple_ptr(wsi,
  571. WSI_TOKEN_HTTP_COLON_METHOD), m);
  572. m = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH);
  573. lws_ss_set_metadata(h, "path",
  574. lws_hdr_simple_ptr(wsi,
  575. WSI_TOKEN_HTTP_COLON_PATH), m);
  576. } else
  577. #endif
  578. {
  579. m = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI);
  580. if (m) {
  581. lws_ss_set_metadata(h, "path",
  582. lws_hdr_simple_ptr(wsi,
  583. WSI_TOKEN_GET_URI), m);
  584. lws_ss_set_metadata(h, "method", "GET", 3);
  585. } else {
  586. m = lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI);
  587. if (m) {
  588. lws_ss_set_metadata(h, "path",
  589. lws_hdr_simple_ptr(wsi,
  590. WSI_TOKEN_POST_URI), m);
  591. lws_ss_set_metadata(h, "method", "POST", 4);
  592. }
  593. }
  594. }
  595. }
  596. r = lws_ss_event_helper(h, LWSSSCS_SERVER_TXN);
  597. if (r)
  598. return _lws_ss_handle_state_ret(r, wsi, &h);
  599. return 0;
  600. #endif
  601. default:
  602. break;
  603. }
  604. return lws_callback_http_dummy(wsi, reason, user, in, len);
  605. }
  606. const struct lws_protocols protocol_secstream_h1 = {
  607. "lws-secstream-h1",
  608. secstream_h1,
  609. 0,
  610. 0,
  611. };
  612. /*
  613. * Munge connect info according to protocol-specific considerations... this
  614. * usually means interpreting aux in a protocol-specific way and using the
  615. * pieces at connection setup time, eg, http url pieces.
  616. *
  617. * len bytes of buf can be used for things with scope until after the actual
  618. * connect.
  619. */
  620. static int
  621. secstream_connect_munge_h1(lws_ss_handle_t *h, char *buf, size_t len,
  622. struct lws_client_connect_info *i,
  623. union lws_ss_contemp *ct)
  624. {
  625. const char *pbasis = h->policy->u.http.url;
  626. size_t used_in, used_out;
  627. lws_strexp_t exp;
  628. /* i.path on entry is used to override the policy urlpath if not "" */
  629. if (i->path[0])
  630. pbasis = i->path;
  631. if (!pbasis)
  632. return 0;
  633. #if defined(LWS_WITH_SS_RIDESHARE)
  634. if (h->policy->flags & LWSSSPOLF_HTTP_MULTIPART)
  635. i->ssl_connection |= LCCSCF_HTTP_MULTIPART_MIME;
  636. if (h->policy->flags & LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED)
  637. i->ssl_connection |= LCCSCF_HTTP_X_WWW_FORM_URLENCODED;
  638. #endif
  639. /* protocol aux is the path part */
  640. i->path = buf;
  641. buf[0] = '/';
  642. lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1);
  643. if (lws_strexp_expand(&exp, pbasis, strlen(pbasis),
  644. &used_in, &used_out) != LSTRX_DONE)
  645. return 1;
  646. return 0;
  647. }
  648. const struct ss_pcols ss_pcol_h1 = {
  649. "h1",
  650. "http/1.1",
  651. &protocol_secstream_h1,
  652. secstream_connect_munge_h1,
  653. NULL
  654. };