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#include <errno.h> 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_send_pipe_choked(struct lws *wsi) 37{ 38 struct lws *wsi_eff = wsi; 39 fd_set writefds; 40 struct timeval tv = { 0, 0 }; 41 int n; 42#if defined(LWS_WITH_HTTP2) 43 wsi_eff = lws_get_network_wsi(wsi); 44#endif 45 46 /* the fact we checked implies we avoided back-to-back writes */ 47 wsi_eff->could_have_pending = 0; 48 49 /* treat the fact we got a truncated send pending as if we're choked */ 50 if (lws_has_buffered_out(wsi) 51#if defined(LWS_WITH_HTTP_STREAM_COMPRESSION) 52 || wsi->http.comp_ctx.buflist_comp || 53 wsi->http.comp_ctx.may_have_more 54#endif 55 ) 56 return 1; 57 58 FD_ZERO(&writefds); 59 FD_SET(wsi_eff->desc.sockfd, &writefds); 60 61 n = select(wsi_eff->desc.sockfd + 1, NULL, &writefds, NULL, &tv); 62 if (n < 0) 63 return 1; /* choked */ 64 65 return !n; /* n = 0 = not writable = choked */ 66} 67 68int 69lws_poll_listen_fd(struct lws_pollfd *fd) 70{ 71 fd_set readfds; 72 struct timeval tv = { 0, 0 }; 73 74 FD_ZERO(&readfds); 75 FD_SET(fd->fd, &readfds); 76 77 return select(fd->fd + 1, &readfds, NULL, NULL, &tv); 78} 79 80int 81lws_plat_set_nonblocking(lws_sockfd_type fd) 82{ 83 return fcntl(fd, F_SETFL, O_NONBLOCK) < 0; 84} 85 86int 87lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt) 88{ 89 int optval = 1; 90 socklen_t optlen = sizeof(optval); 91 92#if defined(__APPLE__) || \ 93 defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ 94 defined(__NetBSD__) || \ 95 defined(__OpenBSD__) 96 struct protoent *tcp_proto; 97#endif 98 99 if (vhost->ka_time) { 100 /* enable keepalive on this socket */ 101 optval = 1; 102 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, 103 (const void *)&optval, optlen) < 0) 104 return 1; 105 106#if defined(__APPLE__) || \ 107 defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ 108 defined(__NetBSD__) || \ 109 defined(__CYGWIN__) || defined(__OpenBSD__) || defined (__sun) 110 111 /* 112 * didn't find a way to set these per-socket, need to 113 * tune kernel systemwide values 114 */ 115#else 116 /* set the keepalive conditions we want on it too */ 117 optval = vhost->ka_time; 118 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, 119 (const void *)&optval, optlen) < 0) 120 return 1; 121 122 optval = vhost->ka_interval; 123 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, 124 (const void *)&optval, optlen) < 0) 125 return 1; 126 127 optval = vhost->ka_probes; 128 if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, 129 (const void *)&optval, optlen) < 0) 130 return 1; 131#endif 132 } 133 134 /* Disable Nagle */ 135 optval = 1; 136 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, optlen) < 0) 137 return 1; 138 139 return lws_plat_set_nonblocking(fd); 140} 141 142static const int ip_opt_lws_flags[] = { 143 LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT, 144 LCCSCF_IP_HIGH_RELIABILITY, LCCSCF_IP_LOW_COST 145}, ip_opt_val[] = { 146 IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY, IPTOS_MINCOST 147}; 148#if !defined(LWS_WITH_NO_LOGS) 149static const char *ip_opt_names[] = { 150 "LOWDELAY", "THROUGHPUT", "RELIABILITY", "MINCOST" 151}; 152#endif 153 154int 155lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags) 156{ 157 int optval = (int)pri, ret = 0, n; 158 socklen_t optlen = sizeof(optval); 159#if !defined(LWS_WITH_NO_LOGS) 160 int en; 161#endif 162 163#if defined(SO_PRIORITY) 164 if (pri) { /* 0 is the default already */ 165 if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, 166 (const void *)&optval, optlen) < 0) { 167#if !defined(LWS_WITH_NO_LOGS) 168 en = errno; 169 lwsl_warn("%s: unable to set socket pri %d: errno %d\n", 170 __func__, (int)pri, en); 171#endif 172 ret = 1; 173 } else 174 lwsl_notice("%s: set pri %u\n", __func__, pri); 175 } 176#endif 177 178 for (n = 0; n < 4; n++) { 179 if (!(lws_flags & ip_opt_lws_flags[n])) 180 continue; 181 182 optval = (int)ip_opt_val[n]; 183 if (setsockopt(fd, IPPROTO_IP, IP_TOS, (const void *)&optval, 184 optlen) < 0) { 185#if !defined(LWS_WITH_NO_LOGS) 186 en = errno; 187 lwsl_warn("%s: unable to set %s: errno %d\n", __func__, 188 ip_opt_names[n], en); 189#endif 190 ret = 1; 191 } else 192 lwsl_notice("%s: set ip flag %s\n", __func__, 193 ip_opt_names[n]); 194 } 195 196 return ret; 197} 198 199/* cast a struct sockaddr_in6 * into addr for ipv6 */ 200 201int 202lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr, 203 size_t addrlen) 204{ 205#if 0 206 int rc = LWS_ITOSA_NOT_EXIST; 207 208 struct ifaddrs *ifr; 209 struct ifaddrs *ifc; 210#ifdef LWS_WITH_IPV6 211 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; 212#endif 213 214 getifaddrs(&ifr); 215 for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) { 216 if (!ifc->ifa_addr) 217 continue; 218 219 lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname); 220 221 if (strcmp(ifc->ifa_name, ifname)) 222 continue; 223 224 switch (ifc->ifa_addr->sa_family) { 225 case AF_INET: 226#ifdef LWS_WITH_IPV6 227 if (ipv6) { 228 /* map IPv4 to IPv6 */ 229 memset((char *)&addr6->sin6_addr, 0, 230 sizeof(struct in6_addr)); 231 addr6->sin6_addr.s6_addr[10] = 0xff; 232 addr6->sin6_addr.s6_addr[11] = 0xff; 233 memcpy(&addr6->sin6_addr.s6_addr[12], 234 &((struct sockaddr_in *)ifc->ifa_addr)->sin_addr, 235 sizeof(struct in_addr)); 236 } else 237#endif 238 memcpy(addr, 239 (struct sockaddr_in *)ifc->ifa_addr, 240 sizeof(struct sockaddr_in)); 241 break; 242#ifdef LWS_WITH_IPV6 243 case AF_INET6: 244 memcpy(&addr6->sin6_addr, 245 &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr, 246 sizeof(struct in6_addr)); 247 break; 248#endif 249 default: 250 continue; 251 } 252 rc = LWS_ITOSA_USABLE; 253 } 254 255 freeifaddrs(ifr); 256 257 if (rc == LWS_ITOSA_NOT_EXIST) { 258 /* check if bind to IP address */ 259#ifdef LWS_WITH_IPV6 260 if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1) 261 rc = LWS_ITOSA_USABLE; 262 else 263#endif 264 if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1) 265 rc = LWS_ITOSA_USABLE; 266 } 267 268 return rc; 269#endif 270 271 return LWS_ITOSA_NOT_EXIST; 272} 273 274const char * 275lws_plat_inet_ntop(int af, const void *src, char *dst, socklen_t cnt) 276{ 277 return inet_ntop(af, src, dst, cnt); 278} 279 280int 281lws_plat_inet_pton(int af, const char *src, void *dst) 282{ 283 return 1; // inet_pton(af, src, dst); 284} 285 286int 287lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len) 288{ 289 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__); 290 291 return -1; 292} 293 294int 295lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, size_t canned_len, 296 size_t n, int fd, const char *iface) 297{ 298 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__); 299 300 return -1; 301} 302 303int 304lws_plat_if_up(const char *ifname, int fd, int up) 305{ 306 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__); 307 308 return -1; 309} 310 311int 312lws_plat_BINDTODEVICE(lws_sockfd_type fd, const char *ifname) 313{ 314 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__); 315 316 return -1; 317} 318 319int 320lws_plat_ifconfig(int fd, lws_dhcpc_ifstate_t *is) 321{ 322 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__); 323 324 return -1; 325} 326 327int 328lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost) 329{ 330 return 0; 331} 332 333#if defined(LWS_WITH_MBEDTLS) 334int 335lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len) 336{ 337 int fd = ((mbedtls_net_context *) ctx)->fd; 338 int ret; 339 340 if (fd < 0) 341 return MBEDTLS_ERR_NET_INVALID_CONTEXT; 342 343 ret = write(fd, buf, len); 344 if (ret >= 0) 345 return ret; 346 347 if (errno == EAGAIN || errno == EWOULDBLOCK) 348 return MBEDTLS_ERR_SSL_WANT_WRITE; 349 350 if (errno == EPIPE || errno == ECONNRESET) 351 return MBEDTLS_ERR_NET_CONN_RESET; 352 353 if( errno == EINTR ) 354 return MBEDTLS_ERR_SSL_WANT_WRITE; 355 356 return MBEDTLS_ERR_NET_SEND_FAILED; 357} 358 359int 360lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len) 361{ 362 int fd = ((mbedtls_net_context *) ctx)->fd; 363 int ret; 364 365 if (fd < 0) 366 return MBEDTLS_ERR_NET_INVALID_CONTEXT; 367 368 ret = (int)read(fd, buf, len); 369 if (ret >= 0) 370 return ret; 371 372 if (errno == EAGAIN || errno == EWOULDBLOCK) 373 return MBEDTLS_ERR_SSL_WANT_READ; 374 375 if (errno == EPIPE || errno == ECONNRESET) 376 return MBEDTLS_ERR_NET_CONN_RESET; 377 378 if (errno == EINTR || !errno) 379 return MBEDTLS_ERR_SSL_WANT_READ; 380 381 return MBEDTLS_ERR_NET_RECV_FAILED; 382} 383#endif 384 385