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 #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
26 #define _WINSOCK_DEPRECATED_NO_WARNINGS
27 #endif
28 #include "private-lib-core.h"
29
30
31 int
lws_send_pipe_choked(struct lws * wsi)32 lws_send_pipe_choked(struct lws *wsi)
33 { struct lws *wsi_eff;
34
35 #if defined(LWS_WITH_HTTP2)
36 wsi_eff = lws_get_network_wsi(wsi);
37 #else
38 wsi_eff = wsi;
39 #endif
40 /* the fact we checked implies we avoided back-to-back writes */
41 wsi_eff->could_have_pending = 0;
42
43 /* treat the fact we got a truncated send pending as if we're choked */
44 if (lws_has_buffered_out(wsi_eff)
45 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
46 ||wsi->http.comp_ctx.buflist_comp ||
47 wsi->http.comp_ctx.may_have_more
48 #endif
49 )
50 return 1;
51
52 return (int)wsi_eff->sock_send_blocking;
53 }
54
55 int
lws_poll_listen_fd(struct lws_pollfd * fd)56 lws_poll_listen_fd(struct lws_pollfd *fd)
57 {
58 fd_set readfds;
59 struct timeval tv = { 0, 0 };
60
61 assert((fd->events & LWS_POLLIN) == LWS_POLLIN);
62
63 FD_ZERO(&readfds);
64 FD_SET(fd->fd, &readfds);
65
66 return select(((int)fd->fd) + 1, &readfds, NULL, NULL, &tv);
67 }
68
69 int
lws_plat_set_nonblocking(lws_sockfd_type fd)70 lws_plat_set_nonblocking(lws_sockfd_type fd)
71 {
72 u_long optl = 1;
73 int result = !!ioctlsocket(fd, FIONBIO, &optl);
74 if (result)
75 {
76 int error = LWS_ERRNO;
77 lwsl_err("ioctlsocket FIONBIO 1 failed with error %d\n", error);
78 }
79 return result;
80 }
81
82 int
lws_plat_set_socket_options(struct lws_vhost * vhost,lws_sockfd_type fd,int unix_skt)83 lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
84 int unix_skt)
85 {
86 int optval = 1;
87 int optlen = sizeof(optval);
88 DWORD dwBytesRet;
89 struct tcp_keepalive alive;
90 int protonbr;
91 #ifndef _WIN32_WCE
92 struct protoent *tcp_proto;
93 #endif
94
95 if (vhost->ka_time) {
96 /* enable keepalive on this socket */
97 optval = 1;
98 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
99 (const char *)&optval, optlen) < 0) {
100 int error = LWS_ERRNO;
101 lwsl_err("setsockopt SO_KEEPALIVE 1 failed with error %d\n", error);
102 return 1;
103 }
104
105 alive.onoff = TRUE;
106 alive.keepalivetime = vhost->ka_time * 1000;
107 alive.keepaliveinterval = vhost->ka_interval * 1000;
108
109 if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
110 NULL, 0, &dwBytesRet, NULL, NULL)) {
111 int error = LWS_ERRNO;
112 lwsl_err("WSAIoctl SIO_KEEPALIVE_VALS 1 %lu %lu failed with error %d\n", alive.keepalivetime, alive.keepaliveinterval, error);
113 return 1;
114 }
115 }
116
117 /* Disable Nagle */
118 optval = 1;
119 #ifndef _WIN32_WCE
120 tcp_proto = getprotobyname("TCP");
121 if (!tcp_proto) {
122 int error = LWS_ERRNO;
123 lwsl_warn("getprotobyname(\"TCP\") failed with error, falling back to 6 %d\n", error);
124 protonbr = 6; /* IPPROTO_TCP */
125 } else
126 protonbr = tcp_proto->p_proto;
127 #else
128 protonbr = 6;
129 #endif
130
131 if (setsockopt(fd, protonbr, TCP_NODELAY, (const char *)&optval, optlen) ) {
132 int error = LWS_ERRNO;
133 lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", error);
134 }
135
136
137 return lws_plat_set_nonblocking(fd);
138 }
139
140
141 int
lws_interface_to_sa(int ipv6,const char * ifname,struct sockaddr_in * addr,size_t addrlen)142 lws_interface_to_sa(int ipv6,
143 const char *ifname, struct sockaddr_in *addr, size_t addrlen)
144 {
145 #ifdef LWS_WITH_IPV6
146 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
147
148 if (ipv6) {
149 if (lws_plat_inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1) {
150 return LWS_ITOSA_USABLE;
151 }
152 }
153 #endif
154
155 long long address = inet_addr(ifname);
156
157 if (address == INADDR_NONE) {
158 struct hostent *entry = gethostbyname(ifname);
159 if (entry)
160 address = ((struct in_addr *)entry->h_addr_list[0])->s_addr;
161 }
162
163 if (address == INADDR_NONE)
164 return LWS_ITOSA_NOT_EXIST;
165
166 addr->sin_addr.s_addr = (unsigned long)(lws_intptr_t)address;
167
168 return LWS_ITOSA_USABLE;
169 }
170
171 void
lws_plat_insert_socket_into_fds(struct lws_context * context,struct lws * wsi)172 lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
173 {
174 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
175 int n = LWS_POLLIN | LWS_POLLHUP | FD_CONNECT;
176
177 if (wsi->udp) {
178 lwsl_info("%s: UDP\n", __func__);
179 n = LWS_POLLIN;
180 }
181
182 pt->fds[pt->fds_count++].revents = 0;
183 WSAEventSelect(wsi->desc.sockfd, pt->events, n);
184 }
185
186 void
lws_plat_delete_socket_from_fds(struct lws_context * context,struct lws * wsi,int m)187 lws_plat_delete_socket_from_fds(struct lws_context *context,
188 struct lws *wsi, int m)
189 {
190 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
191
192 pt->fds_count--;
193 }
194
195
196 int
lws_plat_check_connection_error(struct lws * wsi)197 lws_plat_check_connection_error(struct lws *wsi)
198 {
199 int optVal;
200 int optLen = sizeof(int);
201
202 if (getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR,
203 (char*)&optVal, &optLen) != SOCKET_ERROR && optVal &&
204 optVal != LWS_EALREADY && optVal != LWS_EINPROGRESS &&
205 optVal != LWS_EWOULDBLOCK && optVal != WSAEINVAL) {
206 lwsl_debug("Connect failed SO_ERROR=%d\n", optVal);
207 return 1;
208 }
209
210 return 0;
211 }
212
213 int
lws_plat_change_pollfd(struct lws_context * context,struct lws * wsi,struct lws_pollfd * pfd)214 lws_plat_change_pollfd(struct lws_context *context,
215 struct lws *wsi, struct lws_pollfd *pfd)
216 {
217 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
218 long e = LWS_POLLHUP | FD_CONNECT;
219
220 if ((pfd->events & LWS_POLLIN))
221 e |= LWS_POLLIN;
222
223 if ((pfd->events & LWS_POLLOUT))
224 e |= LWS_POLLOUT;
225
226 if (WSAEventSelect(wsi->desc.sockfd, pt->events, e) != SOCKET_ERROR)
227 return 0;
228
229 lwsl_err("WSAEventSelect() failed with error %d\n", LWS_ERRNO);
230
231 return 1;
232 }
233
234 const char *
lws_plat_inet_ntop(int af,const void * src,char * dst,int cnt)235 lws_plat_inet_ntop(int af, const void *src, char *dst, int cnt)
236 {
237 WCHAR *buffer;
238 size_t bufferlen = (size_t)cnt;
239 BOOL ok = FALSE;
240
241 buffer = lws_malloc(bufferlen * 2, "inet_ntop");
242 if (!buffer) {
243 lwsl_err("Out of memory\n");
244 return NULL;
245 }
246
247 if (af == AF_INET) {
248 struct sockaddr_in srcaddr;
249 memset(&srcaddr, 0, sizeof(srcaddr));
250 srcaddr.sin_family = AF_INET;
251 memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
252
253 if (!WSAAddressToStringW((struct sockaddr*)&srcaddr,
254 sizeof(srcaddr), 0, buffer,
255 (LPDWORD)&bufferlen))
256 ok = TRUE;
257 #ifdef LWS_WITH_IPV6
258 } else if (af == AF_INET6) {
259 struct sockaddr_in6 srcaddr;
260 memset(&srcaddr, 0, sizeof(srcaddr));
261 srcaddr.sin6_family = AF_INET6;
262 memcpy(&(srcaddr.sin6_addr), src, sizeof(srcaddr.sin6_addr));
263
264 if (!WSAAddressToStringW((struct sockaddr*)&srcaddr,
265 sizeof(srcaddr), 0, buffer,
266 (LPDWORD)&bufferlen))
267 ok = TRUE;
268 #endif
269 } else
270 lwsl_err("Unsupported type\n");
271
272 if (!ok) {
273 int rv = WSAGetLastError();
274 lwsl_err("WSAAddressToString() : %d\n", rv);
275 } else {
276 if (WideCharToMultiByte(CP_ACP, 0, buffer, (int)bufferlen, dst,
277 cnt, 0, NULL) <= 0)
278 ok = FALSE;
279 }
280
281 lws_free(buffer);
282 return ok ? dst : NULL;
283 }
284
285 int
lws_plat_inet_pton(int af,const char * src,void * dst)286 lws_plat_inet_pton(int af, const char *src, void *dst)
287 {
288 WCHAR *buffer;
289 size_t bufferlen = strlen(src) + 1;
290 BOOL ok = FALSE;
291
292 buffer = lws_malloc(bufferlen * 2, "inet_pton");
293 if (!buffer) {
294 lwsl_err("Out of memory\n");
295 return -1;
296 }
297
298 if (MultiByteToWideChar(CP_ACP, 0, src, (int)bufferlen, buffer,
299 (int)bufferlen) <= 0) {
300 lwsl_err("Failed to convert multi byte to wide char\n");
301 lws_free(buffer);
302 return -1;
303 }
304
305 if (af == AF_INET) {
306 struct sockaddr_in dstaddr;
307 int dstaddrlen = sizeof(dstaddr);
308
309 memset(&dstaddr, 0, sizeof(dstaddr));
310 dstaddr.sin_family = AF_INET;
311
312 if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) {
313 ok = TRUE;
314 memcpy(dst, &dstaddr.sin_addr, sizeof(dstaddr.sin_addr));
315 }
316 #ifdef LWS_WITH_IPV6
317 } else if (af == AF_INET6) {
318 struct sockaddr_in6 dstaddr;
319 int dstaddrlen = sizeof(dstaddr);
320
321 memset(&dstaddr, 0, sizeof(dstaddr));
322 dstaddr.sin6_family = AF_INET6;
323
324 if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) {
325 ok = TRUE;
326 memcpy(dst, &dstaddr.sin6_addr, sizeof(dstaddr.sin6_addr));
327 }
328 #endif
329 } else
330 lwsl_err("Unsupported type\n");
331
332 if (!ok) {
333 int rv = WSAGetLastError();
334 lwsl_err("WSAAddressToString() : %d\n", rv);
335 }
336
337 lws_free(buffer);
338 return ok ? 1 : -1;
339 }
340
341 int
lws_plat_ifname_to_hwaddr(int fd,const char * ifname,uint8_t * hwaddr,int len)342 lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len)
343 {
344 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
345
346 return -1;
347 }
348
349 int
lws_plat_rawudp_broadcast(uint8_t * p,const uint8_t * canned,int canned_len,int n,int fd,const char * iface)350 lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, int canned_len,
351 int n, int fd, const char *iface)
352 {
353 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
354
355 return -1;
356 }
357
358 int
lws_plat_if_up(const char * ifname,int fd,int up)359 lws_plat_if_up(const char *ifname, int fd, int up)
360 {
361 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
362
363 return -1;
364 }
365
366 int
lws_plat_BINDTODEVICE(lws_sockfd_type fd,const char * ifname)367 lws_plat_BINDTODEVICE(lws_sockfd_type fd, const char *ifname)
368 {
369 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
370
371 return -1;
372 }
373
374 int
lws_plat_ifconfig_ip(const char * ifname,int fd,uint8_t * ip,uint8_t * mask_ip,uint8_t * gateway_ip)375 lws_plat_ifconfig_ip(const char *ifname, int fd, uint8_t *ip, uint8_t *mask_ip,
376 uint8_t *gateway_ip)
377 {
378 lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
379
380 return -1;
381 }
382
383