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 27d4afb5ceSopenharmony_ci/* 28d4afb5ceSopenharmony_ci * notice this returns number of bytes consumed, or -1 29d4afb5ceSopenharmony_ci */ 30d4afb5ceSopenharmony_ciint 31d4afb5ceSopenharmony_cilws_issue_raw(struct lws *wsi, unsigned char *buf, size_t len) 32d4afb5ceSopenharmony_ci{ 33d4afb5ceSopenharmony_ci struct lws_context *context = lws_get_context(wsi); 34d4afb5ceSopenharmony_ci size_t real_len = len; 35d4afb5ceSopenharmony_ci unsigned int n, m; 36d4afb5ceSopenharmony_ci 37d4afb5ceSopenharmony_ci /* 38d4afb5ceSopenharmony_ci * If you're looking to dump data being sent down the tls tunnel, see 39d4afb5ceSopenharmony_ci * lws_ssl_capable_write() in lib/tls/mbedtls/mbedtls-ssl.c or 40d4afb5ceSopenharmony_ci * lib/tls/openssl/openssl-ssl.c. 41d4afb5ceSopenharmony_ci * 42d4afb5ceSopenharmony_ci * There's also a corresponding lws_ssl_capable_read() in those files 43d4afb5ceSopenharmony_ci * where you can enable a dump of decrypted data as soon as it was 44d4afb5ceSopenharmony_ci * read. 45d4afb5ceSopenharmony_ci */ 46d4afb5ceSopenharmony_ci 47d4afb5ceSopenharmony_ci /* just ignore sends after we cleared the truncation buffer */ 48d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE && 49d4afb5ceSopenharmony_ci !lws_has_buffered_out(wsi) 50d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION) 51d4afb5ceSopenharmony_ci && !wsi->http.comp_ctx.may_have_more 52d4afb5ceSopenharmony_ci#endif 53d4afb5ceSopenharmony_ci ) 54d4afb5ceSopenharmony_ci return (int)len; 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci if (buf && lws_has_buffered_out(wsi)) { 57d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "** prot: %s, incr buflist_out by %lu", 58d4afb5ceSopenharmony_ci wsi->a.protocol->name, (unsigned long)len); 59d4afb5ceSopenharmony_ci 60d4afb5ceSopenharmony_ci /* 61d4afb5ceSopenharmony_ci * already buflist ahead of this, add it on the tail of the 62d4afb5ceSopenharmony_ci * buflist, then ignore it for now and act like we're flushing 63d4afb5ceSopenharmony_ci * the buflist... 64d4afb5ceSopenharmony_ci */ 65d4afb5ceSopenharmony_ci 66d4afb5ceSopenharmony_ci if (lws_buflist_append_segment(&wsi->buflist_out, buf, len)) 67d4afb5ceSopenharmony_ci return -1; 68d4afb5ceSopenharmony_ci 69d4afb5ceSopenharmony_ci buf = NULL; 70d4afb5ceSopenharmony_ci len = 0; 71d4afb5ceSopenharmony_ci } 72d4afb5ceSopenharmony_ci 73d4afb5ceSopenharmony_ci if (wsi->buflist_out) { 74d4afb5ceSopenharmony_ci /* we have to drain the earliest buflist_out stuff first */ 75d4afb5ceSopenharmony_ci 76d4afb5ceSopenharmony_ci len = lws_buflist_next_segment_len(&wsi->buflist_out, &buf); 77d4afb5ceSopenharmony_ci real_len = len; 78d4afb5ceSopenharmony_ci 79d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "draining %d", (int)len); 80d4afb5ceSopenharmony_ci } 81d4afb5ceSopenharmony_ci 82d4afb5ceSopenharmony_ci if (!len || !buf) 83d4afb5ceSopenharmony_ci return 0; 84d4afb5ceSopenharmony_ci 85d4afb5ceSopenharmony_ci if (!wsi->mux_substream && !lws_socket_is_valid(wsi->desc.sockfd)) 86d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "invalid sock"); 87d4afb5ceSopenharmony_ci 88d4afb5ceSopenharmony_ci /* limit sending */ 89d4afb5ceSopenharmony_ci if (wsi->a.protocol->tx_packet_size) 90d4afb5ceSopenharmony_ci n = (unsigned int)wsi->a.protocol->tx_packet_size; 91d4afb5ceSopenharmony_ci else { 92d4afb5ceSopenharmony_ci n = (unsigned int)wsi->a.protocol->rx_buffer_size; 93d4afb5ceSopenharmony_ci if (!n) 94d4afb5ceSopenharmony_ci n = context->pt_serv_buf_size; 95d4afb5ceSopenharmony_ci } 96d4afb5ceSopenharmony_ci n += LWS_PRE + 4; 97d4afb5ceSopenharmony_ci if (n > len) 98d4afb5ceSopenharmony_ci n = (unsigned int)len; 99d4afb5ceSopenharmony_ci 100d4afb5ceSopenharmony_ci /* nope, send it on the socket directly */ 101d4afb5ceSopenharmony_ci 102d4afb5ceSopenharmony_ci if (lws_fi(&wsi->fic, "sendfail")) 103d4afb5ceSopenharmony_ci m = (unsigned int)LWS_SSL_CAPABLE_ERROR; 104d4afb5ceSopenharmony_ci else 105d4afb5ceSopenharmony_ci m = (unsigned int)lws_ssl_capable_write(wsi, buf, n); 106d4afb5ceSopenharmony_ci 107d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "ssl_capable_write (%d) says %d", n, m); 108d4afb5ceSopenharmony_ci 109d4afb5ceSopenharmony_ci /* something got written, it can have been truncated now */ 110d4afb5ceSopenharmony_ci wsi->could_have_pending = 1; 111d4afb5ceSopenharmony_ci 112d4afb5ceSopenharmony_ci switch ((int)m) { 113d4afb5ceSopenharmony_ci case LWS_SSL_CAPABLE_ERROR: 114d4afb5ceSopenharmony_ci /* we're going to close, let close know sends aren't possible */ 115d4afb5ceSopenharmony_ci wsi->socket_is_permanently_unusable = 1; 116d4afb5ceSopenharmony_ci return -1; 117d4afb5ceSopenharmony_ci case LWS_SSL_CAPABLE_MORE_SERVICE: 118d4afb5ceSopenharmony_ci /* 119d4afb5ceSopenharmony_ci * nothing got sent, not fatal. Retry the whole thing later, 120d4afb5ceSopenharmony_ci * ie, implying treat it was a truncated send so it gets 121d4afb5ceSopenharmony_ci * retried 122d4afb5ceSopenharmony_ci */ 123d4afb5ceSopenharmony_ci m = 0; 124d4afb5ceSopenharmony_ci break; 125d4afb5ceSopenharmony_ci } 126d4afb5ceSopenharmony_ci 127d4afb5ceSopenharmony_ci if ((int)m < 0) 128d4afb5ceSopenharmony_ci m = 0; 129d4afb5ceSopenharmony_ci 130d4afb5ceSopenharmony_ci /* 131d4afb5ceSopenharmony_ci * we were sending this from buflist_out? Then not sending everything 132d4afb5ceSopenharmony_ci * is a small matter of advancing ourselves only by the amount we did 133d4afb5ceSopenharmony_ci * send in the buflist. 134d4afb5ceSopenharmony_ci */ 135d4afb5ceSopenharmony_ci if (lws_has_buffered_out(wsi)) { 136d4afb5ceSopenharmony_ci if (m) { 137d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "partial adv %d (vs %ld)", 138d4afb5ceSopenharmony_ci m, (long)real_len); 139d4afb5ceSopenharmony_ci lws_buflist_use_segment(&wsi->buflist_out, m); 140d4afb5ceSopenharmony_ci } 141d4afb5ceSopenharmony_ci 142d4afb5ceSopenharmony_ci if (!lws_has_buffered_out(wsi)) { 143d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "buflist_out flushed"); 144d4afb5ceSopenharmony_ci 145d4afb5ceSopenharmony_ci m = (unsigned int)real_len; 146d4afb5ceSopenharmony_ci if (lwsi_state(wsi) == LRS_FLUSHING_BEFORE_CLOSE) { 147d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "*signalling to close now"); 148d4afb5ceSopenharmony_ci return -1; /* retry closing now */ 149d4afb5ceSopenharmony_ci } 150d4afb5ceSopenharmony_ci 151d4afb5ceSopenharmony_ci if (wsi->close_when_buffered_out_drained) { 152d4afb5ceSopenharmony_ci wsi->close_when_buffered_out_drained = 0; 153d4afb5ceSopenharmony_ci return -1; 154d4afb5ceSopenharmony_ci } 155d4afb5ceSopenharmony_ci 156d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_H1) || defined(LWS_ROLE_H2) 157d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SERVER) 158d4afb5ceSopenharmony_ci if (wsi->http.deferred_transaction_completed) { 159d4afb5ceSopenharmony_ci lwsl_wsi_notice(wsi, "partial completed, doing " 160d4afb5ceSopenharmony_ci "deferred transaction completed"); 161d4afb5ceSopenharmony_ci wsi->http.deferred_transaction_completed = 0; 162d4afb5ceSopenharmony_ci return lws_http_transaction_completed(wsi) ? 163d4afb5ceSopenharmony_ci -1 : (int)real_len; 164d4afb5ceSopenharmony_ci } 165d4afb5ceSopenharmony_ci#endif 166d4afb5ceSopenharmony_ci#endif 167d4afb5ceSopenharmony_ci#if defined(LWS_ROLE_WS) 168d4afb5ceSopenharmony_ci /* Since buflist_out flushed, we're not inside a frame any more */ 169d4afb5ceSopenharmony_ci if (wsi->ws) 170d4afb5ceSopenharmony_ci wsi->ws->inside_frame = 0; 171d4afb5ceSopenharmony_ci#endif 172d4afb5ceSopenharmony_ci } 173d4afb5ceSopenharmony_ci /* always callback on writeable */ 174d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 175d4afb5ceSopenharmony_ci 176d4afb5ceSopenharmony_ci return (int)m; 177d4afb5ceSopenharmony_ci } 178d4afb5ceSopenharmony_ci 179d4afb5ceSopenharmony_ci#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION) 180d4afb5ceSopenharmony_ci if (wsi->http.comp_ctx.may_have_more) 181d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 182d4afb5ceSopenharmony_ci#endif 183d4afb5ceSopenharmony_ci 184d4afb5ceSopenharmony_ci if (m == real_len) 185d4afb5ceSopenharmony_ci /* what we just sent went out cleanly */ 186d4afb5ceSopenharmony_ci return (int)m; 187d4afb5ceSopenharmony_ci 188d4afb5ceSopenharmony_ci /* 189d4afb5ceSopenharmony_ci * We were not able to send everything... and we were not sending from 190d4afb5ceSopenharmony_ci * an existing buflist_out. So we are starting a fresh buflist_out, by 191d4afb5ceSopenharmony_ci * buffering the unsent remainder on it. 192d4afb5ceSopenharmony_ci * (it will get first priority next time the socket is writable). 193d4afb5ceSopenharmony_ci */ 194d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "new partial sent %d from %lu total", 195d4afb5ceSopenharmony_ci m, (unsigned long)real_len); 196d4afb5ceSopenharmony_ci 197d4afb5ceSopenharmony_ci if (lws_buflist_append_segment(&wsi->buflist_out, buf + m, 198d4afb5ceSopenharmony_ci real_len - m) < 0) 199d4afb5ceSopenharmony_ci return -1; 200d4afb5ceSopenharmony_ci 201d4afb5ceSopenharmony_ci#if defined(LWS_WITH_UDP) 202d4afb5ceSopenharmony_ci if (lws_wsi_is_udp(wsi)) 203d4afb5ceSopenharmony_ci /* stash original destination for fulfilling UDP partials */ 204d4afb5ceSopenharmony_ci wsi->udp->sa46_pending = wsi->udp->sa46; 205d4afb5ceSopenharmony_ci#endif 206d4afb5ceSopenharmony_ci 207d4afb5ceSopenharmony_ci /* since something buffered, force it to get another chance to send */ 208d4afb5ceSopenharmony_ci lws_callback_on_writable(wsi); 209d4afb5ceSopenharmony_ci 210d4afb5ceSopenharmony_ci return (int)real_len; 211d4afb5ceSopenharmony_ci} 212d4afb5ceSopenharmony_ci 213d4afb5ceSopenharmony_ciint 214d4afb5ceSopenharmony_cilws_write(struct lws *wsi, unsigned char *buf, size_t len, 215d4afb5ceSopenharmony_ci enum lws_write_protocol wp) 216d4afb5ceSopenharmony_ci{ 217d4afb5ceSopenharmony_ci int m; 218d4afb5ceSopenharmony_ci 219d4afb5ceSopenharmony_ci if ((int)len < 0) { 220d4afb5ceSopenharmony_ci lwsl_wsi_err(wsi, "suspicious len int %d, ulong %lu", 221d4afb5ceSopenharmony_ci (int)len, (unsigned long)len); 222d4afb5ceSopenharmony_ci return -1; 223d4afb5ceSopenharmony_ci } 224d4afb5ceSopenharmony_ci 225d4afb5ceSopenharmony_ci#ifdef LWS_WITH_ACCESS_LOG 226d4afb5ceSopenharmony_ci wsi->http.access_log.sent += len; 227d4afb5ceSopenharmony_ci#endif 228d4afb5ceSopenharmony_ci 229d4afb5ceSopenharmony_ci assert(wsi->role_ops); 230d4afb5ceSopenharmony_ci 231d4afb5ceSopenharmony_ci if (!lws_rops_fidx(wsi->role_ops, LWS_ROPS_write_role_protocol)) 232d4afb5ceSopenharmony_ci m = lws_issue_raw(wsi, buf, len); 233d4afb5ceSopenharmony_ci else 234d4afb5ceSopenharmony_ci m = lws_rops_func_fidx(wsi->role_ops, LWS_ROPS_write_role_protocol). 235d4afb5ceSopenharmony_ci write_role_protocol(wsi, buf, len, &wp); 236d4afb5ceSopenharmony_ci 237d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) 238d4afb5ceSopenharmony_ci if (wsi->a.vhost) 239d4afb5ceSopenharmony_ci lws_metric_event(wsi->a.vhost->mt_traffic_tx, (char) 240d4afb5ceSopenharmony_ci (m < 0 ? METRES_NOGO : METRES_GO), len); 241d4afb5ceSopenharmony_ci#endif 242d4afb5ceSopenharmony_ci 243d4afb5ceSopenharmony_ci return m; 244d4afb5ceSopenharmony_ci} 245d4afb5ceSopenharmony_ci 246d4afb5ceSopenharmony_ciint 247d4afb5ceSopenharmony_cilws_ssl_capable_read_no_ssl(struct lws *wsi, unsigned char *buf, size_t len) 248d4afb5ceSopenharmony_ci{ 249d4afb5ceSopenharmony_ci int n = 0, en; 250d4afb5ceSopenharmony_ci 251d4afb5ceSopenharmony_ci errno = 0; 252d4afb5ceSopenharmony_ci#if defined(LWS_WITH_UDP) 253d4afb5ceSopenharmony_ci if (lws_wsi_is_udp(wsi)) { 254d4afb5ceSopenharmony_ci socklen_t slt = sizeof(wsi->udp->sa46); 255d4afb5ceSopenharmony_ci 256d4afb5ceSopenharmony_ci n = (int)recvfrom(wsi->desc.sockfd, (char *)buf, 257d4afb5ceSopenharmony_ci#if defined(WIN32) 258d4afb5ceSopenharmony_ci (int) 259d4afb5ceSopenharmony_ci#endif 260d4afb5ceSopenharmony_ci len, 0, 261d4afb5ceSopenharmony_ci sa46_sockaddr(&wsi->udp->sa46), &slt); 262d4afb5ceSopenharmony_ci } else 263d4afb5ceSopenharmony_ci#endif 264d4afb5ceSopenharmony_ci n = (int)recv(wsi->desc.sockfd, (char *)buf, 265d4afb5ceSopenharmony_ci#if defined(WIN32) 266d4afb5ceSopenharmony_ci (int) 267d4afb5ceSopenharmony_ci#endif 268d4afb5ceSopenharmony_ci len, 0); 269d4afb5ceSopenharmony_ci en = LWS_ERRNO; 270d4afb5ceSopenharmony_ci if (n >= 0) { 271d4afb5ceSopenharmony_ci 272d4afb5ceSopenharmony_ci if (!n && wsi->unix_skt) 273d4afb5ceSopenharmony_ci goto do_err; 274d4afb5ceSopenharmony_ci 275d4afb5ceSopenharmony_ci /* 276d4afb5ceSopenharmony_ci * See https://libwebsockets.org/ 277d4afb5ceSopenharmony_ci * pipermail/libwebsockets/2019-March/007857.html 278d4afb5ceSopenharmony_ci */ 279d4afb5ceSopenharmony_ci if (!n && !wsi->unix_skt) 280d4afb5ceSopenharmony_ci goto do_err; 281d4afb5ceSopenharmony_ci 282d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) && defined(LWS_WITH_SERVER) 283d4afb5ceSopenharmony_ci if (wsi->a.vhost) 284d4afb5ceSopenharmony_ci lws_metric_event(wsi->a.vhost->mt_traffic_rx, 285d4afb5ceSopenharmony_ci METRES_GO /* rx */, (unsigned int)n); 286d4afb5ceSopenharmony_ci#endif 287d4afb5ceSopenharmony_ci 288d4afb5ceSopenharmony_ci return n; 289d4afb5ceSopenharmony_ci } 290d4afb5ceSopenharmony_ci 291d4afb5ceSopenharmony_ci if (en == LWS_EAGAIN || 292d4afb5ceSopenharmony_ci en == LWS_EWOULDBLOCK || 293d4afb5ceSopenharmony_ci en == LWS_EINTR) 294d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_MORE_SERVICE; 295d4afb5ceSopenharmony_ci 296d4afb5ceSopenharmony_cido_err: 297d4afb5ceSopenharmony_ci#if defined(LWS_WITH_SYS_METRICS) && defined(LWS_WITH_SERVER) 298d4afb5ceSopenharmony_ci if (wsi->a.vhost) 299d4afb5ceSopenharmony_ci lws_metric_event(wsi->a.vhost->mt_traffic_rx, METRES_NOGO, 0u); 300d4afb5ceSopenharmony_ci#endif 301d4afb5ceSopenharmony_ci 302d4afb5ceSopenharmony_ci lwsl_wsi_info(wsi, "error on reading from skt : %d, errno %d", n, en); 303d4afb5ceSopenharmony_ci 304d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_ERROR; 305d4afb5ceSopenharmony_ci} 306d4afb5ceSopenharmony_ci 307d4afb5ceSopenharmony_ciint 308d4afb5ceSopenharmony_cilws_ssl_capable_write_no_ssl(struct lws *wsi, unsigned char *buf, size_t len) 309d4afb5ceSopenharmony_ci{ 310d4afb5ceSopenharmony_ci int n = 0; 311d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_OPTEE) 312d4afb5ceSopenharmony_ci ssize_t send(int sockfd, const void *buf, size_t len, int flags); 313d4afb5ceSopenharmony_ci#endif 314d4afb5ceSopenharmony_ci 315d4afb5ceSopenharmony_ci#if defined(LWS_WITH_UDP) 316d4afb5ceSopenharmony_ci if (lws_wsi_is_udp(wsi)) { 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci if (lws_fi(&wsi->fic, "udp_tx_loss")) { 319d4afb5ceSopenharmony_ci /* pretend it was sent */ 320d4afb5ceSopenharmony_ci n = (int)(ssize_t)len; 321d4afb5ceSopenharmony_ci goto post_send; 322d4afb5ceSopenharmony_ci } 323d4afb5ceSopenharmony_ci 324d4afb5ceSopenharmony_ci if (lws_has_buffered_out(wsi)) 325d4afb5ceSopenharmony_ci n = (int)sendto(wsi->desc.sockfd, (const char *)buf, 326d4afb5ceSopenharmony_ci#if defined(WIN32) 327d4afb5ceSopenharmony_ci (int) 328d4afb5ceSopenharmony_ci#endif 329d4afb5ceSopenharmony_ci len, 0, sa46_sockaddr(&wsi->udp->sa46_pending), 330d4afb5ceSopenharmony_ci sa46_socklen(&wsi->udp->sa46_pending)); 331d4afb5ceSopenharmony_ci else 332d4afb5ceSopenharmony_ci n = (int)sendto(wsi->desc.sockfd, (const char *)buf, 333d4afb5ceSopenharmony_ci#if defined(WIN32) 334d4afb5ceSopenharmony_ci (int) 335d4afb5ceSopenharmony_ci#endif 336d4afb5ceSopenharmony_ci len, 0, sa46_sockaddr(&wsi->udp->sa46), 337d4afb5ceSopenharmony_ci sa46_socklen(&wsi->udp->sa46)); 338d4afb5ceSopenharmony_ci } else 339d4afb5ceSopenharmony_ci#endif 340d4afb5ceSopenharmony_ci if (wsi->role_ops->file_handle) 341d4afb5ceSopenharmony_ci n = (int)write((int)(lws_intptr_t)wsi->desc.filefd, buf, 342d4afb5ceSopenharmony_ci#if defined(WIN32) 343d4afb5ceSopenharmony_ci (int) 344d4afb5ceSopenharmony_ci#endif 345d4afb5ceSopenharmony_ci len); 346d4afb5ceSopenharmony_ci else 347d4afb5ceSopenharmony_ci n = (int)send(wsi->desc.sockfd, (char *)buf, 348d4afb5ceSopenharmony_ci#if defined(WIN32) 349d4afb5ceSopenharmony_ci (int) 350d4afb5ceSopenharmony_ci#endif 351d4afb5ceSopenharmony_ci len, MSG_NOSIGNAL); 352d4afb5ceSopenharmony_ci// lwsl_info("%s: sent len %d result %d", __func__, len, n); 353d4afb5ceSopenharmony_ci 354d4afb5ceSopenharmony_ci#if defined(LWS_WITH_UDP) 355d4afb5ceSopenharmony_cipost_send: 356d4afb5ceSopenharmony_ci#endif 357d4afb5ceSopenharmony_ci if (n >= 0) 358d4afb5ceSopenharmony_ci return n; 359d4afb5ceSopenharmony_ci 360d4afb5ceSopenharmony_ci if (LWS_ERRNO == LWS_EAGAIN || 361d4afb5ceSopenharmony_ci LWS_ERRNO == LWS_EWOULDBLOCK || 362d4afb5ceSopenharmony_ci LWS_ERRNO == LWS_EINTR) { 363d4afb5ceSopenharmony_ci if (LWS_ERRNO == LWS_EWOULDBLOCK) { 364d4afb5ceSopenharmony_ci lws_set_blocking_send(wsi); 365d4afb5ceSopenharmony_ci } 366d4afb5ceSopenharmony_ci 367d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_MORE_SERVICE; 368d4afb5ceSopenharmony_ci } 369d4afb5ceSopenharmony_ci 370d4afb5ceSopenharmony_ci lwsl_wsi_debug(wsi, "ERROR writing len %d to skt fd %d err %d / errno %d", 371d4afb5ceSopenharmony_ci (int)(ssize_t)len, wsi->desc.sockfd, n, LWS_ERRNO); 372d4afb5ceSopenharmony_ci 373d4afb5ceSopenharmony_ci return LWS_SSL_CAPABLE_ERROR; 374d4afb5ceSopenharmony_ci} 375d4afb5ceSopenharmony_ci 376d4afb5ceSopenharmony_ciint 377d4afb5ceSopenharmony_cilws_ssl_pending_no_ssl(struct lws *wsi) 378d4afb5ceSopenharmony_ci{ 379d4afb5ceSopenharmony_ci (void)wsi; 380d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_FREERTOS) 381d4afb5ceSopenharmony_ci return 100; 382d4afb5ceSopenharmony_ci#else 383d4afb5ceSopenharmony_ci return 0; 384d4afb5ceSopenharmony_ci#endif 385d4afb5ceSopenharmony_ci} 386