1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2019 - 2020 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci * 24d4afb5ceSopenharmony_ci * This is the glue that wires up h1 to Secure Streams. 25d4afb5ceSopenharmony_ci */ 26d4afb5ceSopenharmony_ci 27d4afb5ceSopenharmony_ci#include <private-lib-core.h> 28d4afb5ceSopenharmony_ci 29d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_FREERTOS) || defined(LWS_ROLE_H2) 30d4afb5ceSopenharmony_ci#define LWS_WITH_SS_RIDESHARE 31d4afb5ceSopenharmony_ci#endif 32d4afb5ceSopenharmony_ci 33d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SS_RIDESHARE) 34d4afb5ceSopenharmony_cistatic int 35d4afb5ceSopenharmony_ciss_http_multipart_parser(lws_ss_handle_t *h, void *in, size_t len) 36d4afb5ceSopenharmony_ci{ 37d4afb5ceSopenharmony_ci uint8_t *q = (uint8_t *)in; 38d4afb5ceSopenharmony_ci int pending_issue = 0, n = 0; 39d4afb5ceSopenharmony_ci 40d4afb5ceSopenharmony_ci 41d4afb5ceSopenharmony_ci /* let's stick it in the boundary state machine first */ 42d4afb5ceSopenharmony_ci while (n < (int)len) { 43d4afb5ceSopenharmony_ci if (h->u.http.boundary_seq != h->u.http.boundary_len) { 44d4afb5ceSopenharmony_ci if (q[n] == h->u.http.boundary[h->u.http.boundary_seq]) 45d4afb5ceSopenharmony_ci h->u.http.boundary_seq++; 46d4afb5ceSopenharmony_ci else { 47d4afb5ceSopenharmony_ci h->u.http.boundary_seq = 0; 48d4afb5ceSopenharmony_ci h->u.http.boundary_dashes = 0; 49d4afb5ceSopenharmony_ci h->u.http.boundary_post = 0; 50d4afb5ceSopenharmony_ci } 51d4afb5ceSopenharmony_ci goto around; 52d4afb5ceSopenharmony_ci } 53d4afb5ceSopenharmony_ci 54d4afb5ceSopenharmony_ci /* 55d4afb5ceSopenharmony_ci * We already matched the boundary string, now we're 56d4afb5ceSopenharmony_ci * looking if there's a -- afterwards 57d4afb5ceSopenharmony_ci */ 58d4afb5ceSopenharmony_ci if (h->u.http.boundary_dashes < 2) { 59d4afb5ceSopenharmony_ci if (q[n] == '-') { 60d4afb5ceSopenharmony_ci h->u.http.boundary_dashes++; 61d4afb5ceSopenharmony_ci goto around; 62d4afb5ceSopenharmony_ci } 63d4afb5ceSopenharmony_ci /* there was no final -- ... */ 64d4afb5ceSopenharmony_ci } 65d4afb5ceSopenharmony_ci 66d4afb5ceSopenharmony_ci if (h->u.http.boundary_dashes == 2) { 67d4afb5ceSopenharmony_ci /* 68d4afb5ceSopenharmony_ci * It's an EOM boundary: issue pending + multipart EOP 69d4afb5ceSopenharmony_ci */ 70d4afb5ceSopenharmony_ci lwsl_debug("%s: seen EOP, n %d pi %d\n", 71d4afb5ceSopenharmony_ci __func__, n, pending_issue); 72d4afb5ceSopenharmony_ci /* 73d4afb5ceSopenharmony_ci * It's possible we already started the decode before 74d4afb5ceSopenharmony_ci * the end of the last packet. Then there is no 75d4afb5ceSopenharmony_ci * remainder to send. 76d4afb5ceSopenharmony_ci */ 77d4afb5ceSopenharmony_ci if (n >= pending_issue + h->u.http.boundary_len + 78d4afb5ceSopenharmony_ci (h->u.http.any ? 2 : 0) + 1) { 79d4afb5ceSopenharmony_ci h->info.rx(ss_to_userobj(h), 80d4afb5ceSopenharmony_ci &q[pending_issue], 81d4afb5ceSopenharmony_ci (unsigned int)(n - pending_issue - 82d4afb5ceSopenharmony_ci h->u.http.boundary_len - 1 - 83d4afb5ceSopenharmony_ci (h->u.http.any ? 2 : 0) /* crlf */), 84d4afb5ceSopenharmony_ci (!h->u.http.som ? LWSSS_FLAG_SOM : 0) | 85d4afb5ceSopenharmony_ci LWSSS_FLAG_EOM | LWSSS_FLAG_RELATED_END); 86d4afb5ceSopenharmony_ci h->u.http.eom = 1; 87d4afb5ceSopenharmony_ci } 88d4afb5ceSopenharmony_ci 89d4afb5ceSopenharmony_ci /* 90d4afb5ceSopenharmony_ci * Peer may not END_STREAM us 91d4afb5ceSopenharmony_ci */ 92d4afb5ceSopenharmony_ci return 0; 93d4afb5ceSopenharmony_ci //return -1; 94d4afb5ceSopenharmony_ci } 95d4afb5ceSopenharmony_ci 96d4afb5ceSopenharmony_ci /* how about --boundaryCRLF */ 97d4afb5ceSopenharmony_ci 98d4afb5ceSopenharmony_ci if (h->u.http.boundary_post < 2) { 99d4afb5ceSopenharmony_ci if ((!h->u.http.boundary_post && q[n] == '\x0d') || 100d4afb5ceSopenharmony_ci (h->u.http.boundary_post && q[n] == '\x0a')) { 101d4afb5ceSopenharmony_ci h->u.http.boundary_post++; 102d4afb5ceSopenharmony_ci goto around; 103d4afb5ceSopenharmony_ci } 104d4afb5ceSopenharmony_ci /* there was no final CRLF ... it's wrong */ 105d4afb5ceSopenharmony_ci 106d4afb5ceSopenharmony_ci return -1; 107d4afb5ceSopenharmony_ci } 108d4afb5ceSopenharmony_ci if (h->u.http.boundary_post != 2) 109d4afb5ceSopenharmony_ci goto around; 110d4afb5ceSopenharmony_ci 111d4afb5ceSopenharmony_ci /* 112d4afb5ceSopenharmony_ci * We have a starting "--boundaryCRLF" or intermediate 113d4afb5ceSopenharmony_ci * "CRLF--boundaryCRLF" boundary 114d4afb5ceSopenharmony_ci */ 115d4afb5ceSopenharmony_ci lwsl_debug("%s: b_post = 2 (pi %d)\n", __func__, pending_issue); 116d4afb5ceSopenharmony_ci h->u.http.boundary_seq = 0; 117d4afb5ceSopenharmony_ci h->u.http.boundary_post = 0; 118d4afb5ceSopenharmony_ci 119d4afb5ceSopenharmony_ci if (n >= pending_issue && (h->u.http.any || !h->u.http.som)) { 120d4afb5ceSopenharmony_ci /* Intermediate... do the EOM */ 121d4afb5ceSopenharmony_ci lwsl_debug("%s: seen interm EOP n %d pi %d\n", __func__, 122d4afb5ceSopenharmony_ci n, pending_issue); 123d4afb5ceSopenharmony_ci /* 124d4afb5ceSopenharmony_ci * It's possible we already started the decode before 125d4afb5ceSopenharmony_ci * the end of the last packet. Then there is no 126d4afb5ceSopenharmony_ci * remainder to send. 127d4afb5ceSopenharmony_ci */ 128d4afb5ceSopenharmony_ci if (n >= pending_issue + h->u.http.boundary_len + 129d4afb5ceSopenharmony_ci (h->u.http.any ? 2 : 0)) { 130d4afb5ceSopenharmony_ci h->info.rx(ss_to_userobj(h), &q[pending_issue], 131d4afb5ceSopenharmony_ci (unsigned int)(n - pending_issue - 132d4afb5ceSopenharmony_ci h->u.http.boundary_len - 133d4afb5ceSopenharmony_ci (h->u.http.any ? 2 /* crlf */ : 0)), 134d4afb5ceSopenharmony_ci (!h->u.http.som ? LWSSS_FLAG_SOM : 0) | 135d4afb5ceSopenharmony_ci LWSSS_FLAG_EOM); 136d4afb5ceSopenharmony_ci h->u.http.eom = 1; 137d4afb5ceSopenharmony_ci } 138d4afb5ceSopenharmony_ci } 139d4afb5ceSopenharmony_ci 140d4afb5ceSopenharmony_ci /* Next message starts after this boundary */ 141d4afb5ceSopenharmony_ci 142d4afb5ceSopenharmony_ci pending_issue = n; 143d4afb5ceSopenharmony_ci if (h->u.http.eom) { 144d4afb5ceSopenharmony_ci /* reset only if we have sent eom */ 145d4afb5ceSopenharmony_ci h->u.http.som = 0; 146d4afb5ceSopenharmony_ci h->u.http.eom = 0; 147d4afb5ceSopenharmony_ci } 148d4afb5ceSopenharmony_ci 149d4afb5ceSopenharmony_ciaround: 150d4afb5ceSopenharmony_ci n++; 151d4afb5ceSopenharmony_ci } 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci if (pending_issue != n) { 154d4afb5ceSopenharmony_ci uint8_t oh = 0; 155d4afb5ceSopenharmony_ci 156d4afb5ceSopenharmony_ci /* 157d4afb5ceSopenharmony_ci * handle the first or last "--boundaryCRLF" case which is not captured in the 158d4afb5ceSopenharmony_ci * previous loop, on the Bob downchannel (/directive) 159d4afb5ceSopenharmony_ci * 160d4afb5ceSopenharmony_ci * probably does not cover the case that one boundary term is separated in multipile 161d4afb5ceSopenharmony_ci * one callbacks though never see such case 162d4afb5ceSopenharmony_ci */ 163d4afb5ceSopenharmony_ci 164d4afb5ceSopenharmony_ci if ((n >= h->u.http.boundary_len) && 165d4afb5ceSopenharmony_ci h->u.http.boundary_seq == h->u.http.boundary_len && 166d4afb5ceSopenharmony_ci h->u.http.boundary_post == 2) { 167d4afb5ceSopenharmony_ci 168d4afb5ceSopenharmony_ci oh = 1; 169d4afb5ceSopenharmony_ci } 170d4afb5ceSopenharmony_ci 171d4afb5ceSopenharmony_ci h->info.rx(ss_to_userobj(h), &q[pending_issue], 172d4afb5ceSopenharmony_ci (unsigned int)(oh ? 173d4afb5ceSopenharmony_ci (n - pending_issue - h->u.http.boundary_len - 174d4afb5ceSopenharmony_ci (h->u.http.any ? 2 : 0)) : 175d4afb5ceSopenharmony_ci (n - pending_issue)), 176d4afb5ceSopenharmony_ci (!h->u.http.som ? LWSSS_FLAG_SOM : 0) | 177d4afb5ceSopenharmony_ci (oh && h->u.http.any ? LWSSS_FLAG_EOM : 0)); 178d4afb5ceSopenharmony_ci 179d4afb5ceSopenharmony_ci if (oh && h->u.http.any) 180d4afb5ceSopenharmony_ci h->u.http.eom = 1; 181d4afb5ceSopenharmony_ci 182d4afb5ceSopenharmony_ci h->u.http.any = 1; 183d4afb5ceSopenharmony_ci h->u.http.som = 1; 184d4afb5ceSopenharmony_ci } 185d4afb5ceSopenharmony_ci 186d4afb5ceSopenharmony_ci return 0; 187d4afb5ceSopenharmony_ci} 188d4afb5ceSopenharmony_ci#endif 189d4afb5ceSopenharmony_ci 190d4afb5ceSopenharmony_ci/* 191d4afb5ceSopenharmony_ci * Returns 0, or the ss state resp maps on to 192d4afb5ceSopenharmony_ci */ 193d4afb5ceSopenharmony_ci 194d4afb5ceSopenharmony_cistatic int 195d4afb5ceSopenharmony_cilws_ss_http_resp_to_state(lws_ss_handle_t *h, int resp) 196d4afb5ceSopenharmony_ci{ 197d4afb5ceSopenharmony_ci const lws_ss_http_respmap_t *r = h->policy->u.http.respmap; 198d4afb5ceSopenharmony_ci int n = h->policy->u.http.count_respmap; 199d4afb5ceSopenharmony_ci 200d4afb5ceSopenharmony_ci while (n--) 201d4afb5ceSopenharmony_ci if (resp == r->resp) 202d4afb5ceSopenharmony_ci return r->state; 203d4afb5ceSopenharmony_ci else 204d4afb5ceSopenharmony_ci r++; 205d4afb5ceSopenharmony_ci 206d4afb5ceSopenharmony_ci return 0; /* no hit */ 207d4afb5ceSopenharmony_ci} 208d4afb5ceSopenharmony_ci 209d4afb5ceSopenharmony_ci/* 210d4afb5ceSopenharmony_ci * This converts any set metadata items into outgoing http headers 211d4afb5ceSopenharmony_ci */ 212d4afb5ceSopenharmony_ci 213d4afb5ceSopenharmony_cistatic int 214d4afb5ceSopenharmony_cilws_apply_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf, 215d4afb5ceSopenharmony_ci uint8_t **pp, uint8_t *end) 216d4afb5ceSopenharmony_ci{ 217d4afb5ceSopenharmony_ci lws_ss_metadata_t *polmd = h->policy->metadata; 218d4afb5ceSopenharmony_ci int m = 0; 219d4afb5ceSopenharmony_ci 220d4afb5ceSopenharmony_ci while (polmd) { 221d4afb5ceSopenharmony_ci 222d4afb5ceSopenharmony_ci /* has to have a non-empty header string */ 223d4afb5ceSopenharmony_ci 224d4afb5ceSopenharmony_ci if (polmd->value__may_own_heap && 225d4afb5ceSopenharmony_ci ((uint8_t *)polmd->value__may_own_heap)[0] && 226d4afb5ceSopenharmony_ci h->metadata[m].value__may_own_heap) { 227d4afb5ceSopenharmony_ci if (lws_add_http_header_by_name(wsi, 228d4afb5ceSopenharmony_ci polmd->value__may_own_heap, 229d4afb5ceSopenharmony_ci h->metadata[m].value__may_own_heap, 230d4afb5ceSopenharmony_ci (int)h->metadata[m].length, pp, end)) 231d4afb5ceSopenharmony_ci return -1; 232d4afb5ceSopenharmony_ci 233d4afb5ceSopenharmony_ci /* 234d4afb5ceSopenharmony_ci * Check for the case he's setting a non-zero 235d4afb5ceSopenharmony_ci * content-length "via the backdoor" metadata- 236d4afb5ceSopenharmony_ci * driven headers, and set the body_pending() 237d4afb5ceSopenharmony_ci * state if so... 238d4afb5ceSopenharmony_ci */ 239d4afb5ceSopenharmony_ci 240d4afb5ceSopenharmony_ci if (!strncmp(polmd->value__may_own_heap, 241d4afb5ceSopenharmony_ci "content-length", 14) && 242d4afb5ceSopenharmony_ci atoi(h->metadata[m].value__may_own_heap)) 243d4afb5ceSopenharmony_ci lws_client_http_body_pending(wsi, 1); 244d4afb5ceSopenharmony_ci } 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ci m++; 247d4afb5ceSopenharmony_ci polmd = polmd->next; 248d4afb5ceSopenharmony_ci } 249d4afb5ceSopenharmony_ci 250d4afb5ceSopenharmony_ci /* 251d4afb5ceSopenharmony_ci * Content-length on POST / PUT / PATCH if we have the length information 252d4afb5ceSopenharmony_ci */ 253d4afb5ceSopenharmony_ci 254d4afb5ceSopenharmony_ci if (h->policy->u.http.method && ( 255d4afb5ceSopenharmony_ci (!strcmp(h->policy->u.http.method, "POST") || 256d4afb5ceSopenharmony_ci !strcmp(h->policy->u.http.method, "PATCH") || 257d4afb5ceSopenharmony_ci !strcmp(h->policy->u.http.method, "PUT"))) && 258d4afb5ceSopenharmony_ci wsi->http.writeable_len) { 259d4afb5ceSopenharmony_ci if (!(h->policy->flags & 260d4afb5ceSopenharmony_ci LWSSSPOLF_HTTP_NO_CONTENT_LENGTH)) { 261d4afb5ceSopenharmony_ci int n = lws_snprintf((char *)buf, 20, "%u", 262d4afb5ceSopenharmony_ci (unsigned int)wsi->http.writeable_len); 263d4afb5ceSopenharmony_ci if (lws_add_http_header_by_token(wsi, 264d4afb5ceSopenharmony_ci WSI_TOKEN_HTTP_CONTENT_LENGTH, 265d4afb5ceSopenharmony_ci buf, n, pp, end)) 266d4afb5ceSopenharmony_ci return -1; 267d4afb5ceSopenharmony_ci } 268d4afb5ceSopenharmony_ci lws_client_http_body_pending(wsi, 1); 269d4afb5ceSopenharmony_ci } 270d4afb5ceSopenharmony_ci 271d4afb5ceSopenharmony_ci return 0; 272d4afb5ceSopenharmony_ci} 273d4afb5ceSopenharmony_ci 274d4afb5ceSopenharmony_ci 275d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) 276d4afb5ceSopenharmony_cistatic int 277d4afb5ceSopenharmony_cilws_apply_instant_metadata(lws_ss_handle_t *h, struct lws *wsi, uint8_t *buf, 278d4afb5ceSopenharmony_ci uint8_t **pp, uint8_t *end) 279d4afb5ceSopenharmony_ci{ 280d4afb5ceSopenharmony_ci lws_ss_metadata_t *imd = h->instant_metadata; 281d4afb5ceSopenharmony_ci 282d4afb5ceSopenharmony_ci while (imd) { 283d4afb5ceSopenharmony_ci if (imd->name && imd->value__may_own_heap) { 284d4afb5ceSopenharmony_ci lwsl_debug("%s add header %s %s %d\n", __func__, 285d4afb5ceSopenharmony_ci imd->name, 286d4afb5ceSopenharmony_ci (char *)imd->value__may_own_heap, 287d4afb5ceSopenharmony_ci (int)imd->length); 288d4afb5ceSopenharmony_ci if (lws_add_http_header_by_name(wsi, 289d4afb5ceSopenharmony_ci (const unsigned char *)imd->name, 290d4afb5ceSopenharmony_ci (const unsigned char *)imd->value__may_own_heap, 291d4afb5ceSopenharmony_ci (int)imd->length, pp, end)) 292d4afb5ceSopenharmony_ci return -1; 293d4afb5ceSopenharmony_ci 294d4afb5ceSopenharmony_ci /* it's possible user set content-length directly */ 295d4afb5ceSopenharmony_ci if (!strncmp(imd->name, 296d4afb5ceSopenharmony_ci "content-length", 14) && 297d4afb5ceSopenharmony_ci atoi(imd->value__may_own_heap)) 298d4afb5ceSopenharmony_ci lws_client_http_body_pending(wsi, 1); 299d4afb5ceSopenharmony_ci 300d4afb5ceSopenharmony_ci } 301d4afb5ceSopenharmony_ci 302d4afb5ceSopenharmony_ci imd = imd->next; 303d4afb5ceSopenharmony_ci } 304d4afb5ceSopenharmony_ci 305d4afb5ceSopenharmony_ci return 0; 306d4afb5ceSopenharmony_ci} 307d4afb5ceSopenharmony_ci#endif 308d4afb5ceSopenharmony_ci/* 309d4afb5ceSopenharmony_ci * Check if any metadata headers present in the server headers, and record 310d4afb5ceSopenharmony_ci * them into the associated metadata item if so. 311d4afb5ceSopenharmony_ci */ 312d4afb5ceSopenharmony_ci 313d4afb5ceSopenharmony_cistatic int 314d4afb5ceSopenharmony_cilws_extract_metadata(lws_ss_handle_t *h, struct lws *wsi) 315d4afb5ceSopenharmony_ci{ 316d4afb5ceSopenharmony_ci lws_ss_metadata_t *polmd = h->policy->metadata, *omd; 317d4afb5ceSopenharmony_ci int n; 318d4afb5ceSopenharmony_ci 319d4afb5ceSopenharmony_ci while (polmd) { 320d4afb5ceSopenharmony_ci 321d4afb5ceSopenharmony_ci if (polmd->value_is_http_token != LWS_HTTP_NO_KNOWN_HEADER) { 322d4afb5ceSopenharmony_ci 323d4afb5ceSopenharmony_ci /* it's a well-known header token */ 324d4afb5ceSopenharmony_ci 325d4afb5ceSopenharmony_ci n = lws_hdr_total_length(wsi, polmd->value_is_http_token); 326d4afb5ceSopenharmony_ci if (n) { 327d4afb5ceSopenharmony_ci const char *cp = lws_hdr_simple_ptr(wsi, 328d4afb5ceSopenharmony_ci polmd->value_is_http_token); 329d4afb5ceSopenharmony_ci omd = lws_ss_get_handle_metadata(h, polmd->name); 330d4afb5ceSopenharmony_ci if (!omd || !cp) 331d4afb5ceSopenharmony_ci return 1; 332d4afb5ceSopenharmony_ci 333d4afb5ceSopenharmony_ci assert(!strcmp(omd->name, polmd->name)); 334d4afb5ceSopenharmony_ci 335d4afb5ceSopenharmony_ci /* 336d4afb5ceSopenharmony_ci * it's present on the wsi, we want to 337d4afb5ceSopenharmony_ci * set the related metadata name to it then 338d4afb5ceSopenharmony_ci */ 339d4afb5ceSopenharmony_ci 340d4afb5ceSopenharmony_ci _lws_ss_alloc_set_metadata(omd, polmd->name, cp, 341d4afb5ceSopenharmony_ci (unsigned int)n); 342d4afb5ceSopenharmony_ci 343d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) 344d4afb5ceSopenharmony_ci /* 345d4afb5ceSopenharmony_ci * ...and because we are doing it from parsing 346d4afb5ceSopenharmony_ci * onward rx, we want to mark the metadata as 347d4afb5ceSopenharmony_ci * needing passing to the client 348d4afb5ceSopenharmony_ci */ 349d4afb5ceSopenharmony_ci omd->pending_onward = 1; 350d4afb5ceSopenharmony_ci#endif 351d4afb5ceSopenharmony_ci } 352d4afb5ceSopenharmony_ci } 353d4afb5ceSopenharmony_ci 354d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CUSTOM_HEADERS) 355d4afb5ceSopenharmony_ci else 356d4afb5ceSopenharmony_ci 357d4afb5ceSopenharmony_ci /* has to have a non-empty header string */ 358d4afb5ceSopenharmony_ci 359d4afb5ceSopenharmony_ci if (polmd->value__may_own_heap && 360d4afb5ceSopenharmony_ci ((uint8_t *)polmd->value__may_own_heap)[0]) { 361d4afb5ceSopenharmony_ci char *p; 362d4afb5ceSopenharmony_ci 363d4afb5ceSopenharmony_ci /* 364d4afb5ceSopenharmony_ci * Can it be a custom header? 365d4afb5ceSopenharmony_ci */ 366d4afb5ceSopenharmony_ci 367d4afb5ceSopenharmony_ci n = lws_hdr_custom_length(wsi, (const char *) 368d4afb5ceSopenharmony_ci polmd->value__may_own_heap, 369d4afb5ceSopenharmony_ci polmd->value_length); 370d4afb5ceSopenharmony_ci if (n > 0) { 371d4afb5ceSopenharmony_ci 372d4afb5ceSopenharmony_ci p = lws_malloc((unsigned int)n + 1, __func__); 373d4afb5ceSopenharmony_ci if (!p) 374d4afb5ceSopenharmony_ci return 1; 375d4afb5ceSopenharmony_ci 376d4afb5ceSopenharmony_ci /* if needed, free any previous value */ 377d4afb5ceSopenharmony_ci 378d4afb5ceSopenharmony_ci if (polmd->value_on_lws_heap) { 379d4afb5ceSopenharmony_ci lws_free( 380d4afb5ceSopenharmony_ci polmd->value__may_own_heap); 381d4afb5ceSopenharmony_ci polmd->value_on_lws_heap = 0; 382d4afb5ceSopenharmony_ci } 383d4afb5ceSopenharmony_ci 384d4afb5ceSopenharmony_ci /* 385d4afb5ceSopenharmony_ci * copy the named custom header value 386d4afb5ceSopenharmony_ci * into the malloc'd buffer 387d4afb5ceSopenharmony_ci */ 388d4afb5ceSopenharmony_ci 389d4afb5ceSopenharmony_ci if (lws_hdr_custom_copy(wsi, p, n + 1, 390d4afb5ceSopenharmony_ci (const char *) 391d4afb5ceSopenharmony_ci polmd->value__may_own_heap, 392d4afb5ceSopenharmony_ci polmd->value_length) < 0) { 393d4afb5ceSopenharmony_ci lws_free(p); 394d4afb5ceSopenharmony_ci 395d4afb5ceSopenharmony_ci return 1; 396d4afb5ceSopenharmony_ci } 397d4afb5ceSopenharmony_ci 398d4afb5ceSopenharmony_ci omd = lws_ss_get_handle_metadata(h, 399d4afb5ceSopenharmony_ci polmd->name); 400d4afb5ceSopenharmony_ci if (omd) { 401d4afb5ceSopenharmony_ci 402d4afb5ceSopenharmony_ci _lws_ss_set_metadata(omd, 403d4afb5ceSopenharmony_ci polmd->name, p, (size_t)n); 404d4afb5ceSopenharmony_ci omd->value_on_lws_heap = 1; 405d4afb5ceSopenharmony_ci 406d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) 407d4afb5ceSopenharmony_ci omd->pending_onward = 1; 408d4afb5ceSopenharmony_ci#endif 409d4afb5ceSopenharmony_ci } 410d4afb5ceSopenharmony_ci } 411d4afb5ceSopenharmony_ci } 412d4afb5ceSopenharmony_ci#endif 413d4afb5ceSopenharmony_ci 414d4afb5ceSopenharmony_ci polmd = polmd->next; 415d4afb5ceSopenharmony_ci } 416d4afb5ceSopenharmony_ci 417d4afb5ceSopenharmony_ci return 0; 418d4afb5ceSopenharmony_ci} 419d4afb5ceSopenharmony_ci 420d4afb5ceSopenharmony_cistatic const uint8_t blob_idx[] = { 421d4afb5ceSopenharmony_ci LWS_SYSBLOB_TYPE_AUTH, 422d4afb5ceSopenharmony_ci LWS_SYSBLOB_TYPE_DEVICE_SERIAL, 423d4afb5ceSopenharmony_ci LWS_SYSBLOB_TYPE_DEVICE_FW_VERSION, 424d4afb5ceSopenharmony_ci LWS_SYSBLOB_TYPE_DEVICE_TYPE, 425d4afb5ceSopenharmony_ci}; 426d4afb5ceSopenharmony_ci 427d4afb5ceSopenharmony_ciint 428d4afb5ceSopenharmony_cisecstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, 429d4afb5ceSopenharmony_ci void *in, size_t len) 430d4afb5ceSopenharmony_ci{ 431d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 432d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi]; 433d4afb5ceSopenharmony_ci#endif 434d4afb5ceSopenharmony_ci lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); 435d4afb5ceSopenharmony_ci uint8_t buf[LWS_PRE + 1520], *p = &buf[LWS_PRE], 436d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 437d4afb5ceSopenharmony_ci *start = p, 438d4afb5ceSopenharmony_ci#endif 439d4afb5ceSopenharmony_ci *end = &buf[sizeof(buf) - 1]; 440d4afb5ceSopenharmony_ci lws_ss_state_return_t r; 441d4afb5ceSopenharmony_ci int f = 0, m, status; 442d4afb5ceSopenharmony_ci char conceal_eom = 0; 443d4afb5ceSopenharmony_ci lws_usec_t inter; 444d4afb5ceSopenharmony_ci size_t buflen; 445d4afb5ceSopenharmony_ci 446d4afb5ceSopenharmony_ci switch (reason) { 447d4afb5ceSopenharmony_ci 448d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: 449d4afb5ceSopenharmony_ci if (!h) { 450d4afb5ceSopenharmony_ci lwsl_err("%s: CCE with no ss handle %s\n", __func__, lws_wsi_tag(wsi)); 451d4afb5ceSopenharmony_ci break; 452d4afb5ceSopenharmony_ci } 453d4afb5ceSopenharmony_ci 454d4afb5ceSopenharmony_ci lws_ss_assert_extant(wsi->a.context, wsi->tsi, h); 455d4afb5ceSopenharmony_ci 456d4afb5ceSopenharmony_ci assert(h->policy); 457d4afb5ceSopenharmony_ci 458d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CONMON) 459d4afb5ceSopenharmony_ci lws_conmon_ss_json(h); 460d4afb5ceSopenharmony_ci#endif 461d4afb5ceSopenharmony_ci 462d4afb5ceSopenharmony_ci lws_metrics_caliper_report_hist(h->cal_txn, wsi); 463d4afb5ceSopenharmony_ci lwsl_info("%s: %s CLIENT_CONNECTION_ERROR: %s\n", __func__, 464d4afb5ceSopenharmony_ci h->lc.gutag, in ? (const char *)in : "none"); 465d4afb5ceSopenharmony_ci if (h->ss_dangling_connected) { 466d4afb5ceSopenharmony_ci /* already disconnected, no action for DISCONNECT_ME */ 467d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); 468d4afb5ceSopenharmony_ci if (r != LWSSSSRET_OK) 469d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 470d4afb5ceSopenharmony_ci } else { 471d4afb5ceSopenharmony_ci /* already disconnected, no action for DISCONNECT_ME */ 472d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_UNREACHABLE); 473d4afb5ceSopenharmony_ci if (r) { 474d4afb5ceSopenharmony_ci if (h->inside_connect) { 475d4afb5ceSopenharmony_ci h->pending_ret = r; 476d4afb5ceSopenharmony_ci break; 477d4afb5ceSopenharmony_ci } 478d4afb5ceSopenharmony_ci 479d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 480d4afb5ceSopenharmony_ci } 481d4afb5ceSopenharmony_ci } 482d4afb5ceSopenharmony_ci 483d4afb5ceSopenharmony_ci h->wsi = NULL; 484d4afb5ceSopenharmony_ci r = lws_ss_backoff(h); 485d4afb5ceSopenharmony_ci if (r != LWSSSSRET_OK) { 486d4afb5ceSopenharmony_ci if (h->inside_connect) { 487d4afb5ceSopenharmony_ci h->pending_ret = r; 488d4afb5ceSopenharmony_ci break; 489d4afb5ceSopenharmony_ci } 490d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 491d4afb5ceSopenharmony_ci } 492d4afb5ceSopenharmony_ci break; 493d4afb5ceSopenharmony_ci 494d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_HTTP_REDIRECT: 495d4afb5ceSopenharmony_ci 496d4afb5ceSopenharmony_ci if (!h) 497d4afb5ceSopenharmony_ci return -1; 498d4afb5ceSopenharmony_ci 499d4afb5ceSopenharmony_ci if (h->policy->u.http.fail_redirect) 500d4afb5ceSopenharmony_ci lws_system_cpd_set(lws_get_context(wsi), 501d4afb5ceSopenharmony_ci LWS_CPD_CAPTIVE_PORTAL); 502d4afb5ceSopenharmony_ci /* unless it's explicitly allowed, reject to follow it */ 503d4afb5ceSopenharmony_ci return !(h->policy->flags & LWSSSPOLF_ALLOW_REDIRECTS); 504d4afb5ceSopenharmony_ci 505d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLOSED_HTTP: /* server */ 506d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLOSED_CLIENT_HTTP: 507d4afb5ceSopenharmony_ci if (!h) 508d4afb5ceSopenharmony_ci break; 509d4afb5ceSopenharmony_ci 510d4afb5ceSopenharmony_ci lws_sul_cancel(&h->sul_timeout); 511d4afb5ceSopenharmony_ci 512d4afb5ceSopenharmony_ci lws_ss_assert_extant(wsi->a.context, wsi->tsi, h); 513d4afb5ceSopenharmony_ci 514d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CONMON) 515d4afb5ceSopenharmony_ci if (wsi->conmon.pcol == LWSCONMON_PCOL_NONE) { 516d4afb5ceSopenharmony_ci wsi->conmon.pcol = LWSCONMON_PCOL_HTTP; 517d4afb5ceSopenharmony_ci wsi->conmon.protocol_specific.http.response = 518d4afb5ceSopenharmony_ci (int)lws_http_client_http_response(wsi); 519d4afb5ceSopenharmony_ci } 520d4afb5ceSopenharmony_ci 521d4afb5ceSopenharmony_ci lws_conmon_ss_json(h); 522d4afb5ceSopenharmony_ci#endif 523d4afb5ceSopenharmony_ci 524d4afb5ceSopenharmony_ci lws_metrics_caliper_report_hist(h->cal_txn, wsi); 525d4afb5ceSopenharmony_ci //lwsl_notice("%s: %s LWS_CALLBACK_CLOSED_CLIENT_HTTP\n", 526d4afb5ceSopenharmony_ci // __func__, wsi->lc.gutag); 527d4afb5ceSopenharmony_ci 528d4afb5ceSopenharmony_ci h->wsi = NULL; 529d4afb5ceSopenharmony_ci h->hanging_som = 0; 530d4afb5ceSopenharmony_ci h->subseq = 0; 531d4afb5ceSopenharmony_ci 532d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 533d4afb5ceSopenharmony_ci lws_pt_lock(pt, __func__); 534d4afb5ceSopenharmony_ci lws_dll2_remove(&h->cli_list); 535d4afb5ceSopenharmony_ci lws_pt_unlock(pt); 536d4afb5ceSopenharmony_ci#endif 537d4afb5ceSopenharmony_ci 538d4afb5ceSopenharmony_ci if (h->policy && !(h->policy->flags & LWSSSPOLF_OPPORTUNISTIC) && 539d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 540d4afb5ceSopenharmony_ci !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not server */ 541d4afb5ceSopenharmony_ci#endif 542d4afb5ceSopenharmony_ci !h->txn_ok && !wsi->a.context->being_destroyed) { 543d4afb5ceSopenharmony_ci r = lws_ss_backoff(h); 544d4afb5ceSopenharmony_ci if (r != LWSSSSRET_OK) 545d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 546d4afb5ceSopenharmony_ci break; 547d4afb5ceSopenharmony_ci } else 548d4afb5ceSopenharmony_ci h->seqstate = SSSEQ_IDLE; 549d4afb5ceSopenharmony_ci 550d4afb5ceSopenharmony_ci if (h->ss_dangling_connected) { 551d4afb5ceSopenharmony_ci /* already disconnected, no action for DISCONNECT_ME */ 552d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_DISCONNECTED); 553d4afb5ceSopenharmony_ci if (r != LWSSSSRET_OK) 554d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 555d4afb5ceSopenharmony_ci } 556d4afb5ceSopenharmony_ci break; 557d4afb5ceSopenharmony_ci 558d4afb5ceSopenharmony_ci case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: 559d4afb5ceSopenharmony_ci 560d4afb5ceSopenharmony_ci if (!h) 561d4afb5ceSopenharmony_ci return -1; 562d4afb5ceSopenharmony_ci 563d4afb5ceSopenharmony_ci lws_ss_assert_extant(wsi->a.context, wsi->tsi, h); 564d4afb5ceSopenharmony_ci h->wsi = wsi; /* since we accept the wsi is bound to the SS, 565d4afb5ceSopenharmony_ci * ensure the SS feels the same way about the wsi */ 566d4afb5ceSopenharmony_ci 567d4afb5ceSopenharmony_ci#if defined(LWS_WITH_CONMON) 568d4afb5ceSopenharmony_ci if (wsi->conmon.pcol == LWSCONMON_PCOL_NONE) { 569d4afb5ceSopenharmony_ci wsi->conmon.pcol = LWSCONMON_PCOL_HTTP; 570d4afb5ceSopenharmony_ci wsi->conmon.protocol_specific.http.response = 571d4afb5ceSopenharmony_ci (int)lws_http_client_http_response(wsi); 572d4afb5ceSopenharmony_ci } 573d4afb5ceSopenharmony_ci 574d4afb5ceSopenharmony_ci lws_conmon_ss_json(h); 575d4afb5ceSopenharmony_ci#endif 576d4afb5ceSopenharmony_ci 577d4afb5ceSopenharmony_ci status = (int)lws_http_client_http_response(wsi); 578d4afb5ceSopenharmony_ci lwsl_info("%s: LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: %d\n", __func__, status); 579d4afb5ceSopenharmony_ci // if (!status) 580d4afb5ceSopenharmony_ci /* it's just telling use we connected / joined the nwsi */ 581d4afb5ceSopenharmony_ci // break; 582d4afb5ceSopenharmony_ci 583d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) 584d4afb5ceSopenharmony_ci if (status) { 585d4afb5ceSopenharmony_ci lws_snprintf((char *)buf, 10, "%d", status); 586d4afb5ceSopenharmony_ci lws_metrics_tag_ss_add(h, "http_resp", (char *)buf); 587d4afb5ceSopenharmony_ci } 588d4afb5ceSopenharmony_ci#endif 589d4afb5ceSopenharmony_ci 590d4afb5ceSopenharmony_ci if (status == HTTP_STATUS_SERVICE_UNAVAILABLE /* 503 */ || 591d4afb5ceSopenharmony_ci status == 429 /* Too many requests */) { 592d4afb5ceSopenharmony_ci /* 593d4afb5ceSopenharmony_ci * We understand this attempt failed, and that we should 594d4afb5ceSopenharmony_ci * conceal this attempt. If there's a specified 595d4afb5ceSopenharmony_ci * retry-after, we should use that if larger than our 596d4afb5ceSopenharmony_ci * computed backoff 597d4afb5ceSopenharmony_ci */ 598d4afb5ceSopenharmony_ci 599d4afb5ceSopenharmony_ci inter = 0; 600d4afb5ceSopenharmony_ci lws_http_check_retry_after(wsi, &inter); 601d4afb5ceSopenharmony_ci 602d4afb5ceSopenharmony_ci r = _lws_ss_backoff(h, inter); 603d4afb5ceSopenharmony_ci if (r != LWSSSSRET_OK) 604d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 605d4afb5ceSopenharmony_ci 606d4afb5ceSopenharmony_ci return -1; /* end this stream */ 607d4afb5ceSopenharmony_ci } 608d4afb5ceSopenharmony_ci 609d4afb5ceSopenharmony_ci if (h->policy->u.http.resp_expect) 610d4afb5ceSopenharmony_ci h->u.http.good_respcode = 611d4afb5ceSopenharmony_ci status == h->policy->u.http.resp_expect; 612d4afb5ceSopenharmony_ci else 613d4afb5ceSopenharmony_ci h->u.http.good_respcode = (status >= 200 && status < 300); 614d4afb5ceSopenharmony_ci // lwsl_err("%s: good resp %d %d\n", __func__, status, h->u.http.good_respcode); 615d4afb5ceSopenharmony_ci 616d4afb5ceSopenharmony_ci if (lws_extract_metadata(h, wsi)) { 617d4afb5ceSopenharmony_ci lwsl_info("%s: rx metadata extract failed\n", __func__); 618d4afb5ceSopenharmony_ci 619d4afb5ceSopenharmony_ci return -1; 620d4afb5ceSopenharmony_ci } 621d4afb5ceSopenharmony_ci 622d4afb5ceSopenharmony_ci if (status) { 623d4afb5ceSopenharmony_ci /* 624d4afb5ceSopenharmony_ci * Check and see if it's something from the response 625d4afb5ceSopenharmony_ci * map, if so, generate the requested status. If we're 626d4afb5ceSopenharmony_ci * the proxy onward connection, metadata has priority 627d4afb5ceSopenharmony_ci * over state updates on the serialization, so the 628d4afb5ceSopenharmony_ci * state callback will see the right metadata. 629d4afb5ceSopenharmony_ci */ 630d4afb5ceSopenharmony_ci int n = lws_ss_http_resp_to_state(h, status); 631d4afb5ceSopenharmony_ci if (n) { 632d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, (lws_ss_constate_t)n); 633d4afb5ceSopenharmony_ci if (r != LWSSSSRET_OK) 634d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, 635d4afb5ceSopenharmony_ci &h); 636d4afb5ceSopenharmony_ci } 637d4afb5ceSopenharmony_ci } 638d4afb5ceSopenharmony_ci 639d4afb5ceSopenharmony_ci if (h->u.http.good_respcode) 640d4afb5ceSopenharmony_ci lwsl_info("%s: Connected streamtype %s, %d\n", __func__, 641d4afb5ceSopenharmony_ci h->policy->streamtype, status); 642d4afb5ceSopenharmony_ci else 643d4afb5ceSopenharmony_ci if (h->u.http.good_respcode) 644d4afb5ceSopenharmony_ci lwsl_warn("%s: Connected streamtype %s, BAD %d\n", 645d4afb5ceSopenharmony_ci __func__, h->policy->streamtype, 646d4afb5ceSopenharmony_ci status); 647d4afb5ceSopenharmony_ci 648d4afb5ceSopenharmony_ci h->hanging_som = 0; 649d4afb5ceSopenharmony_ci 650d4afb5ceSopenharmony_ci h->retry = 0; 651d4afb5ceSopenharmony_ci h->seqstate = SSSEQ_CONNECTED; 652d4afb5ceSopenharmony_ci lws_sul_cancel(&h->sul); 653d4afb5ceSopenharmony_ci 654d4afb5ceSopenharmony_ci if (h->prev_ss_state != LWSSSCS_CONNECTED) { 655d4afb5ceSopenharmony_ci wsi->client_suppress_CONNECTION_ERROR = 1; 656d4afb5ceSopenharmony_ci if (h->prev_ss_state != LWSSSCS_CONNECTED) { 657d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); 658d4afb5ceSopenharmony_ci if (r != LWSSSSRET_OK) 659d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 660d4afb5ceSopenharmony_ci } 661d4afb5ceSopenharmony_ci } 662d4afb5ceSopenharmony_ci 663d4afb5ceSopenharmony_ci /* 664d4afb5ceSopenharmony_ci * Since it's an http transaction we initiated... this is 665d4afb5ceSopenharmony_ci * proof of connection validity 666d4afb5ceSopenharmony_ci */ 667d4afb5ceSopenharmony_ci lws_validity_confirmed(wsi); 668d4afb5ceSopenharmony_ci 669d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SS_RIDESHARE) 670d4afb5ceSopenharmony_ci 671d4afb5ceSopenharmony_ci /* 672d4afb5ceSopenharmony_ci * There are two ways we might want to deal with multipart, 673d4afb5ceSopenharmony_ci * one is pass it through raw (although the user code needs 674d4afb5ceSopenharmony_ci * a helping hand for learning the boundary), and the other 675d4afb5ceSopenharmony_ci * is to deframe it and provide basically submessages in the 676d4afb5ceSopenharmony_ci * different parts. 677d4afb5ceSopenharmony_ci */ 678d4afb5ceSopenharmony_ci 679d4afb5ceSopenharmony_ci if (lws_hdr_copy(wsi, (char *)buf, sizeof(buf), 680d4afb5ceSopenharmony_ci WSI_TOKEN_HTTP_CONTENT_TYPE) > 0 && 681d4afb5ceSopenharmony_ci /* multipart/form-data; 682d4afb5ceSopenharmony_ci * boundary=----WebKitFormBoundarycc7YgAPEIHvgE9Bf */ 683d4afb5ceSopenharmony_ci 684d4afb5ceSopenharmony_ci (!strncmp((char *)buf, "multipart/form-data", 19) || 685d4afb5ceSopenharmony_ci !strncmp((char *)buf, "multipart/related", 17))) { 686d4afb5ceSopenharmony_ci struct lws_tokenize ts; 687d4afb5ceSopenharmony_ci lws_tokenize_elem e; 688d4afb5ceSopenharmony_ci 689d4afb5ceSopenharmony_ci // puts((const char *)buf); 690d4afb5ceSopenharmony_ci 691d4afb5ceSopenharmony_ci memset(&ts, 0, sizeof(ts)); 692d4afb5ceSopenharmony_ci ts.start = (char *)buf; 693d4afb5ceSopenharmony_ci ts.len = strlen(ts.start); 694d4afb5ceSopenharmony_ci ts.flags = LWS_TOKENIZE_F_RFC7230_DELIMS | 695d4afb5ceSopenharmony_ci LWS_TOKENIZE_F_SLASH_NONTERM | 696d4afb5ceSopenharmony_ci LWS_TOKENIZE_F_MINUS_NONTERM; 697d4afb5ceSopenharmony_ci 698d4afb5ceSopenharmony_ci h->u.http.boundary[0] = '\0'; 699d4afb5ceSopenharmony_ci do { 700d4afb5ceSopenharmony_ci e = lws_tokenize(&ts); 701d4afb5ceSopenharmony_ci if (e == LWS_TOKZE_TOKEN_NAME_EQUALS && 702d4afb5ceSopenharmony_ci !strncmp(ts.token, "boundary", 8) && 703d4afb5ceSopenharmony_ci ts.token_len == 8) { 704d4afb5ceSopenharmony_ci e = lws_tokenize(&ts); 705d4afb5ceSopenharmony_ci if (e != LWS_TOKZE_TOKEN) 706d4afb5ceSopenharmony_ci goto malformed; 707d4afb5ceSopenharmony_ci h->u.http.boundary[0] = '\x0d'; 708d4afb5ceSopenharmony_ci h->u.http.boundary[1] = '\x0a'; 709d4afb5ceSopenharmony_ci h->u.http.boundary[2] = '-'; 710d4afb5ceSopenharmony_ci h->u.http.boundary[3] = '-'; 711d4afb5ceSopenharmony_ci lws_strnncpy(h->u.http.boundary + 4, 712d4afb5ceSopenharmony_ci ts.token, ts.token_len, 713d4afb5ceSopenharmony_ci sizeof(h->u.http.boundary) - 4); 714d4afb5ceSopenharmony_ci h->u.http.boundary_len = 715d4afb5ceSopenharmony_ci (uint8_t)(ts.token_len + 4); 716d4afb5ceSopenharmony_ci h->u.http.boundary_seq = 2; 717d4afb5ceSopenharmony_ci h->u.http.boundary_dashes = 0; 718d4afb5ceSopenharmony_ci } 719d4afb5ceSopenharmony_ci } while (e > 0); 720d4afb5ceSopenharmony_ci lwsl_info("%s: multipart boundary '%s' len %d\n", __func__, 721d4afb5ceSopenharmony_ci h->u.http.boundary, h->u.http.boundary_len); 722d4afb5ceSopenharmony_ci 723d4afb5ceSopenharmony_ci /* inform the ss that a related message group begins */ 724d4afb5ceSopenharmony_ci 725d4afb5ceSopenharmony_ci if ((h->policy->flags & LWSSSPOLF_HTTP_MULTIPART_IN) && 726d4afb5ceSopenharmony_ci h->u.http.boundary[0]) 727d4afb5ceSopenharmony_ci h->info.rx(ss_to_userobj(h), NULL, 0, 728d4afb5ceSopenharmony_ci LWSSS_FLAG_RELATED_START); 729d4afb5ceSopenharmony_ci 730d4afb5ceSopenharmony_ci // lws_header_table_detach(wsi, 0); 731d4afb5ceSopenharmony_ci } 732d4afb5ceSopenharmony_ci break; 733d4afb5ceSopenharmony_cimalformed: 734d4afb5ceSopenharmony_ci lwsl_notice("%s: malformed multipart header\n", __func__); 735d4afb5ceSopenharmony_ci return -1; 736d4afb5ceSopenharmony_ci#else 737d4afb5ceSopenharmony_ci break; 738d4afb5ceSopenharmony_ci#endif 739d4afb5ceSopenharmony_ci 740d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: 741d4afb5ceSopenharmony_ci if (!h) 742d4afb5ceSopenharmony_ci return -1; 743d4afb5ceSopenharmony_ci if (h->writeable_len) 744d4afb5ceSopenharmony_ci wsi->http.writeable_len = h->writeable_len; 745d4afb5ceSopenharmony_ci 746d4afb5ceSopenharmony_ci { 747d4afb5ceSopenharmony_ci uint8_t **p = (uint8_t **)in, *end = (*p) + len, 748d4afb5ceSopenharmony_ci *oin = *(uint8_t **)in; 749d4afb5ceSopenharmony_ci 750d4afb5ceSopenharmony_ci /* 751d4afb5ceSopenharmony_ci * blob-based headers 752d4afb5ceSopenharmony_ci */ 753d4afb5ceSopenharmony_ci 754d4afb5ceSopenharmony_ci for (m = 0; m < _LWSSS_HBI_COUNT; m++) { 755d4afb5ceSopenharmony_ci lws_system_blob_t *ab; 756d4afb5ceSopenharmony_ci int o = 0, n; 757d4afb5ceSopenharmony_ci 758d4afb5ceSopenharmony_ci if (!h->policy->u.http.blob_header[m]) 759d4afb5ceSopenharmony_ci continue; 760d4afb5ceSopenharmony_ci 761d4afb5ceSopenharmony_ci /* 762d4afb5ceSopenharmony_ci * To be backward compatible, default is system-wide LWA auth, 763d4afb5ceSopenharmony_ci * and "http_auth_header" is for default LWA auth, current users do not 764d4afb5ceSopenharmony_ci * need any change in their policy. 765d4afb5ceSopenharmony_ci * If user wants different auth/token, need to specify the "use_auth" 766d4afb5ceSopenharmony_ci * and will be handled after metadata headers are applied. 767d4afb5ceSopenharmony_ci */ 768d4afb5ceSopenharmony_ci 769d4afb5ceSopenharmony_ci if (m == LWSSS_HBI_AUTH && 770d4afb5ceSopenharmony_ci h->policy->u.http.auth_preamble) 771d4afb5ceSopenharmony_ci o = lws_snprintf((char *)buf, sizeof(buf), "%s", 772d4afb5ceSopenharmony_ci h->policy->u.http.auth_preamble); 773d4afb5ceSopenharmony_ci 774d4afb5ceSopenharmony_ci if (o > (int)sizeof(buf) - 2) 775d4afb5ceSopenharmony_ci return -1; 776d4afb5ceSopenharmony_ci 777d4afb5ceSopenharmony_ci ab = lws_system_get_blob(wsi->a.context, blob_idx[m], 0); 778d4afb5ceSopenharmony_ci if (!ab) 779d4afb5ceSopenharmony_ci return -1; 780d4afb5ceSopenharmony_ci 781d4afb5ceSopenharmony_ci buflen = sizeof(buf) - (unsigned int)o - 2u; 782d4afb5ceSopenharmony_ci n = lws_system_blob_get(ab, buf + o, &buflen, 0); 783d4afb5ceSopenharmony_ci if (n < 0) 784d4afb5ceSopenharmony_ci return -1; 785d4afb5ceSopenharmony_ci 786d4afb5ceSopenharmony_ci buf[(unsigned int)o + buflen] = '\0'; 787d4afb5ceSopenharmony_ci lwsl_debug("%s: adding blob %d: %s\n", __func__, m, buf); 788d4afb5ceSopenharmony_ci 789d4afb5ceSopenharmony_ci if (lws_add_http_header_by_name(wsi, 790d4afb5ceSopenharmony_ci (uint8_t *)h->policy->u.http.blob_header[m], 791d4afb5ceSopenharmony_ci buf, (int)((int)buflen + o), p, end)) 792d4afb5ceSopenharmony_ci return -1; 793d4afb5ceSopenharmony_ci } 794d4afb5ceSopenharmony_ci 795d4afb5ceSopenharmony_ci /* 796d4afb5ceSopenharmony_ci * metadata-based headers 797d4afb5ceSopenharmony_ci */ 798d4afb5ceSopenharmony_ci 799d4afb5ceSopenharmony_ci if (lws_apply_metadata(h, wsi, buf, p, end)) 800d4afb5ceSopenharmony_ci return -1; 801d4afb5ceSopenharmony_ci 802d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SS_DIRECT_PROTOCOL_STR) 803d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_DIRECT_PROTO_STR) { 804d4afb5ceSopenharmony_ci if (lws_apply_instant_metadata(h, wsi, buf, p, end)) 805d4afb5ceSopenharmony_ci return -1; 806d4afb5ceSopenharmony_ci } 807d4afb5ceSopenharmony_ci#endif 808d4afb5ceSopenharmony_ci 809d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4) 810d4afb5ceSopenharmony_ci if (h->policy->auth && h->policy->auth->type && 811d4afb5ceSopenharmony_ci !strcmp(h->policy->auth->type, "sigv4")) { 812d4afb5ceSopenharmony_ci 813d4afb5ceSopenharmony_ci if (lws_ss_apply_sigv4(wsi, h, p, end)) 814d4afb5ceSopenharmony_ci return -1; 815d4afb5ceSopenharmony_ci } 816d4afb5ceSopenharmony_ci#endif 817d4afb5ceSopenharmony_ci 818d4afb5ceSopenharmony_ci 819d4afb5ceSopenharmony_ci (void)oin; 820d4afb5ceSopenharmony_ci //if (*p != oin) 821d4afb5ceSopenharmony_ci // lwsl_hexdump_notice(oin, lws_ptr_diff_size_t(*p, oin)); 822d4afb5ceSopenharmony_ci 823d4afb5ceSopenharmony_ci } 824d4afb5ceSopenharmony_ci 825d4afb5ceSopenharmony_ci /* 826d4afb5ceSopenharmony_ci * So when proxied, for POST we have to synthesize a CONNECTED 827d4afb5ceSopenharmony_ci * state, so it can request a writeable and deliver the POST 828d4afb5ceSopenharmony_ci * body 829d4afb5ceSopenharmony_ci */ 830d4afb5ceSopenharmony_ci if ((h->policy->protocol == LWSSSP_H1 || 831d4afb5ceSopenharmony_ci h->policy->protocol == LWSSSP_H2) && 832d4afb5ceSopenharmony_ci h->being_serialized && ( 833d4afb5ceSopenharmony_ci !strcmp(h->policy->u.http.method, "PUT") || 834d4afb5ceSopenharmony_ci !strcmp(h->policy->u.http.method, "PATCH") || 835d4afb5ceSopenharmony_ci !strcmp(h->policy->u.http.method, "POST"))) { 836d4afb5ceSopenharmony_ci 837d4afb5ceSopenharmony_ci wsi->client_suppress_CONNECTION_ERROR = 1; 838d4afb5ceSopenharmony_ci if (h->prev_ss_state != LWSSSCS_CONNECTED) { 839d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); 840d4afb5ceSopenharmony_ci if (r) 841d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 842d4afb5ceSopenharmony_ci } 843d4afb5ceSopenharmony_ci } 844d4afb5ceSopenharmony_ci 845d4afb5ceSopenharmony_ci break; 846d4afb5ceSopenharmony_ci 847d4afb5ceSopenharmony_ci /* chunks of chunked content, with header removed */ 848d4afb5ceSopenharmony_ci case LWS_CALLBACK_HTTP_BODY: 849d4afb5ceSopenharmony_ci case LWS_CALLBACK_RECEIVE_CLIENT_HTTP_READ: 850d4afb5ceSopenharmony_ci lwsl_debug("%s: RECEIVE_CLIENT_HTTP_READ: read %d\n", 851d4afb5ceSopenharmony_ci __func__, (int)len); 852d4afb5ceSopenharmony_ci if (!h || !h->info.rx) 853d4afb5ceSopenharmony_ci return 0; 854d4afb5ceSopenharmony_ci 855d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SS_RIDESHARE) 856d4afb5ceSopenharmony_ci if ((h->policy->flags & LWSSSPOLF_HTTP_MULTIPART_IN) && 857d4afb5ceSopenharmony_ci h->u.http.boundary[0]) 858d4afb5ceSopenharmony_ci return ss_http_multipart_parser(h, in, len); 859d4afb5ceSopenharmony_ci#endif 860d4afb5ceSopenharmony_ci 861d4afb5ceSopenharmony_ci if (!h->subseq) { 862d4afb5ceSopenharmony_ci f |= LWSSS_FLAG_SOM; 863d4afb5ceSopenharmony_ci h->hanging_som = 1; 864d4afb5ceSopenharmony_ci h->subseq = 1; 865d4afb5ceSopenharmony_ci } 866d4afb5ceSopenharmony_ci 867d4afb5ceSopenharmony_ci // lwsl_notice("%s: HTTP_READ: client side sent len %d fl 0x%x\n", 868d4afb5ceSopenharmony_ci // __func__, (int)len, (int)f); 869d4afb5ceSopenharmony_ci 870d4afb5ceSopenharmony_ci h->wsi = wsi; /* since we accept the wsi is bound to the SS, 871d4afb5ceSopenharmony_ci * ensure the SS feels the same way about the wsi */ 872d4afb5ceSopenharmony_ci r = h->info.rx(ss_to_userobj(h), (const uint8_t *)in, len, f); 873d4afb5ceSopenharmony_ci if (r != LWSSSSRET_OK) 874d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 875d4afb5ceSopenharmony_ci 876d4afb5ceSopenharmony_ci return 0; /* don't passthru */ 877d4afb5ceSopenharmony_ci 878d4afb5ceSopenharmony_ci /* uninterpreted http content */ 879d4afb5ceSopenharmony_ci case LWS_CALLBACK_RECEIVE_CLIENT_HTTP: 880d4afb5ceSopenharmony_ci { 881d4afb5ceSopenharmony_ci char *px = (char *)buf + LWS_PRE; /* guarantees LWS_PRE */ 882d4afb5ceSopenharmony_ci int lenx = sizeof(buf) - LWS_PRE; 883d4afb5ceSopenharmony_ci 884d4afb5ceSopenharmony_ci m = lws_http_client_read(wsi, &px, &lenx); 885d4afb5ceSopenharmony_ci if (m < 0) 886d4afb5ceSopenharmony_ci return m; 887d4afb5ceSopenharmony_ci } 888d4afb5ceSopenharmony_ci lws_set_timeout(wsi, 99, 30); 889d4afb5ceSopenharmony_ci 890d4afb5ceSopenharmony_ci return 0; /* don't passthru */ 891d4afb5ceSopenharmony_ci 892d4afb5ceSopenharmony_ci case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: 893d4afb5ceSopenharmony_ci // lwsl_debug("%s: LWS_CALLBACK_COMPLETED_CLIENT_HTTP\n", __func__); 894d4afb5ceSopenharmony_ci 895d4afb5ceSopenharmony_ci if (!h) 896d4afb5ceSopenharmony_ci return -1; 897d4afb5ceSopenharmony_ci 898d4afb5ceSopenharmony_ci if (h->hanging_som) { 899d4afb5ceSopenharmony_ci h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_EOM); 900d4afb5ceSopenharmony_ci h->hanging_som = 0; 901d4afb5ceSopenharmony_ci h->subseq = 0; 902d4afb5ceSopenharmony_ci } 903d4afb5ceSopenharmony_ci 904d4afb5ceSopenharmony_ci wsi->http.writeable_len = h->writeable_len = 0; 905d4afb5ceSopenharmony_ci lws_sul_cancel(&h->sul_timeout); 906d4afb5ceSopenharmony_ci 907d4afb5ceSopenharmony_ci h->txn_ok = 1; 908d4afb5ceSopenharmony_ci 909d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) 910d4afb5ceSopenharmony_ci lws_metrics_tag_ss_add(h, "result", 911d4afb5ceSopenharmony_ci h->u.http.good_respcode ? 912d4afb5ceSopenharmony_ci "SS_ACK_REMOTE" : "SS_NACK_REMOTE"); 913d4afb5ceSopenharmony_ci#endif 914d4afb5ceSopenharmony_ci 915d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, h->u.http.good_respcode ? 916d4afb5ceSopenharmony_ci LWSSSCS_QOS_ACK_REMOTE : 917d4afb5ceSopenharmony_ci LWSSSCS_QOS_NACK_REMOTE); 918d4afb5ceSopenharmony_ci if (r != LWSSSSRET_OK) 919d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 920d4afb5ceSopenharmony_ci 921d4afb5ceSopenharmony_ci lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ 922d4afb5ceSopenharmony_ci break; 923d4afb5ceSopenharmony_ci 924d4afb5ceSopenharmony_ci case LWS_CALLBACK_HTTP_WRITEABLE: 925d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLIENT_HTTP_WRITEABLE: 926d4afb5ceSopenharmony_ci 927d4afb5ceSopenharmony_ci if (!h || !h->info.tx) { 928d4afb5ceSopenharmony_ci lwsl_notice("%s: no handle / tx\n", __func__); 929d4afb5ceSopenharmony_ci return 0; 930d4afb5ceSopenharmony_ci } 931d4afb5ceSopenharmony_ci 932d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 933d4afb5ceSopenharmony_ci if (h->txn_resp_pending) { 934d4afb5ceSopenharmony_ci /* 935d4afb5ceSopenharmony_ci * If we're going to start sending something, we need to 936d4afb5ceSopenharmony_ci * to take care of the http response header for it first 937d4afb5ceSopenharmony_ci */ 938d4afb5ceSopenharmony_ci h->txn_resp_pending = 0; 939d4afb5ceSopenharmony_ci 940d4afb5ceSopenharmony_ci if (lws_add_http_common_headers(wsi, 941d4afb5ceSopenharmony_ci (unsigned int)(h->txn_resp_set ? 942d4afb5ceSopenharmony_ci (h->txn_resp ? h->txn_resp : 200) : 943d4afb5ceSopenharmony_ci HTTP_STATUS_NOT_FOUND), 944d4afb5ceSopenharmony_ci NULL, h->wsi->http.writeable_len, 945d4afb5ceSopenharmony_ci &p, end)) 946d4afb5ceSopenharmony_ci return 1; 947d4afb5ceSopenharmony_ci 948d4afb5ceSopenharmony_ci /* 949d4afb5ceSopenharmony_ci * metadata-based headers 950d4afb5ceSopenharmony_ci */ 951d4afb5ceSopenharmony_ci 952d4afb5ceSopenharmony_ci if (lws_apply_metadata(h, wsi, buf, &p, end)) 953d4afb5ceSopenharmony_ci return -1; 954d4afb5ceSopenharmony_ci 955d4afb5ceSopenharmony_ci if (lws_finalize_write_http_header(wsi, start, &p, end)) 956d4afb5ceSopenharmony_ci return 1; 957d4afb5ceSopenharmony_ci 958d4afb5ceSopenharmony_ci /* write the body separately */ 959d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 960d4afb5ceSopenharmony_ci 961d4afb5ceSopenharmony_ci return 0; 962d4afb5ceSopenharmony_ci } 963d4afb5ceSopenharmony_ci#endif 964d4afb5ceSopenharmony_ci 965d4afb5ceSopenharmony_ci if ( 966d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 967d4afb5ceSopenharmony_ci !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not accepted */ 968d4afb5ceSopenharmony_ci#endif 969d4afb5ceSopenharmony_ci !h->rideshare) 970d4afb5ceSopenharmony_ci 971d4afb5ceSopenharmony_ci h->rideshare = h->policy; 972d4afb5ceSopenharmony_ci 973d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SS_RIDESHARE) 974d4afb5ceSopenharmony_ci if ( 975d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 976d4afb5ceSopenharmony_ci !(h->info.flags & LWSSSINFLAGS_ACCEPTED) && /* not accepted */ 977d4afb5ceSopenharmony_ci#endif 978d4afb5ceSopenharmony_ci !h->inside_msg && h->rideshare->u.http.multipart_name) 979d4afb5ceSopenharmony_ci lws_client_http_multipart(wsi, 980d4afb5ceSopenharmony_ci h->rideshare->u.http.multipart_name, 981d4afb5ceSopenharmony_ci h->rideshare->u.http.multipart_filename, 982d4afb5ceSopenharmony_ci h->rideshare->u.http.multipart_content_type, 983d4afb5ceSopenharmony_ci (char **)&p, (char *)end); 984d4afb5ceSopenharmony_ci 985d4afb5ceSopenharmony_ci buflen = lws_ptr_diff_size_t(end, p); 986d4afb5ceSopenharmony_ci if (h->policy->u.http.multipart_name) 987d4afb5ceSopenharmony_ci buflen -= 24; /* allow space for end of multipart */ 988d4afb5ceSopenharmony_ci#else 989d4afb5ceSopenharmony_ci buflen = lws_ptr_diff_size_t(end, p); 990d4afb5ceSopenharmony_ci#endif 991d4afb5ceSopenharmony_ci r = h->info.tx(ss_to_userobj(h), h->txord++, p, &buflen, &f); 992d4afb5ceSopenharmony_ci if (r == LWSSSSRET_TX_DONT_SEND) 993d4afb5ceSopenharmony_ci return 0; 994d4afb5ceSopenharmony_ci if (r < 0) 995d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 996d4afb5ceSopenharmony_ci 997d4afb5ceSopenharmony_ci // lwsl_notice("%s: WRITEABLE: user tx says len %d fl 0x%x\n", 998d4afb5ceSopenharmony_ci // __func__, (int)buflen, (int)f); 999d4afb5ceSopenharmony_ci 1000d4afb5ceSopenharmony_ci p += buflen; 1001d4afb5ceSopenharmony_ci 1002d4afb5ceSopenharmony_ci if (f & LWSSS_FLAG_EOM) { 1003d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1004d4afb5ceSopenharmony_ci if (!(h->info.flags & LWSSSINFLAGS_ACCEPTED)) { 1005d4afb5ceSopenharmony_ci#endif 1006d4afb5ceSopenharmony_ci conceal_eom = 1; 1007d4afb5ceSopenharmony_ci /* end of rideshares */ 1008d4afb5ceSopenharmony_ci if (!h->rideshare->rideshare_streamtype) { 1009d4afb5ceSopenharmony_ci lws_client_http_body_pending(wsi, 0); 1010d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SS_RIDESHARE) 1011d4afb5ceSopenharmony_ci if (h->rideshare->u.http.multipart_name) 1012d4afb5ceSopenharmony_ci lws_client_http_multipart(wsi, NULL, NULL, NULL, 1013d4afb5ceSopenharmony_ci (char **)&p, (char *)end); 1014d4afb5ceSopenharmony_ci conceal_eom = 0; 1015d4afb5ceSopenharmony_ci#endif 1016d4afb5ceSopenharmony_ci } else { 1017d4afb5ceSopenharmony_ci h->rideshare = lws_ss_policy_lookup(wsi->a.context, 1018d4afb5ceSopenharmony_ci h->rideshare->rideshare_streamtype); 1019d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 1020d4afb5ceSopenharmony_ci } 1021d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1022d4afb5ceSopenharmony_ci } 1023d4afb5ceSopenharmony_ci#endif 1024d4afb5ceSopenharmony_ci 1025d4afb5ceSopenharmony_ci h->inside_msg = 0; 1026d4afb5ceSopenharmony_ci } else { 1027d4afb5ceSopenharmony_ci /* otherwise we can spin with zero length writes */ 1028d4afb5ceSopenharmony_ci if (!f && !lws_ptr_diff(p, buf + LWS_PRE)) 1029d4afb5ceSopenharmony_ci break; 1030d4afb5ceSopenharmony_ci h->inside_msg = 1; 1031d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 1032d4afb5ceSopenharmony_ci } 1033d4afb5ceSopenharmony_ci 1034d4afb5ceSopenharmony_ci lwsl_info("%s: lws_write %d %d\n", __func__, 1035d4afb5ceSopenharmony_ci lws_ptr_diff(p, buf + LWS_PRE), f); 1036d4afb5ceSopenharmony_ci 1037d4afb5ceSopenharmony_ci if (lws_write(wsi, buf + LWS_PRE, lws_ptr_diff_size_t(p, buf + LWS_PRE), 1038d4afb5ceSopenharmony_ci (!conceal_eom && (f & LWSSS_FLAG_EOM)) ? 1039d4afb5ceSopenharmony_ci LWS_WRITE_HTTP_FINAL : LWS_WRITE_HTTP) != 1040d4afb5ceSopenharmony_ci (int)lws_ptr_diff(p, buf + LWS_PRE)) { 1041d4afb5ceSopenharmony_ci lwsl_err("%s: write failed\n", __func__); 1042d4afb5ceSopenharmony_ci return -1; 1043d4afb5ceSopenharmony_ci } 1044d4afb5ceSopenharmony_ci 1045d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1046d4afb5ceSopenharmony_ci if ((h->info.flags & LWSSSINFLAGS_ACCEPTED) /* server */ && 1047d4afb5ceSopenharmony_ci (f & LWSSS_FLAG_EOM) && 1048d4afb5ceSopenharmony_ci lws_http_transaction_completed(wsi)) 1049d4afb5ceSopenharmony_ci return -1; 1050d4afb5ceSopenharmony_ci#else 1051d4afb5ceSopenharmony_ci lws_set_timeout(wsi, 0, 0); 1052d4afb5ceSopenharmony_ci#endif 1053d4afb5ceSopenharmony_ci break; 1054d4afb5ceSopenharmony_ci 1055d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 1056d4afb5ceSopenharmony_ci case LWS_CALLBACK_HTTP: 1057d4afb5ceSopenharmony_ci 1058d4afb5ceSopenharmony_ci if (!h) 1059d4afb5ceSopenharmony_ci return -1; 1060d4afb5ceSopenharmony_ci 1061d4afb5ceSopenharmony_ci lwsl_info("%s: LWS_CALLBACK_HTTP\n", __func__); 1062d4afb5ceSopenharmony_ci { 1063d4afb5ceSopenharmony_ci 1064d4afb5ceSopenharmony_ci h->txn_resp_set = 0; 1065d4afb5ceSopenharmony_ci h->txn_resp_pending = 1; 1066d4afb5ceSopenharmony_ci h->writeable_len = 0; 1067d4afb5ceSopenharmony_ci 1068d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H2) 1069d4afb5ceSopenharmony_ci m = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_METHOD); 1070d4afb5ceSopenharmony_ci if (m) { 1071d4afb5ceSopenharmony_ci if (lws_ss_alloc_set_metadata(h, "method", 1072d4afb5ceSopenharmony_ci lws_hdr_simple_ptr(wsi, 1073d4afb5ceSopenharmony_ci WSI_TOKEN_HTTP_COLON_METHOD), (unsigned int)m)) 1074d4afb5ceSopenharmony_ci return -1; 1075d4afb5ceSopenharmony_ci m = lws_hdr_total_length(wsi, WSI_TOKEN_HTTP_COLON_PATH); 1076d4afb5ceSopenharmony_ci if (m && lws_ss_alloc_set_metadata(h, "path", 1077d4afb5ceSopenharmony_ci lws_hdr_simple_ptr(wsi, 1078d4afb5ceSopenharmony_ci WSI_TOKEN_HTTP_COLON_PATH), (unsigned int)m)) 1079d4afb5ceSopenharmony_ci return -1; 1080d4afb5ceSopenharmony_ci } else 1081d4afb5ceSopenharmony_ci#endif 1082d4afb5ceSopenharmony_ci { 1083d4afb5ceSopenharmony_ci m = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI); 1084d4afb5ceSopenharmony_ci if (m) { 1085d4afb5ceSopenharmony_ci if (lws_ss_alloc_set_metadata(h, "path", 1086d4afb5ceSopenharmony_ci lws_hdr_simple_ptr(wsi, 1087d4afb5ceSopenharmony_ci WSI_TOKEN_GET_URI), (unsigned int)m)) 1088d4afb5ceSopenharmony_ci return -1; 1089d4afb5ceSopenharmony_ci if (lws_ss_alloc_set_metadata(h, "method", "GET", 3)) 1090d4afb5ceSopenharmony_ci return -1; 1091d4afb5ceSopenharmony_ci } else { 1092d4afb5ceSopenharmony_ci m = lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI); 1093d4afb5ceSopenharmony_ci if (m) { 1094d4afb5ceSopenharmony_ci if (lws_ss_alloc_set_metadata(h, "path", 1095d4afb5ceSopenharmony_ci lws_hdr_simple_ptr(wsi, 1096d4afb5ceSopenharmony_ci WSI_TOKEN_POST_URI), (unsigned int)m)) 1097d4afb5ceSopenharmony_ci return -1; 1098d4afb5ceSopenharmony_ci if (lws_ss_alloc_set_metadata(h, "method", "POST", 4)) 1099d4afb5ceSopenharmony_ci return -1; 1100d4afb5ceSopenharmony_ci } else { 1101d4afb5ceSopenharmony_ci m = lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI); 1102d4afb5ceSopenharmony_ci if (m) { 1103d4afb5ceSopenharmony_ci if (lws_ss_alloc_set_metadata(h, "path", 1104d4afb5ceSopenharmony_ci lws_hdr_simple_ptr(wsi, 1105d4afb5ceSopenharmony_ci WSI_TOKEN_PATCH_URI), (unsigned int)m)) 1106d4afb5ceSopenharmony_ci return -1; 1107d4afb5ceSopenharmony_ci if (lws_ss_alloc_set_metadata(h, "method", "PATCH", 5)) 1108d4afb5ceSopenharmony_ci return -1; 1109d4afb5ceSopenharmony_ci } 1110d4afb5ceSopenharmony_ci } 1111d4afb5ceSopenharmony_ci } 1112d4afb5ceSopenharmony_ci } 1113d4afb5ceSopenharmony_ci } 1114d4afb5ceSopenharmony_ci 1115d4afb5ceSopenharmony_ci if (!h->ss_dangling_connected) { 1116d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) 1117d4afb5ceSopenharmony_ci /* 1118d4afb5ceSopenharmony_ci * If any hanging caliper measurement, dump it, and free any tags 1119d4afb5ceSopenharmony_ci */ 1120d4afb5ceSopenharmony_ci lws_metrics_caliper_report_hist(h->cal_txn, (struct lws *)NULL); 1121d4afb5ceSopenharmony_ci#endif 1122d4afb5ceSopenharmony_ci wsi->client_suppress_CONNECTION_ERROR = 1; 1123d4afb5ceSopenharmony_ci if (h->prev_ss_state != LWSSSCS_CONNECTED) { 1124d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_CONNECTED); 1125d4afb5ceSopenharmony_ci if (r) 1126d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 1127d4afb5ceSopenharmony_ci } 1128d4afb5ceSopenharmony_ci } 1129d4afb5ceSopenharmony_ci 1130d4afb5ceSopenharmony_ci r = lws_ss_event_helper(h, LWSSSCS_SERVER_TXN); 1131d4afb5ceSopenharmony_ci if (r) 1132d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, 1133d4afb5ceSopenharmony_ci wsi, &h); 1134d4afb5ceSopenharmony_ci 1135d4afb5ceSopenharmony_ci return 0; 1136d4afb5ceSopenharmony_ci#endif 1137d4afb5ceSopenharmony_ci 1138d4afb5ceSopenharmony_ci default: 1139d4afb5ceSopenharmony_ci break; 1140d4afb5ceSopenharmony_ci } 1141d4afb5ceSopenharmony_ci 1142d4afb5ceSopenharmony_ci return lws_callback_http_dummy(wsi, reason, user, in, len); 1143d4afb5ceSopenharmony_ci} 1144d4afb5ceSopenharmony_ci 1145d4afb5ceSopenharmony_ciconst struct lws_protocols protocol_secstream_h1 = { 1146d4afb5ceSopenharmony_ci "lws-secstream-h1", 1147d4afb5ceSopenharmony_ci secstream_h1, 1148d4afb5ceSopenharmony_ci 0, 0, 0, NULL, 0 1149d4afb5ceSopenharmony_ci}; 1150d4afb5ceSopenharmony_ci 1151d4afb5ceSopenharmony_ci/* 1152d4afb5ceSopenharmony_ci * Munge connect info according to protocol-specific considerations... this 1153d4afb5ceSopenharmony_ci * usually means interpreting aux in a protocol-specific way and using the 1154d4afb5ceSopenharmony_ci * pieces at connection setup time, eg, http url pieces. 1155d4afb5ceSopenharmony_ci * 1156d4afb5ceSopenharmony_ci * len bytes of buf can be used for things with scope until after the actual 1157d4afb5ceSopenharmony_ci * connect. 1158d4afb5ceSopenharmony_ci */ 1159d4afb5ceSopenharmony_ci 1160d4afb5ceSopenharmony_cistatic int 1161d4afb5ceSopenharmony_cisecstream_connect_munge_h1(lws_ss_handle_t *h, char *buf, size_t len, 1162d4afb5ceSopenharmony_ci struct lws_client_connect_info *i, 1163d4afb5ceSopenharmony_ci union lws_ss_contemp *ct) 1164d4afb5ceSopenharmony_ci{ 1165d4afb5ceSopenharmony_ci const char *pbasis = h->policy->u.http.url; 1166d4afb5ceSopenharmony_ci size_t used_in, used_out; 1167d4afb5ceSopenharmony_ci lws_strexp_t exp; 1168d4afb5ceSopenharmony_ci 1169d4afb5ceSopenharmony_ci /* i.path on entry is used to override the policy urlpath if not "" */ 1170d4afb5ceSopenharmony_ci 1171d4afb5ceSopenharmony_ci if (i->path[0]) 1172d4afb5ceSopenharmony_ci pbasis = i->path; 1173d4afb5ceSopenharmony_ci 1174d4afb5ceSopenharmony_ci if (!pbasis) 1175d4afb5ceSopenharmony_ci return 0; 1176d4afb5ceSopenharmony_ci 1177d4afb5ceSopenharmony_ci /* uncomment to force h1 */ 1178d4afb5ceSopenharmony_ci // i->alpn = "http/1.1"; 1179d4afb5ceSopenharmony_ci 1180d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SS_RIDESHARE) 1181d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_HTTP_MULTIPART) 1182d4afb5ceSopenharmony_ci i->ssl_connection |= LCCSCF_HTTP_MULTIPART_MIME; 1183d4afb5ceSopenharmony_ci 1184d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED) 1185d4afb5ceSopenharmony_ci i->ssl_connection |= LCCSCF_HTTP_X_WWW_FORM_URLENCODED; 1186d4afb5ceSopenharmony_ci#endif 1187d4afb5ceSopenharmony_ci 1188d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_HTTP_CACHE_COOKIES) 1189d4afb5ceSopenharmony_ci i->ssl_connection |= LCCSCF_CACHE_COOKIES; 1190d4afb5ceSopenharmony_ci 1191d4afb5ceSopenharmony_ci /* protocol aux is the path part */ 1192d4afb5ceSopenharmony_ci 1193d4afb5ceSopenharmony_ci i->path = buf; 1194d4afb5ceSopenharmony_ci 1195d4afb5ceSopenharmony_ci /* skip the unnessary '/' */ 1196d4afb5ceSopenharmony_ci if (*pbasis == '/') 1197d4afb5ceSopenharmony_ci pbasis = pbasis + 1; 1198d4afb5ceSopenharmony_ci 1199d4afb5ceSopenharmony_ci buf[0] = '/'; 1200d4afb5ceSopenharmony_ci 1201d4afb5ceSopenharmony_ci lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); 1202d4afb5ceSopenharmony_ci 1203d4afb5ceSopenharmony_ci if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), 1204d4afb5ceSopenharmony_ci &used_in, &used_out) != LSTRX_DONE) 1205d4afb5ceSopenharmony_ci return 1; 1206d4afb5ceSopenharmony_ci 1207d4afb5ceSopenharmony_ci return 0; 1208d4afb5ceSopenharmony_ci} 1209d4afb5ceSopenharmony_ci 1210d4afb5ceSopenharmony_ci 1211d4afb5ceSopenharmony_ciconst struct ss_pcols ss_pcol_h1 = { 1212d4afb5ceSopenharmony_ci "h1", 1213d4afb5ceSopenharmony_ci "http/1.1", 1214d4afb5ceSopenharmony_ci &protocol_secstream_h1, 1215d4afb5ceSopenharmony_ci secstream_connect_munge_h1, 1216d4afb5ceSopenharmony_ci NULL, NULL 1217d4afb5ceSopenharmony_ci}; 1218