• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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