1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 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 * C++ classes for Secure Streams 25d4afb5ceSopenharmony_ci */ 26d4afb5ceSopenharmony_ci 27d4afb5ceSopenharmony_ci#include <libwebsockets.hxx> 28d4afb5ceSopenharmony_ci 29d4afb5ceSopenharmony_cistatic const char *pcols[] = { 30d4afb5ceSopenharmony_ci "http://", /* LWSSSP_H1 */ 31d4afb5ceSopenharmony_ci "https://", 32d4afb5ceSopenharmony_ci "h2://", /* LWSSSP_H2 */ 33d4afb5ceSopenharmony_ci "h2s://", 34d4afb5ceSopenharmony_ci "ws://", /* LWSSSP_WS */ 35d4afb5ceSopenharmony_ci "wss://", 36d4afb5ceSopenharmony_ci "mqtt://", /* LWSSSP_MQTT */ 37d4afb5ceSopenharmony_ci "mqtts://", 38d4afb5ceSopenharmony_ci "raw://", /* LWSSSP_RAW */ 39d4afb5ceSopenharmony_ci "raws://", 40d4afb5ceSopenharmony_ci}; 41d4afb5ceSopenharmony_ci 42d4afb5ceSopenharmony_cistatic const uint8_t pcols_len[] = { 43d4afb5ceSopenharmony_ci 7, 8, 5, 6, 5, 6, 7, 8, 6, 7 44d4afb5ceSopenharmony_ci}; 45d4afb5ceSopenharmony_ci 46d4afb5ceSopenharmony_cistatic const uint16_t pcols_port[] = { 47d4afb5ceSopenharmony_ci 80, 443, 443, 443, 80, 443, 1883, 8883, 80, 443 48d4afb5ceSopenharmony_ci}; 49d4afb5ceSopenharmony_ci 50d4afb5ceSopenharmony_cilss::lss(lws_ctx_t _ctx, std::string _uri, lsscomp_t _comp, bool _psh, 51d4afb5ceSopenharmony_ci lws_sscb_rx rx, lws_sscb_tx tx, lws_sscb_state state) 52d4afb5ceSopenharmony_ci{ 53d4afb5ceSopenharmony_ci const char *p, *urlpath; 54d4afb5ceSopenharmony_ci lws_ss_info_t ssi; 55d4afb5ceSopenharmony_ci int n, port; 56d4afb5ceSopenharmony_ci 57d4afb5ceSopenharmony_ci memset(&ssi, 0, sizeof(ssi)); 58d4afb5ceSopenharmony_ci memset(&pol, 0, sizeof(pol)); 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci ctx = _ctx; 61d4afb5ceSopenharmony_ci comp = _comp; 62d4afb5ceSopenharmony_ci comp_done = 0; 63d4afb5ceSopenharmony_ci rxlen = 0; 64d4afb5ceSopenharmony_ci 65d4afb5ceSopenharmony_ci /* 66d4afb5ceSopenharmony_ci * We have a common stub userdata, our "real" userdata is in the 67d4afb5ceSopenharmony_ci * derived class members. The Opaque user pointer points to the 68d4afb5ceSopenharmony_ci * lss itself. 69d4afb5ceSopenharmony_ci */ 70d4afb5ceSopenharmony_ci 71d4afb5ceSopenharmony_ci ssi.handle_offset = offsetof(lssPriv, lssPriv::m_ss); 72d4afb5ceSopenharmony_ci ssi.opaque_user_data_offset = offsetof(lssPriv, lssPriv::m_plss); 73d4afb5ceSopenharmony_ci 74d4afb5ceSopenharmony_ci ssi.user_alloc = sizeof(lssPriv); 75d4afb5ceSopenharmony_ci ssi.rx = rx; 76d4afb5ceSopenharmony_ci ssi.tx = tx; 77d4afb5ceSopenharmony_ci ssi.state = state; 78d4afb5ceSopenharmony_ci ssi.policy = &pol; /* we will provide our own policy */ 79d4afb5ceSopenharmony_ci 80d4afb5ceSopenharmony_ci /* 81d4afb5ceSopenharmony_ci * _uri is like "https://warmcat.com:443/index.html"... we need to 82d4afb5ceSopenharmony_ci * deconstruct it into its policy implications 83d4afb5ceSopenharmony_ci */ 84d4afb5ceSopenharmony_ci 85d4afb5ceSopenharmony_ci uri = strdup(_uri.c_str()); 86d4afb5ceSopenharmony_ci 87d4afb5ceSopenharmony_ci for (n = 0; n < LWS_ARRAY_SIZE(pcols); n++) 88d4afb5ceSopenharmony_ci if (!strncmp(uri, pcols[n], pcols_len[n])) 89d4afb5ceSopenharmony_ci break; 90d4afb5ceSopenharmony_ci 91d4afb5ceSopenharmony_ci if (n == LWS_ARRAY_SIZE(pcols)) 92d4afb5ceSopenharmony_ci throw lssException("unknown uri protocol://"); 93d4afb5ceSopenharmony_ci 94d4afb5ceSopenharmony_ci pol.protocol = n >> 1; 95d4afb5ceSopenharmony_ci if (n & 1) 96d4afb5ceSopenharmony_ci pol.flags |= LWSSSPOLF_TLS; 97d4afb5ceSopenharmony_ci 98d4afb5ceSopenharmony_ci n = pcols_port[n]; 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci if (lws_parse_uri(uri, &p, &pol.endpoint, &n, &urlpath)) 101d4afb5ceSopenharmony_ci throw lssException("unable to parse uri://"); 102d4afb5ceSopenharmony_ci 103d4afb5ceSopenharmony_ci pol.port = (uint16_t)n; 104d4afb5ceSopenharmony_ci 105d4afb5ceSopenharmony_ci if (pol.protocol <= LWSSSP_WS) { 106d4afb5ceSopenharmony_ci pol.u.http.url = urlpath; 107d4afb5ceSopenharmony_ci 108d4afb5ceSopenharmony_ci /* 109d4afb5ceSopenharmony_ci * These are workarounds for common h2 server noncompliances 110d4afb5ceSopenharmony_ci */ 111d4afb5ceSopenharmony_ci 112d4afb5ceSopenharmony_ci pol.flags |= LWSSSPOLF_QUIRK_NGHTTP2_END_STREAM | 113d4afb5ceSopenharmony_ci LWSSSPOLF_H2_QUIRK_OVERFLOWS_TXCR | 114d4afb5ceSopenharmony_ci LWSSSPOLF_H2_QUIRK_UNCLEAN_HPACK_STATE; 115d4afb5ceSopenharmony_ci 116d4afb5ceSopenharmony_ci if (pol.protocol < LWSSSP_WS) 117d4afb5ceSopenharmony_ci pol.u.http.method = _psh ? "POST" : "GET"; 118d4afb5ceSopenharmony_ci } 119d4afb5ceSopenharmony_ci 120d4afb5ceSopenharmony_ci us_start = lws_now_usecs(); 121d4afb5ceSopenharmony_ci 122d4afb5ceSopenharmony_ci if (lws_ss_create(ctx, 0, &ssi, (void *)this, &m_ss, NULL, NULL)) 123d4afb5ceSopenharmony_ci goto blow; 124d4afb5ceSopenharmony_ci 125d4afb5ceSopenharmony_ci if (pol.protocol <= LWSSSP_WS) 126d4afb5ceSopenharmony_ci lws_ss_client_connect(m_ss); 127d4afb5ceSopenharmony_ci 128d4afb5ceSopenharmony_ci return; 129d4afb5ceSopenharmony_ci 130d4afb5ceSopenharmony_ciblow: 131d4afb5ceSopenharmony_ci if (uri) 132d4afb5ceSopenharmony_ci free(uri); 133d4afb5ceSopenharmony_ci throw lssException("ss creation failed"); 134d4afb5ceSopenharmony_ci} 135d4afb5ceSopenharmony_ci 136d4afb5ceSopenharmony_cilss::~lss() 137d4afb5ceSopenharmony_ci{ 138d4afb5ceSopenharmony_ci if (uri) 139d4afb5ceSopenharmony_ci free(uri); 140d4afb5ceSopenharmony_ci if (m_ss) 141d4afb5ceSopenharmony_ci lws_ss_destroy(&m_ss); 142d4afb5ceSopenharmony_ci} 143d4afb5ceSopenharmony_ci 144d4afb5ceSopenharmony_ciint lss::call_completion(lws_ss_constate_t state) 145d4afb5ceSopenharmony_ci{ 146d4afb5ceSopenharmony_ci if (comp_done) 147d4afb5ceSopenharmony_ci return 0; 148d4afb5ceSopenharmony_ci if (!comp) 149d4afb5ceSopenharmony_ci return 0; 150d4afb5ceSopenharmony_ci 151d4afb5ceSopenharmony_ci comp_done = 1; 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ci return comp(this, state, NULL); 154d4afb5ceSopenharmony_ci} 155