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 25d4afb5ceSopenharmony_ci#include <private-lib-core.h> 26d4afb5ceSopenharmony_ci 27d4afb5ceSopenharmony_ciextern int 28d4afb5ceSopenharmony_cisecstream_h1(struct lws *wsi, enum lws_callback_reasons reason, void *user, 29d4afb5ceSopenharmony_ci void *in, size_t len); 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_cistatic int 32d4afb5ceSopenharmony_cisecstream_h2(struct lws *wsi, enum lws_callback_reasons reason, void *user, 33d4afb5ceSopenharmony_ci void *in, size_t len) 34d4afb5ceSopenharmony_ci{ 35d4afb5ceSopenharmony_ci lws_ss_handle_t *h = (lws_ss_handle_t *)lws_get_opaque_user_data(wsi); 36d4afb5ceSopenharmony_ci lws_ss_state_return_t r; 37d4afb5ceSopenharmony_ci int n; 38d4afb5ceSopenharmony_ci 39d4afb5ceSopenharmony_ci switch (reason) { 40d4afb5ceSopenharmony_ci 41d4afb5ceSopenharmony_ci case LWS_CALLBACK_ESTABLISHED_CLIENT_HTTP: 42d4afb5ceSopenharmony_ci 43d4afb5ceSopenharmony_ci if (!h) 44d4afb5ceSopenharmony_ci return -1; 45d4afb5ceSopenharmony_ci 46d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) 47d4afb5ceSopenharmony_ci if (h->being_serialized) { 48d4afb5ceSopenharmony_ci /* 49d4afb5ceSopenharmony_ci * We are the proxy-side SS for a remote client... we 50d4afb5ceSopenharmony_ci * need to inform the client about the initial tx credit 51d4afb5ceSopenharmony_ci * to write to it that the remote h2 server set up 52d4afb5ceSopenharmony_ci */ 53d4afb5ceSopenharmony_ci lwsl_info("%s: reporting initial tx cr from server %d\n", 54d4afb5ceSopenharmony_ci __func__, wsi->txc.tx_cr); 55d4afb5ceSopenharmony_ci ss_proxy_onward_txcr((void *)(h + 1), wsi->txc.tx_cr); 56d4afb5ceSopenharmony_ci } 57d4afb5ceSopenharmony_ci#endif 58d4afb5ceSopenharmony_ci 59d4afb5ceSopenharmony_ci n = secstream_h1(wsi, reason, user, in, len); 60d4afb5ceSopenharmony_ci 61d4afb5ceSopenharmony_ci if (!n && (h->policy->flags & LWSSSPOLF_LONG_POLL)) { 62d4afb5ceSopenharmony_ci lwsl_notice("%s: h2 client %s entering LONG_POLL\n", 63d4afb5ceSopenharmony_ci __func__, lws_wsi_tag(wsi)); 64d4afb5ceSopenharmony_ci lws_h2_client_stream_long_poll_rxonly(wsi); 65d4afb5ceSopenharmony_ci } 66d4afb5ceSopenharmony_ci return n; 67d4afb5ceSopenharmony_ci 68d4afb5ceSopenharmony_ci case LWS_CALLBACK_CLOSED_CLIENT_HTTP: 69d4afb5ceSopenharmony_ci /* 70d4afb5ceSopenharmony_ci * Only allow the wsi that the handle believes is representing 71d4afb5ceSopenharmony_ci * him to report closure up to h1 72d4afb5ceSopenharmony_ci */ 73d4afb5ceSopenharmony_ci if (!h || h->wsi != wsi) 74d4afb5ceSopenharmony_ci return 0; 75d4afb5ceSopenharmony_ci 76d4afb5ceSopenharmony_ci break; 77d4afb5ceSopenharmony_ci 78d4afb5ceSopenharmony_ci case LWS_CALLBACK_COMPLETED_CLIENT_HTTP: 79d4afb5ceSopenharmony_ci 80d4afb5ceSopenharmony_ci if (!h) 81d4afb5ceSopenharmony_ci return -1; 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_ci // lwsl_err("%s: h2 COMPLETED_CLIENT_HTTP\n", __func__); 84d4afb5ceSopenharmony_ci r = 0; 85d4afb5ceSopenharmony_ci if (h->hanging_som) 86d4afb5ceSopenharmony_ci r = h->info.rx(ss_to_userobj(h), NULL, 0, LWSSS_FLAG_EOM); 87d4afb5ceSopenharmony_ci 88d4afb5ceSopenharmony_ci h->txn_ok = 1; 89d4afb5ceSopenharmony_ci lws_cancel_service(lws_get_context(wsi)); /* abort poll wait */ 90d4afb5ceSopenharmony_ci if (h->hanging_som && r == LWSSSSRET_DESTROY_ME) 91d4afb5ceSopenharmony_ci return _lws_ss_handle_state_ret_CAN_DESTROY_HANDLE(r, wsi, &h); 92d4afb5ceSopenharmony_ci h->hanging_som = 0; 93d4afb5ceSopenharmony_ci break; 94d4afb5ceSopenharmony_ci 95d4afb5ceSopenharmony_ci case LWS_CALLBACK_WSI_TX_CREDIT_GET: 96d4afb5ceSopenharmony_ci 97d4afb5ceSopenharmony_ci if (!h) 98d4afb5ceSopenharmony_ci return -1; 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci /* 101d4afb5ceSopenharmony_ci * The peer has sent us additional tx credit... 102d4afb5ceSopenharmony_ci */ 103d4afb5ceSopenharmony_ci lwsl_info("%s: LWS_CALLBACK_WSI_TX_CREDIT_GET: %d\n", 104d4afb5ceSopenharmony_ci __func__, (int)len); 105d4afb5ceSopenharmony_ci 106d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SECURE_STREAMS_PROXY_API) 107d4afb5ceSopenharmony_ci if (h->being_serialized) 108d4afb5ceSopenharmony_ci /* we are the proxy-side SS for a remote client */ 109d4afb5ceSopenharmony_ci ss_proxy_onward_txcr((void *)(h + 1), (int)len); 110d4afb5ceSopenharmony_ci#endif 111d4afb5ceSopenharmony_ci break; 112d4afb5ceSopenharmony_ci 113d4afb5ceSopenharmony_ci default: 114d4afb5ceSopenharmony_ci break; 115d4afb5ceSopenharmony_ci } 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_ci return secstream_h1(wsi, reason, user, in, len); 118d4afb5ceSopenharmony_ci} 119d4afb5ceSopenharmony_ci 120d4afb5ceSopenharmony_ciconst struct lws_protocols protocol_secstream_h2 = { 121d4afb5ceSopenharmony_ci "lws-secstream-h2", 122d4afb5ceSopenharmony_ci secstream_h2, 123d4afb5ceSopenharmony_ci 0, 0, 0, NULL, 0 124d4afb5ceSopenharmony_ci}; 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci/* 127d4afb5ceSopenharmony_ci * Munge connect info according to protocol-specific considerations... this 128d4afb5ceSopenharmony_ci * usually means interpreting aux in a protocol-specific way and using the 129d4afb5ceSopenharmony_ci * pieces at connection setup time, eg, http url pieces. 130d4afb5ceSopenharmony_ci * 131d4afb5ceSopenharmony_ci * len bytes of buf can be used for things with scope until after the actual 132d4afb5ceSopenharmony_ci * connect. 133d4afb5ceSopenharmony_ci */ 134d4afb5ceSopenharmony_ci 135d4afb5ceSopenharmony_ciint 136d4afb5ceSopenharmony_cisecstream_connect_munge_h2(lws_ss_handle_t *h, char *buf, size_t len, 137d4afb5ceSopenharmony_ci struct lws_client_connect_info *i, 138d4afb5ceSopenharmony_ci union lws_ss_contemp *ct) 139d4afb5ceSopenharmony_ci{ 140d4afb5ceSopenharmony_ci const char *pbasis = h->policy->u.http.url; 141d4afb5ceSopenharmony_ci size_t used_in, used_out; 142d4afb5ceSopenharmony_ci lws_strexp_t exp; 143d4afb5ceSopenharmony_ci 144d4afb5ceSopenharmony_ci /* i.path on entry is used to override the policy urlpath if not "" */ 145d4afb5ceSopenharmony_ci 146d4afb5ceSopenharmony_ci if (i->path[0]) 147d4afb5ceSopenharmony_ci pbasis = i->path; 148d4afb5ceSopenharmony_ci 149d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM) 150d4afb5ceSopenharmony_ci i->ssl_connection |= LCCSCF_H2_QUIRK_NGHTTP2_END_STREAM; 151d4afb5ceSopenharmony_ci 152d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR) 153d4afb5ceSopenharmony_ci i->ssl_connection |= LCCSCF_H2_QUIRK_OVERFLOWS_TXCR; 154d4afb5ceSopenharmony_ci 155d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_HTTP_MULTIPART) 156d4afb5ceSopenharmony_ci i->ssl_connection |= LCCSCF_HTTP_MULTIPART_MIME; 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_HTTP_X_WWW_FORM_URLENCODED) 159d4afb5ceSopenharmony_ci i->ssl_connection |= LCCSCF_HTTP_X_WWW_FORM_URLENCODED; 160d4afb5ceSopenharmony_ci 161d4afb5ceSopenharmony_ci if (h->policy->flags & LWSSSPOLF_HTTP_CACHE_COOKIES) 162d4afb5ceSopenharmony_ci i->ssl_connection |= LCCSCF_CACHE_COOKIES; 163d4afb5ceSopenharmony_ci 164d4afb5ceSopenharmony_ci i->ssl_connection |= LCCSCF_PIPELINE; 165d4afb5ceSopenharmony_ci 166d4afb5ceSopenharmony_ci i->alpn = "h2"; 167d4afb5ceSopenharmony_ci 168d4afb5ceSopenharmony_ci /* initial peer tx credit */ 169d4afb5ceSopenharmony_ci 170d4afb5ceSopenharmony_ci if (h->info.manual_initial_tx_credit) { 171d4afb5ceSopenharmony_ci i->ssl_connection |= LCCSCF_H2_MANUAL_RXFLOW; 172d4afb5ceSopenharmony_ci i->manual_initial_tx_credit = h->info.manual_initial_tx_credit; 173d4afb5ceSopenharmony_ci lwsl_info("%s: initial txcr %d\n", __func__, 174d4afb5ceSopenharmony_ci i->manual_initial_tx_credit); 175d4afb5ceSopenharmony_ci } 176d4afb5ceSopenharmony_ci 177d4afb5ceSopenharmony_ci if (!pbasis) 178d4afb5ceSopenharmony_ci return 0; 179d4afb5ceSopenharmony_ci 180d4afb5ceSopenharmony_ci /* protocol aux is the path part */ 181d4afb5ceSopenharmony_ci 182d4afb5ceSopenharmony_ci i->path = buf; 183d4afb5ceSopenharmony_ci buf[0] = '/'; 184d4afb5ceSopenharmony_ci 185d4afb5ceSopenharmony_ci lws_strexp_init(&exp, (void *)h, lws_ss_exp_cb_metadata, buf + 1, len - 1); 186d4afb5ceSopenharmony_ci 187d4afb5ceSopenharmony_ci if (lws_strexp_expand(&exp, pbasis, strlen(pbasis), 188d4afb5ceSopenharmony_ci &used_in, &used_out) != LSTRX_DONE) 189d4afb5ceSopenharmony_ci return 1; 190d4afb5ceSopenharmony_ci 191d4afb5ceSopenharmony_ci return 0; 192d4afb5ceSopenharmony_ci} 193d4afb5ceSopenharmony_ci 194d4afb5ceSopenharmony_cistatic int 195d4afb5ceSopenharmony_cisecstream_tx_credit_add_h2(lws_ss_handle_t *h, int add) 196d4afb5ceSopenharmony_ci{ 197d4afb5ceSopenharmony_ci lwsl_info("%s: %s: add %d\n", __func__, lws_ss_tag(h), add); 198d4afb5ceSopenharmony_ci if (h->wsi) 199d4afb5ceSopenharmony_ci return lws_h2_update_peer_txcredit(h->wsi, (unsigned int)LWS_H2_STREAM_SID, add); 200d4afb5ceSopenharmony_ci 201d4afb5ceSopenharmony_ci return 0; 202d4afb5ceSopenharmony_ci} 203d4afb5ceSopenharmony_ci 204d4afb5ceSopenharmony_cistatic int 205d4afb5ceSopenharmony_cisecstream_tx_credit_est_h2(lws_ss_handle_t *h) 206d4afb5ceSopenharmony_ci{ 207d4afb5ceSopenharmony_ci if (h->wsi) { 208d4afb5ceSopenharmony_ci lwsl_info("%s: %s: est %d\n", __func__, lws_ss_tag(h), 209d4afb5ceSopenharmony_ci lws_h2_get_peer_txcredit_estimate(h->wsi)); 210d4afb5ceSopenharmony_ci 211d4afb5ceSopenharmony_ci return lws_h2_get_peer_txcredit_estimate(h->wsi); 212d4afb5ceSopenharmony_ci } 213d4afb5ceSopenharmony_ci 214d4afb5ceSopenharmony_ci lwsl_info("%s: %s: Unknown (0)\n", __func__, lws_ss_tag(h)); 215d4afb5ceSopenharmony_ci 216d4afb5ceSopenharmony_ci return 0; 217d4afb5ceSopenharmony_ci} 218d4afb5ceSopenharmony_ci 219d4afb5ceSopenharmony_ciconst struct ss_pcols ss_pcol_h2 = { 220d4afb5ceSopenharmony_ci "h2", 221d4afb5ceSopenharmony_ci "h2", 222d4afb5ceSopenharmony_ci &protocol_secstream_h2, 223d4afb5ceSopenharmony_ci secstream_connect_munge_h2, 224d4afb5ceSopenharmony_ci secstream_tx_credit_add_h2, 225d4afb5ceSopenharmony_ci secstream_tx_credit_est_h2 226d4afb5ceSopenharmony_ci}; 227