freertos-sockets.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  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. #include "private-lib-core.h"
  25. #include <errno.h>
  26. #if defined(LWS_WITH_MBEDTLS)
  27. #if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS)
  28. #include "mbedtls/net_sockets.h"
  29. #else
  30. #include "mbedtls/net.h"
  31. #endif
  32. #endif
  33. int
  34. lws_send_pipe_choked(struct lws *wsi)
  35. {
  36. struct lws *wsi_eff = wsi;
  37. fd_set writefds;
  38. struct timeval tv = { 0, 0 };
  39. int n;
  40. #if defined(LWS_WITH_HTTP2)
  41. wsi_eff = lws_get_network_wsi(wsi);
  42. #endif
  43. /* the fact we checked implies we avoided back-to-back writes */
  44. wsi_eff->could_have_pending = 0;
  45. /* treat the fact we got a truncated send pending as if we're choked */
  46. if (lws_has_buffered_out(wsi)
  47. #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
  48. || wsi->http.comp_ctx.buflist_comp ||
  49. wsi->http.comp_ctx.may_have_more
  50. #endif
  51. )
  52. return 1;
  53. FD_ZERO(&writefds);
  54. FD_SET(wsi_eff->desc.sockfd, &writefds);
  55. n = select(wsi_eff->desc.sockfd + 1, NULL, &writefds, NULL, &tv);
  56. if (n < 0)
  57. return 1; /* choked */
  58. return !n; /* n = 0 = not writable = choked */
  59. }
  60. int
  61. lws_poll_listen_fd(struct lws_pollfd *fd)
  62. {
  63. fd_set readfds;
  64. struct timeval tv = { 0, 0 };
  65. FD_ZERO(&readfds);
  66. FD_SET(fd->fd, &readfds);
  67. return select(fd->fd + 1, &readfds, NULL, NULL, &tv);
  68. }
  69. int
  70. lws_plat_set_nonblocking(lws_sockfd_type fd)
  71. {
  72. return fcntl(fd, F_SETFL, O_NONBLOCK) < 0;
  73. }
  74. int
  75. lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt)
  76. {
  77. int optval = 1;
  78. socklen_t optlen = sizeof(optval);
  79. #if defined(__APPLE__) || \
  80. defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
  81. defined(__NetBSD__) || \
  82. defined(__OpenBSD__)
  83. struct protoent *tcp_proto;
  84. #endif
  85. if (vhost->ka_time) {
  86. /* enable keepalive on this socket */
  87. optval = 1;
  88. if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
  89. (const void *)&optval, optlen) < 0)
  90. return 1;
  91. #if defined(__APPLE__) || \
  92. defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
  93. defined(__NetBSD__) || \
  94. defined(__CYGWIN__) || defined(__OpenBSD__) || defined (__sun)
  95. /*
  96. * didn't find a way to set these per-socket, need to
  97. * tune kernel systemwide values
  98. */
  99. #else
  100. /* set the keepalive conditions we want on it too */
  101. optval = vhost->ka_time;
  102. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,
  103. (const void *)&optval, optlen) < 0)
  104. return 1;
  105. optval = vhost->ka_interval;
  106. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
  107. (const void *)&optval, optlen) < 0)
  108. return 1;
  109. optval = vhost->ka_probes;
  110. if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
  111. (const void *)&optval, optlen) < 0)
  112. return 1;
  113. #endif
  114. }
  115. /* Disable Nagle */
  116. optval = 1;
  117. if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &optval, optlen) < 0)
  118. return 1;
  119. return lws_plat_set_nonblocking(fd);
  120. }
  121. /* cast a struct sockaddr_in6 * into addr for ipv6 */
  122. int
  123. lws_interface_to_sa(int ipv6, const char *ifname, struct sockaddr_in *addr,
  124. size_t addrlen)
  125. {
  126. #if 0
  127. int rc = LWS_ITOSA_NOT_EXIST;
  128. struct ifaddrs *ifr;
  129. struct ifaddrs *ifc;
  130. #ifdef LWS_WITH_IPV6
  131. struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
  132. #endif
  133. getifaddrs(&ifr);
  134. for (ifc = ifr; ifc != NULL && rc; ifc = ifc->ifa_next) {
  135. if (!ifc->ifa_addr)
  136. continue;
  137. lwsl_info(" interface %s vs %s\n", ifc->ifa_name, ifname);
  138. if (strcmp(ifc->ifa_name, ifname))
  139. continue;
  140. switch (ifc->ifa_addr->sa_family) {
  141. case AF_INET:
  142. #ifdef LWS_WITH_IPV6
  143. if (ipv6) {
  144. /* map IPv4 to IPv6 */
  145. memset((char *)&addr6->sin6_addr, 0,
  146. sizeof(struct in6_addr));
  147. addr6->sin6_addr.s6_addr[10] = 0xff;
  148. addr6->sin6_addr.s6_addr[11] = 0xff;
  149. memcpy(&addr6->sin6_addr.s6_addr[12],
  150. &((struct sockaddr_in *)ifc->ifa_addr)->sin_addr,
  151. sizeof(struct in_addr));
  152. } else
  153. #endif
  154. memcpy(addr,
  155. (struct sockaddr_in *)ifc->ifa_addr,
  156. sizeof(struct sockaddr_in));
  157. break;
  158. #ifdef LWS_WITH_IPV6
  159. case AF_INET6:
  160. memcpy(&addr6->sin6_addr,
  161. &((struct sockaddr_in6 *)ifc->ifa_addr)->sin6_addr,
  162. sizeof(struct in6_addr));
  163. break;
  164. #endif
  165. default:
  166. continue;
  167. }
  168. rc = LWS_ITOSA_USABLE;
  169. }
  170. freeifaddrs(ifr);
  171. if (rc == LWS_ITOSA_NOT_EXIST) {
  172. /* check if bind to IP address */
  173. #ifdef LWS_WITH_IPV6
  174. if (inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1)
  175. rc = LWS_ITOSA_USABLE;
  176. else
  177. #endif
  178. if (inet_pton(AF_INET, ifname, &addr->sin_addr) == 1)
  179. rc = LWS_ITOSA_USABLE;
  180. }
  181. return rc;
  182. #endif
  183. return LWS_ITOSA_NOT_EXIST;
  184. }
  185. const char *
  186. lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
  187. {
  188. return inet_ntop(af, src, dst, cnt);
  189. }
  190. int
  191. lws_plat_inet_pton(int af, const char *src, void *dst)
  192. {
  193. return 1; // inet_pton(af, src, dst);
  194. }
  195. int
  196. lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len)
  197. {
  198. lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
  199. return -1;
  200. }
  201. int
  202. lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, int canned_len,
  203. int n, int fd, const char *iface)
  204. {
  205. lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
  206. return -1;
  207. }
  208. int
  209. lws_plat_if_up(const char *ifname, int fd, int up)
  210. {
  211. lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
  212. return -1;
  213. }
  214. int
  215. lws_plat_BINDTODEVICE(lws_sockfd_type fd, const char *ifname)
  216. {
  217. lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
  218. return -1;
  219. }
  220. int
  221. lws_plat_ifconfig_ip(const char *ifname, int fd, uint8_t *ip, uint8_t *mask_ip,
  222. uint8_t *gateway_ip)
  223. {
  224. lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
  225. return -1;
  226. }
  227. #if defined(LWS_WITH_MBEDTLS)
  228. int
  229. lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len)
  230. {
  231. int fd = ((mbedtls_net_context *) ctx)->fd;
  232. int ret;
  233. if (fd < 0)
  234. return MBEDTLS_ERR_NET_INVALID_CONTEXT;
  235. ret = write(fd, buf, len);
  236. if (ret >= 0)
  237. return ret;
  238. if (errno == EAGAIN || errno == EWOULDBLOCK)
  239. return MBEDTLS_ERR_SSL_WANT_WRITE;
  240. if (errno == EPIPE || errno == ECONNRESET)
  241. return MBEDTLS_ERR_NET_CONN_RESET;
  242. if( errno == EINTR )
  243. return MBEDTLS_ERR_SSL_WANT_WRITE;
  244. return MBEDTLS_ERR_NET_SEND_FAILED;
  245. }
  246. int
  247. lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len)
  248. {
  249. int fd = ((mbedtls_net_context *) ctx)->fd;
  250. int ret;
  251. if (fd < 0)
  252. return MBEDTLS_ERR_NET_INVALID_CONTEXT;
  253. ret = (int)read(fd, buf, len);
  254. if (ret >= 0)
  255. return ret;
  256. if (errno == EAGAIN || errno == EWOULDBLOCK)
  257. return MBEDTLS_ERR_SSL_WANT_READ;
  258. if (errno == EPIPE || errno == ECONNRESET)
  259. return MBEDTLS_ERR_NET_CONN_RESET;
  260. if (errno == EINTR || !errno)
  261. return MBEDTLS_ERR_SSL_WANT_READ;
  262. return MBEDTLS_ERR_NET_RECV_FAILED;
  263. }
  264. #endif