1/* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to 8 * deal in the Software without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25#include "private-lib-core.h" 26 27#if defined(LWS_WITH_MBEDTLS) 28#if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS) 29#include "mbedtls/net_sockets.h" 30#else 31#include "mbedtls/net.h" 32#endif 33#endif 34 35int 36lws_plat_pipe_create(struct lws *wsi) 37{ 38 return 1; 39} 40 41int 42lws_plat_pipe_signal(struct lws *wsi) 43{ 44 return 1; 45} 46 47void 48lws_plat_pipe_close(struct lws *wsi) 49{ 50} 51 52int 53lws_send_pipe_choked(struct lws *wsi) 54{ 55 struct lws *wsi_eff; 56 57#if defined(LWS_WITH_HTTP2) 58 wsi_eff = lws_get_network_wsi(wsi); 59#else 60 wsi_eff = wsi; 61#endif 62 63 /* the fact we checked implies we avoided back-to-back writes */ 64 wsi_eff->could_have_pending = 0; 65 66 /* treat the fact we got a truncated send pending as if we're choked */ 67 if (lws_has_buffered_out(wsi_eff) 68#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION) 69 || wsi->http.comp_ctx.buflist_comp || 70 wsi->http.comp_ctx.may_have_more 71#endif 72 ) 73 return 1; 74 75 /* okay to send another packet without blocking */ 76 77 return 0; 78} 79 80int 81lws_poll_listen_fd(struct lws_pollfd *fd) 82{ 83// return poll(fd, 1, 0); 84 85 return 0; 86} 87 88 89int 90_lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi) 91{ 92 lws_usec_t timeout_us = timeout_ms * LWS_US_PER_MS; 93 struct lws_context_per_thread *pt; 94 int n = -1, m, c, a = 0; 95 //char buf; 96 97 /* stay dead once we are dead */ 98 99 if (!context) 100 return 1; 101 102 pt = &context->pt[tsi]; 103 104 if (timeout_ms < 0) 105 timeout_ms = 0; 106 else 107 timeout_ms = 2000000000; 108 109 if (!pt->service_tid_detected && context->vhost_list) { 110 struct lws _lws; 111 112 memset(&_lws, 0, sizeof(_lws)); 113 _lws.context = context; 114 115 pt->service_tid = context->vhost_list->protocols[0].callback( 116 &_lws, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); 117 pt->service_tid_detected = 1; 118 } 119 120 /* 121 * is there anybody with pending stuff that needs service forcing? 122 */ 123 if (lws_service_adjust_timeout(context, 1, tsi)) { 124again: 125 a = 0; 126 if (timeout_us) { 127 lws_usec_t us; 128 129 lws_pt_lock(pt, __func__); 130 /* don't stay in poll wait longer than next hr timeout */ 131 us = __lws_sul_service_ripe(pt->pt_sul_owner, 132 LWS_COUNT_PT_SUL_OWNERS, 133 lws_now_usecs()); 134 if (us && us < timeout_us) 135 timeout_us = us; 136 137 lws_pt_unlock(pt); 138 } 139 140 n = poll(pt->fds, pt->fds_count, timeout_us / LWS_US_PER_MS); 141 142 m = 0; 143 144 if (pt->context->tls_ops && 145 pt->context->tls_ops->fake_POLLIN_for_buffered) 146 m = pt->context->tls_ops->fake_POLLIN_for_buffered(pt); 147 148 if (/*!pt->ws.rx_draining_ext_list && */!m && !n) /* nothing to do */ 149 return 0; 150 } else 151 a = 1; 152 153 m = lws_service_flag_pending(context, tsi); 154 if (m) 155 c = -1; /* unknown limit */ 156 else 157 if (n < 0) { 158 if (LWS_ERRNO != LWS_EINTR) 159 return -1; 160 return 0; 161 } else 162 c = n; 163 164 /* any socket with events to service? */ 165 for (n = 0; n < (int)pt->fds_count && c; n++) { 166 if (!pt->fds[n].revents) 167 continue; 168 169 c--; 170#if 0 171 if (pt->fds[n].fd == pt->dummy_pipe_fds[0]) { 172 if (read(pt->fds[n].fd, &buf, 1) != 1) 173 lwsl_err("Cannot read from dummy pipe."); 174 continue; 175 } 176#endif 177 m = lws_service_fd_tsi(context, &pt->fds[n], tsi); 178 if (m < 0) 179 return -1; 180 /* if something closed, retry this slot */ 181 if (m) 182 n--; 183 } 184 185 if (a) 186 goto again; 187 188 return 0; 189} 190 191int 192lws_plat_service(struct lws_context *context, int timeout_ms) 193{ 194 return _lws_plat_service_tsi(context, timeout_ms, 0); 195} 196 197int 198lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt) 199{ 200 return 0; 201} 202 203 204int 205lws_plat_write_cert(struct lws_vhost *vhost, int is_key, int fd, void *buf, 206 size_t len) 207{ 208 return 1; 209} 210 211 212/* cast a struct sockaddr_in6 * into addr for ipv6 */ 213 214int 215lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, 216 size_t addrlen) 217{ 218 return -1; 219} 220 221void 222lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi) 223{ 224 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; 225 226 pt->fds[pt->fds_count++].revents = 0; 227} 228 229void 230lws_plat_delete_socket_from_fds(struct lws_context *context, 231 struct lws *wsi, int m) 232{ 233 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; 234 235 pt->fds_count--; 236} 237 238int 239lws_plat_change_pollfd(struct lws_context *context, 240 struct lws *wsi, struct lws_pollfd *pfd) 241{ 242 return 0; 243} 244 245const char * 246lws_plat_inet_ntop(int af, const void *src, char *dst, socklen_t cnt) 247{ 248 //return inet_ntop(af, src, dst, cnt); 249 return "lws_plat_inet_ntop"; 250} 251 252int 253lws_plat_inet_pton(int af, const char *src, void *dst) 254{ 255 //return inet_pton(af, src, dst); 256 return 1; 257} 258 259int 260lws_plat_set_socket_options_ip(int fd, uint8_t pri, unsigned int lws_flags) 261{ 262 return 0; 263} 264 265int 266lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost) 267{ 268 return 0; 269} 270 271#if defined(LWS_WITH_MBEDTLS) 272int 273lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) 274{ 275 int fd = ((mbedtls_net_context *) ctx)->fd; 276 int ret; 277 278 if (fd < 0) 279 return MBEDTLS_ERR_NET_INVALID_CONTEXT; 280 281 ret = write(fd, buf, len); 282 if (ret >= 0) 283 return ret; 284 285 if (errno == EAGAIN || errno == EWOULDBLOCK) 286 return MBEDTLS_ERR_SSL_WANT_WRITE; 287 288 if (errno == EPIPE || errno == ECONNRESET) 289 return MBEDTLS_ERR_NET_CONN_RESET; 290 291 if( errno == EINTR ) 292 return MBEDTLS_ERR_SSL_WANT_WRITE; 293 294 return MBEDTLS_ERR_NET_SEND_FAILED; 295} 296 297int 298lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) 299{ 300 int fd = ((mbedtls_net_context *) ctx)->fd; 301 int ret; 302 303 if (fd < 0) 304 return MBEDTLS_ERR_NET_INVALID_CONTEXT; 305 306 ret = (int)read(fd, buf, len); 307 if (ret >= 0) 308 return ret; 309 310 if (errno == EAGAIN || errno == EWOULDBLOCK) 311 return MBEDTLS_ERR_SSL_WANT_READ; 312 313 if (errno == EPIPE || errno == ECONNRESET) 314 return MBEDTLS_ERR_NET_CONN_RESET; 315 316 if (errno == EINTR) 317 return MBEDTLS_ERR_SSL_WANT_READ; 318 319 return MBEDTLS_ERR_NET_RECV_FAILED; 320} 321 322#endif 323