1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 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#include "private-lib-tls-mbedtls.h" 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_civoid 29d4afb5ceSopenharmony_cilws_ssl_destroy(struct lws_vhost *vhost) 30d4afb5ceSopenharmony_ci{ 31d4afb5ceSopenharmony_ci if (!lws_check_opt(vhost->context->options, 32d4afb5ceSopenharmony_ci LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) 33d4afb5ceSopenharmony_ci return; 34d4afb5ceSopenharmony_ci 35d4afb5ceSopenharmony_ci if (vhost->tls.ssl_ctx) 36d4afb5ceSopenharmony_ci SSL_CTX_free(vhost->tls.ssl_ctx); 37d4afb5ceSopenharmony_ci if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx) 38d4afb5ceSopenharmony_ci SSL_CTX_free(vhost->tls.ssl_client_ctx); 39d4afb5ceSopenharmony_ci 40d4afb5ceSopenharmony_ci if (vhost->tls.x509_client_CA) 41d4afb5ceSopenharmony_ci X509_free(vhost->tls.x509_client_CA); 42d4afb5ceSopenharmony_ci} 43d4afb5ceSopenharmony_ci 44d4afb5ceSopenharmony_ciint 45d4afb5ceSopenharmony_cilws_ssl_capable_read(struct lws *wsi, unsigned char *buf, size_t len) 46d4afb5ceSopenharmony_ci{ 47d4afb5ceSopenharmony_ci struct lws_context *context = wsi->a.context; 48d4afb5ceSopenharmony_ci struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; 49d4afb5ceSopenharmony_ci int n = 0, m; 50d4afb5ceSopenharmony_ci 51d4afb5ceSopenharmony_ci if (!wsi->tls.ssl) 52d4afb5ceSopenharmony_ci return lws_ssl_capable_read_no_ssl(wsi, buf, len); 53d4afb5ceSopenharmony_ci 54d4afb5ceSopenharmony_ci errno = 0; 55d4afb5ceSopenharmony_ci n = SSL_read(wsi->tls.ssl, buf, (int)len); 56d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_FREERTOS) 57d4afb5ceSopenharmony_ci if (!n && errno == LWS_ENOTCONN) { 58d4afb5ceSopenharmony_ci lwsl_debug("%s: SSL_read ENOTCONN\n", lws_wsi_tag(wsi)); 59d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_ERROR; 60d4afb5ceSopenharmony_ci } 61d4afb5ceSopenharmony_ci#endif 62d4afb5ceSopenharmony_ci 63d4afb5ceSopenharmony_ci lwsl_debug("%s: %s: SSL_read says %d\n", __func__, lws_wsi_tag(wsi), n); 64d4afb5ceSopenharmony_ci /* manpage: returning 0 means connection shut down */ 65d4afb5ceSopenharmony_ci if (!n) { 66d4afb5ceSopenharmony_ci wsi->socket_is_permanently_unusable = 1; 67d4afb5ceSopenharmony_ci 68d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_ERROR; 69d4afb5ceSopenharmony_ci } 70d4afb5ceSopenharmony_ci 71d4afb5ceSopenharmony_ci if (n < 0) { 72d4afb5ceSopenharmony_ci m = SSL_get_error(wsi->tls.ssl, n); 73d4afb5ceSopenharmony_ci lwsl_debug("%s: %s: ssl err %d errno %d\n", __func__, lws_wsi_tag(wsi), m, errno); 74d4afb5ceSopenharmony_ci if (errno == LWS_ENOTCONN) 75d4afb5ceSopenharmony_ci /* If the socket isn't connected anymore, bail out. */ 76d4afb5ceSopenharmony_ci goto do_err1; 77d4afb5ceSopenharmony_ci 78d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_FREERTOS) 79d4afb5ceSopenharmony_ci if (errno == LWS_ECONNABORTED) 80d4afb5ceSopenharmony_ci goto do_err1; 81d4afb5ceSopenharmony_ci#endif 82d4afb5ceSopenharmony_ci 83d4afb5ceSopenharmony_ci if (m == SSL_ERROR_ZERO_RETURN || 84d4afb5ceSopenharmony_ci m == SSL_ERROR_SYSCALL) 85d4afb5ceSopenharmony_ci goto do_err; 86d4afb5ceSopenharmony_ci 87d4afb5ceSopenharmony_ci if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) { 88d4afb5ceSopenharmony_ci lwsl_debug("%s: WANT_READ\n", __func__); 89d4afb5ceSopenharmony_ci lwsl_debug("%s: LWS_SSL_CAPABLE_MORE_SERVICE\n", lws_wsi_tag(wsi)); 90d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_MORE_SERVICE; 91d4afb5ceSopenharmony_ci } 92d4afb5ceSopenharmony_ci if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) { 93d4afb5ceSopenharmony_ci lwsl_info("%s: WANT_WRITE\n", __func__); 94d4afb5ceSopenharmony_ci lwsl_debug("%s: LWS_SSL_CAPABLE_MORE_SERVICE\n", lws_wsi_tag(wsi)); 95d4afb5ceSopenharmony_ci wsi->tls_read_wanted_write = 1; 96d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 97d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_MORE_SERVICE; 98d4afb5ceSopenharmony_ci } 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_cido_err1: 101d4afb5ceSopenharmony_ci wsi->socket_is_permanently_unusable = 1; 102d4afb5ceSopenharmony_ci 103d4afb5ceSopenharmony_cido_err: 104d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) 105d4afb5ceSopenharmony_ci if (wsi->a.vhost) 106d4afb5ceSopenharmony_ci lws_metric_event(wsi->a.vhost->mt_traffic_rx, METRES_NOGO, 0); 107d4afb5ceSopenharmony_ci#endif 108d4afb5ceSopenharmony_ci 109d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_ERROR; 110d4afb5ceSopenharmony_ci } 111d4afb5ceSopenharmony_ci 112d4afb5ceSopenharmony_ci#if defined(LWS_TLS_LOG_PLAINTEXT_RX) 113d4afb5ceSopenharmony_ci /* 114d4afb5ceSopenharmony_ci * If using mbedtls type tls library, this is the earliest point for all 115d4afb5ceSopenharmony_ci * paths to dump what was received as decrypted data from the tls tunnel 116d4afb5ceSopenharmony_ci */ 117d4afb5ceSopenharmony_ci lwsl_notice("%s: len %d\n", __func__, n); 118d4afb5ceSopenharmony_ci lwsl_hexdump_notice(buf, (size_t)n); 119d4afb5ceSopenharmony_ci#endif 120d4afb5ceSopenharmony_ci 121d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) 122d4afb5ceSopenharmony_ci if (wsi->a.vhost) 123d4afb5ceSopenharmony_ci lws_metric_event(wsi->a.vhost->mt_traffic_rx, 124d4afb5ceSopenharmony_ci METRES_GO /* rx */, (u_mt_t)n); 125d4afb5ceSopenharmony_ci#endif 126d4afb5ceSopenharmony_ci 127d4afb5ceSopenharmony_ci /* 128d4afb5ceSopenharmony_ci * if it was our buffer that limited what we read, 129d4afb5ceSopenharmony_ci * check if SSL has additional data pending inside SSL buffers. 130d4afb5ceSopenharmony_ci * 131d4afb5ceSopenharmony_ci * Because these won't signal at the network layer with POLLIN 132d4afb5ceSopenharmony_ci * and if we don't realize, this data will sit there forever 133d4afb5ceSopenharmony_ci */ 134d4afb5ceSopenharmony_ci if (n != (int)len) 135d4afb5ceSopenharmony_ci goto bail; 136d4afb5ceSopenharmony_ci if (!wsi->tls.ssl) 137d4afb5ceSopenharmony_ci goto bail; 138d4afb5ceSopenharmony_ci 139d4afb5ceSopenharmony_ci if (SSL_pending(wsi->tls.ssl)) { 140d4afb5ceSopenharmony_ci if (lws_dll2_is_detached(&wsi->tls.dll_pending_tls)) 141d4afb5ceSopenharmony_ci lws_dll2_add_head(&wsi->tls.dll_pending_tls, 142d4afb5ceSopenharmony_ci &pt->tls.dll_pending_tls_owner); 143d4afb5ceSopenharmony_ci } else 144d4afb5ceSopenharmony_ci __lws_ssl_remove_wsi_from_buffered_list(wsi); 145d4afb5ceSopenharmony_ci 146d4afb5ceSopenharmony_ci return n; 147d4afb5ceSopenharmony_cibail: 148d4afb5ceSopenharmony_ci lws_ssl_remove_wsi_from_buffered_list(wsi); 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci return n; 151d4afb5ceSopenharmony_ci} 152d4afb5ceSopenharmony_ci 153d4afb5ceSopenharmony_ciint 154d4afb5ceSopenharmony_cilws_ssl_pending(struct lws *wsi) 155d4afb5ceSopenharmony_ci{ 156d4afb5ceSopenharmony_ci if (!wsi->tls.ssl) 157d4afb5ceSopenharmony_ci return 0; 158d4afb5ceSopenharmony_ci 159d4afb5ceSopenharmony_ci return SSL_pending(wsi->tls.ssl); 160d4afb5ceSopenharmony_ci} 161d4afb5ceSopenharmony_ci 162d4afb5ceSopenharmony_ciint 163d4afb5ceSopenharmony_cilws_ssl_capable_write(struct lws *wsi, unsigned char *buf, size_t len) 164d4afb5ceSopenharmony_ci{ 165d4afb5ceSopenharmony_ci int n, m; 166d4afb5ceSopenharmony_ci 167d4afb5ceSopenharmony_ci#if defined(LWS_TLS_LOG_PLAINTEXT_TX) 168d4afb5ceSopenharmony_ci /* 169d4afb5ceSopenharmony_ci * If using mbedtls type tls library, this is the last point for all 170d4afb5ceSopenharmony_ci * paths before sending data into the tls tunnel, where you can dump it 171d4afb5ceSopenharmony_ci * and see what is being sent. 172d4afb5ceSopenharmony_ci */ 173d4afb5ceSopenharmony_ci lwsl_notice("%s: len %d\n", __func__, (int)len); 174d4afb5ceSopenharmony_ci lwsl_hexdump_notice(buf, len); 175d4afb5ceSopenharmony_ci#endif 176d4afb5ceSopenharmony_ci 177d4afb5ceSopenharmony_ci if (!wsi->tls.ssl) 178d4afb5ceSopenharmony_ci return lws_ssl_capable_write_no_ssl(wsi, buf, len); 179d4afb5ceSopenharmony_ci 180d4afb5ceSopenharmony_ci n = SSL_write(wsi->tls.ssl, buf, (int)len); 181d4afb5ceSopenharmony_ci if (n > 0) { 182d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) 183d4afb5ceSopenharmony_ci if (wsi->a.vhost) 184d4afb5ceSopenharmony_ci lws_metric_event(wsi->a.vhost->mt_traffic_tx, 185d4afb5ceSopenharmony_ci METRES_GO, (u_mt_t)n); 186d4afb5ceSopenharmony_ci#endif 187d4afb5ceSopenharmony_ci return n; 188d4afb5ceSopenharmony_ci } 189d4afb5ceSopenharmony_ci 190d4afb5ceSopenharmony_ci m = SSL_get_error(wsi->tls.ssl, n); 191d4afb5ceSopenharmony_ci if (m != SSL_ERROR_SYSCALL) { 192d4afb5ceSopenharmony_ci if (m == SSL_ERROR_WANT_READ || SSL_want_read(wsi->tls.ssl)) { 193d4afb5ceSopenharmony_ci lwsl_notice("%s: want read\n", __func__); 194d4afb5ceSopenharmony_ci 195d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_MORE_SERVICE; 196d4afb5ceSopenharmony_ci } 197d4afb5ceSopenharmony_ci 198d4afb5ceSopenharmony_ci if (m == SSL_ERROR_WANT_WRITE || SSL_want_write(wsi->tls.ssl)) { 199d4afb5ceSopenharmony_ci lws_set_blocking_send(wsi); 200d4afb5ceSopenharmony_ci lwsl_debug("%s: want write\n", __func__); 201d4afb5ceSopenharmony_ci 202d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_MORE_SERVICE; 203d4afb5ceSopenharmony_ci } 204d4afb5ceSopenharmony_ci } 205d4afb5ceSopenharmony_ci 206d4afb5ceSopenharmony_ci lwsl_debug("%s failed: %d\n",__func__, m); 207d4afb5ceSopenharmony_ci wsi->socket_is_permanently_unusable = 1; 208d4afb5ceSopenharmony_ci 209d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) 210d4afb5ceSopenharmony_ci if (wsi->a.vhost) 211d4afb5ceSopenharmony_ci lws_metric_event(wsi->a.vhost->mt_traffic_tx, 212d4afb5ceSopenharmony_ci METRES_NOGO, (u_mt_t)n); 213d4afb5ceSopenharmony_ci#endif 214d4afb5ceSopenharmony_ci 215d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_ERROR; 216d4afb5ceSopenharmony_ci} 217d4afb5ceSopenharmony_ci 218d4afb5ceSopenharmony_ciint openssl_SSL_CTX_private_data_index; 219d4afb5ceSopenharmony_ci 220d4afb5ceSopenharmony_civoid 221d4afb5ceSopenharmony_cilws_ssl_info_callback(const SSL *ssl, int where, int ret) 222d4afb5ceSopenharmony_ci{ 223d4afb5ceSopenharmony_ci struct lws *wsi; 224d4afb5ceSopenharmony_ci struct lws_context *context; 225d4afb5ceSopenharmony_ci struct lws_ssl_info si; 226d4afb5ceSopenharmony_ci 227d4afb5ceSopenharmony_ci context = (struct lws_context *)SSL_CTX_get_ex_data( 228d4afb5ceSopenharmony_ci SSL_get_SSL_CTX(ssl), 229d4afb5ceSopenharmony_ci openssl_SSL_CTX_private_data_index); 230d4afb5ceSopenharmony_ci if (!context) 231d4afb5ceSopenharmony_ci return; 232d4afb5ceSopenharmony_ci wsi = wsi_from_fd(context, SSL_get_fd(ssl)); 233d4afb5ceSopenharmony_ci if (!wsi) 234d4afb5ceSopenharmony_ci return; 235d4afb5ceSopenharmony_ci 236d4afb5ceSopenharmony_ci if (!(where & wsi->a.vhost->tls.ssl_info_event_mask)) 237d4afb5ceSopenharmony_ci return; 238d4afb5ceSopenharmony_ci 239d4afb5ceSopenharmony_ci si.where = where; 240d4afb5ceSopenharmony_ci si.ret = ret; 241d4afb5ceSopenharmony_ci 242d4afb5ceSopenharmony_ci if (user_callback_handle_rxflow(wsi->a.protocol->callback, 243d4afb5ceSopenharmony_ci wsi, LWS_CALLBACK_SSL_INFO, 244d4afb5ceSopenharmony_ci wsi->user_space, &si, 0)) 245d4afb5ceSopenharmony_ci lws_set_timeout(wsi, PENDING_TIMEOUT_KILLED_BY_SSL_INFO, -1); 246d4afb5ceSopenharmony_ci} 247d4afb5ceSopenharmony_ci 248d4afb5ceSopenharmony_ci 249d4afb5ceSopenharmony_ciint 250d4afb5ceSopenharmony_cilws_ssl_close(struct lws *wsi) 251d4afb5ceSopenharmony_ci{ 252d4afb5ceSopenharmony_ci lws_sockfd_type n; 253d4afb5ceSopenharmony_ci 254d4afb5ceSopenharmony_ci if (!wsi->tls.ssl) 255d4afb5ceSopenharmony_ci return 0; /* not handled */ 256d4afb5ceSopenharmony_ci 257d4afb5ceSopenharmony_ci#if defined (LWS_HAVE_SSL_SET_INFO_CALLBACK) 258d4afb5ceSopenharmony_ci /* kill ssl callbacks, becausse we will remove the fd from the 259d4afb5ceSopenharmony_ci * table linking it to the wsi 260d4afb5ceSopenharmony_ci */ 261d4afb5ceSopenharmony_ci if (wsi->a.vhost->tls.ssl_info_event_mask) 262d4afb5ceSopenharmony_ci SSL_set_info_callback(wsi->tls.ssl, NULL); 263d4afb5ceSopenharmony_ci#endif 264d4afb5ceSopenharmony_ci 265d4afb5ceSopenharmony_ci#if defined(LWS_TLS_SYNTHESIZE_CB) 266d4afb5ceSopenharmony_ci lws_sul_cancel(&wsi->tls.sul_cb_synth); 267d4afb5ceSopenharmony_ci /* 268d4afb5ceSopenharmony_ci * ... check the session in case it did not live long enough to get 269d4afb5ceSopenharmony_ci * the scheduled callback to sample it 270d4afb5ceSopenharmony_ci */ 271d4afb5ceSopenharmony_ci lws_sess_cache_synth_cb(&wsi->tls.sul_cb_synth); 272d4afb5ceSopenharmony_ci#endif 273d4afb5ceSopenharmony_ci 274d4afb5ceSopenharmony_ci n = SSL_get_fd(wsi->tls.ssl); 275d4afb5ceSopenharmony_ci if (!wsi->socket_is_permanently_unusable) 276d4afb5ceSopenharmony_ci SSL_shutdown(wsi->tls.ssl); 277d4afb5ceSopenharmony_ci compatible_close(n); 278d4afb5ceSopenharmony_ci SSL_free(wsi->tls.ssl); 279d4afb5ceSopenharmony_ci wsi->tls.ssl = NULL; 280d4afb5ceSopenharmony_ci 281d4afb5ceSopenharmony_ci lws_tls_restrict_return(wsi); 282d4afb5ceSopenharmony_ci 283d4afb5ceSopenharmony_ci return 1; /* handled */ 284d4afb5ceSopenharmony_ci} 285d4afb5ceSopenharmony_ci 286d4afb5ceSopenharmony_civoid 287d4afb5ceSopenharmony_cilws_ssl_SSL_CTX_destroy(struct lws_vhost *vhost) 288d4afb5ceSopenharmony_ci{ 289d4afb5ceSopenharmony_ci if (vhost->tls.ssl_ctx) 290d4afb5ceSopenharmony_ci SSL_CTX_free(vhost->tls.ssl_ctx); 291d4afb5ceSopenharmony_ci 292d4afb5ceSopenharmony_ci if (!vhost->tls.user_supplied_ssl_ctx && vhost->tls.ssl_client_ctx) 293d4afb5ceSopenharmony_ci SSL_CTX_free(vhost->tls.ssl_client_ctx); 294d4afb5ceSopenharmony_ci#if defined(LWS_WITH_ACME) 295d4afb5ceSopenharmony_ci lws_tls_acme_sni_cert_destroy(vhost); 296d4afb5ceSopenharmony_ci#endif 297d4afb5ceSopenharmony_ci} 298d4afb5ceSopenharmony_ci 299d4afb5ceSopenharmony_civoid 300d4afb5ceSopenharmony_cilws_ssl_context_destroy(struct lws_context *context) 301d4afb5ceSopenharmony_ci{ 302d4afb5ceSopenharmony_ci} 303d4afb5ceSopenharmony_ci 304d4afb5ceSopenharmony_cilws_tls_ctx * 305d4afb5ceSopenharmony_cilws_tls_ctx_from_wsi(struct lws *wsi) 306d4afb5ceSopenharmony_ci{ 307d4afb5ceSopenharmony_ci if (!wsi->tls.ssl) 308d4afb5ceSopenharmony_ci return NULL; 309d4afb5ceSopenharmony_ci 310d4afb5ceSopenharmony_ci return SSL_get_SSL_CTX(wsi->tls.ssl); 311d4afb5ceSopenharmony_ci} 312d4afb5ceSopenharmony_ci 313d4afb5ceSopenharmony_cienum lws_ssl_capable_status 314d4afb5ceSopenharmony_ci__lws_tls_shutdown(struct lws *wsi) 315d4afb5ceSopenharmony_ci{ 316d4afb5ceSopenharmony_ci int n = SSL_shutdown(wsi->tls.ssl); 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci lwsl_debug("SSL_shutdown=%d for fd %d\n", n, wsi->desc.sockfd); 319d4afb5ceSopenharmony_ci 320d4afb5ceSopenharmony_ci switch (n) { 321d4afb5ceSopenharmony_ci case 1: /* successful completion */ 322d4afb5ceSopenharmony_ci (void)shutdown(wsi->desc.sockfd, SHUT_WR); 323d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_DONE; 324d4afb5ceSopenharmony_ci 325d4afb5ceSopenharmony_ci case 0: /* needs a retry */ 326d4afb5ceSopenharmony_ci __lws_change_pollfd(wsi, 0, LWS_POLLIN); 327d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_MORE_SERVICE; 328d4afb5ceSopenharmony_ci 329d4afb5ceSopenharmony_ci default: /* fatal error, or WANT */ 330d4afb5ceSopenharmony_ci n = SSL_get_error(wsi->tls.ssl, n); 331d4afb5ceSopenharmony_ci if (n != SSL_ERROR_SYSCALL && n != SSL_ERROR_SSL) { 332d4afb5ceSopenharmony_ci if (SSL_want_read(wsi->tls.ssl)) { 333d4afb5ceSopenharmony_ci lwsl_debug("(wants read)\n"); 334d4afb5ceSopenharmony_ci __lws_change_pollfd(wsi, 0, LWS_POLLIN); 335d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_MORE_SERVICE_READ; 336d4afb5ceSopenharmony_ci } 337d4afb5ceSopenharmony_ci if (SSL_want_write(wsi->tls.ssl)) { 338d4afb5ceSopenharmony_ci lwsl_debug("(wants write)\n"); 339d4afb5ceSopenharmony_ci __lws_change_pollfd(wsi, 0, LWS_POLLOUT); 340d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_MORE_SERVICE_WRITE; 341d4afb5ceSopenharmony_ci } 342d4afb5ceSopenharmony_ci } 343d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_ERROR; 344d4afb5ceSopenharmony_ci } 345d4afb5ceSopenharmony_ci} 346d4afb5ceSopenharmony_ci 347d4afb5ceSopenharmony_ci 348d4afb5ceSopenharmony_cistatic int 349d4afb5ceSopenharmony_citops_fake_POLLIN_for_buffered_mbedtls(struct lws_context_per_thread *pt) 350d4afb5ceSopenharmony_ci{ 351d4afb5ceSopenharmony_ci return lws_tls_fake_POLLIN_for_buffered(pt); 352d4afb5ceSopenharmony_ci} 353d4afb5ceSopenharmony_ci 354d4afb5ceSopenharmony_ciconst struct lws_tls_ops tls_ops_mbedtls = { 355d4afb5ceSopenharmony_ci /* fake_POLLIN_for_buffered */ tops_fake_POLLIN_for_buffered_mbedtls, 356d4afb5ceSopenharmony_ci}; 357