• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2021 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 #define MBEDTLS_ALLOW_PRIVATE_ACCESS
29 #include "private-lib-core.h"
30 
31 #if defined(LWS_WITH_MBEDTLS)
32 #if defined(LWS_HAVE_MBEDTLS_NET_SOCKETS)
33 #include "mbedtls/net_sockets.h"
34 #else
35 #include "mbedtls/net.h"
36 #endif
37 #endif
38 
39 int
lws_send_pipe_choked(struct lws * wsi)40 lws_send_pipe_choked(struct lws *wsi)
41 {	struct lws *wsi_eff;
42 
43 #if defined(LWS_WITH_HTTP2)
44 	wsi_eff = lws_get_network_wsi(wsi);
45 #else
46 	wsi_eff = wsi;
47 #endif
48 	/* the fact we checked implies we avoided back-to-back writes */
49 	wsi_eff->could_have_pending = 0;
50 
51 	/* treat the fact we got a truncated send pending as if we're choked */
52 	if (lws_has_buffered_out(wsi_eff)
53 #if defined(LWS_WITH_HTTP_STREAM_COMPRESSION)
54 	    ||wsi->http.comp_ctx.buflist_comp ||
55 	      wsi->http.comp_ctx.may_have_more
56 #endif
57 	)
58 		return 1;
59 
60 	return (int)wsi_eff->sock_send_blocking;
61 }
62 
63 int
lws_poll_listen_fd(struct lws_pollfd * fd)64 lws_poll_listen_fd(struct lws_pollfd *fd)
65 {
66 	fd_set readfds;
67 	struct timeval tv = { 0, 0 };
68 
69 	assert((fd->events & LWS_POLLIN) == LWS_POLLIN);
70 
71 	FD_ZERO(&readfds);
72 	FD_SET(fd->fd, &readfds);
73 
74 	return select(((int)fd->fd) + 1, &readfds, NULL, NULL, &tv);
75 }
76 
77 int
lws_plat_set_nonblocking(lws_sockfd_type fd)78 lws_plat_set_nonblocking(lws_sockfd_type fd)
79 {
80 	u_long optl = 1;
81 	int result = !!ioctlsocket(fd, FIONBIO, &optl);
82 	if (result)
83 	{
84 		int error = LWS_ERRNO;
85 		lwsl_err("ioctlsocket FIONBIO 1 failed with error %d\n", error);
86 	}
87 	return result;
88 }
89 
90 int
lws_plat_set_socket_options(struct lws_vhost * vhost,lws_sockfd_type fd,int unix_skt)91 lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
92 			    int unix_skt)
93 {
94 	int optval = 1;
95 	int optlen = sizeof(optval);
96 	DWORD dwBytesRet;
97 	struct tcp_keepalive alive;
98 	int protonbr;
99 #ifndef _WIN32_WCE
100 	struct protoent *tcp_proto;
101 #endif
102 
103 	if (vhost->ka_time) {
104 		/* enable keepalive on this socket */
105 		optval = 1;
106 		if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
107 			       (const char *)&optval, optlen) < 0) {
108 			int error = LWS_ERRNO;
109 			lwsl_err("setsockopt SO_KEEPALIVE 1 failed with error %d\n", error);
110 			return 1;
111 		}
112 
113 		alive.onoff = TRUE;
114 		alive.keepalivetime = vhost->ka_time * 1000;
115 		alive.keepaliveinterval = vhost->ka_interval * 1000;
116 
117 		if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
118 			     NULL, 0, &dwBytesRet, NULL, NULL)) {
119 			int error = LWS_ERRNO;
120 			lwsl_err("WSAIoctl SIO_KEEPALIVE_VALS 1 %lu %lu failed with error %d\n", alive.keepalivetime, alive.keepaliveinterval, error);
121 			return 1;
122 		}
123 	}
124 
125 	/* Disable Nagle */
126 	optval = 1;
127 #ifndef _WIN32_WCE
128 	tcp_proto = getprotobyname("TCP");
129 	if (!tcp_proto) {
130 		int error = LWS_ERRNO;
131 		lwsl_warn("getprotobyname(\"TCP\") failed with error, falling back to 6 %d\n", error);
132 		protonbr = 6;  /* IPPROTO_TCP */
133 	} else
134 		protonbr = tcp_proto->p_proto;
135 #else
136 	protonbr = 6;
137 #endif
138 
139 	if (setsockopt(fd, protonbr, TCP_NODELAY, (const char *)&optval, optlen) ) {
140 		int error = LWS_ERRNO;
141 		lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", error);
142 	}
143 
144 	return lws_plat_set_nonblocking(fd);
145 }
146 
147 int
lws_plat_set_socket_options_ip(lws_sockfd_type fd,uint8_t pri,int lws_flags)148 lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
149 {
150 	/*
151 	 * Seems to require "differeniated services" but no docs
152 	 *
153 	 * https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
154 	 * https://docs.microsoft.com/en-us/previous-versions/windows/desktop/qos/differentiated-services
155 	 */
156 	lwsl_warn("%s: not implemented on windows platform\n", __func__);
157 
158 	return 0;
159 }
160 
161 int
lws_interface_to_sa(int ipv6,const char * ifname,struct sockaddr_in * addr,size_t addrlen)162 lws_interface_to_sa(int ipv6,
163 		const char *ifname, struct sockaddr_in *addr, size_t addrlen)
164 {
165 	long long address;
166 #ifdef LWS_WITH_IPV6
167 	struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
168 
169 	if (ipv6) {
170 		if (lws_plat_inet_pton(AF_INET6, ifname, &addr6->sin6_addr) == 1) {
171 			return LWS_ITOSA_USABLE;
172 		}
173 	}
174 #endif
175 
176 	address = inet_addr(ifname);
177 
178 	if (address == INADDR_NONE) {
179 		struct hostent *entry = gethostbyname(ifname);
180 		if (entry)
181 			address = ((struct in_addr *)entry->h_addr_list[0])->s_addr;
182 	}
183 
184 	if (address == INADDR_NONE)
185 		return LWS_ITOSA_NOT_EXIST;
186 
187 	addr->sin_addr.s_addr = (unsigned long)(lws_intptr_t)address;
188 
189 	return LWS_ITOSA_USABLE;
190 }
191 
192 void
lws_plat_insert_socket_into_fds(struct lws_context * context,struct lws * wsi)193 lws_plat_insert_socket_into_fds(struct lws_context *context, struct lws *wsi)
194 {
195 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
196 
197 #if defined(LWS_WITH_UDP)
198 	if (wsi->udp) {
199 		lwsl_info("%s: UDP\n", __func__);
200 		pt->fds[pt->fds_count].events |= LWS_POLLIN;
201 	}
202 #endif
203 
204 	if (context->event_loop_ops->io)
205 		context->event_loop_ops->io(wsi, LWS_EV_START | LWS_EV_READ);
206 
207 	pt->fds[pt->fds_count++].revents = 0;
208 
209 	lws_plat_change_pollfd(context, wsi, &pt->fds[pt->fds_count - 1]);
210 }
211 
212 void
lws_plat_delete_socket_from_fds(struct lws_context * context,struct lws * wsi,int m)213 lws_plat_delete_socket_from_fds(struct lws_context *context,
214 						struct lws *wsi, int m)
215 {
216 	struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
217 
218 	pt->fds_count--;
219 }
220 
221 
222 int
lws_plat_check_connection_error(struct lws * wsi)223 lws_plat_check_connection_error(struct lws *wsi)
224 {
225 	int optVal;
226 	int optLen = sizeof(int);
227 
228 	if (getsockopt(wsi->desc.sockfd, SOL_SOCKET, SO_ERROR,
229 			   (char*)&optVal, &optLen) != SOCKET_ERROR && optVal &&
230 		optVal != LWS_EALREADY && optVal != LWS_EINPROGRESS &&
231 		optVal != LWS_EWOULDBLOCK && optVal != WSAEINVAL) {
232 		   lwsl_debug("Connect failed SO_ERROR=%d\n", optVal);
233 		   return 1;
234 	}
235 
236 	return 0;
237 }
238 
239 int
lws_plat_change_pollfd(struct lws_context * context,struct lws * wsi,struct lws_pollfd * pfd)240 lws_plat_change_pollfd(struct lws_context *context, struct lws *wsi,
241 		       struct lws_pollfd *pfd)
242 {
243 	//struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
244 
245 	return 0;
246 }
247 
248 #if defined(LWS_WITH_TLS)
249 
250 int
lws_plat_vhost_tls_client_ctx_init(struct lws_vhost * vhost)251 lws_plat_vhost_tls_client_ctx_init(struct lws_vhost *vhost)
252 {
253 #if !defined(LWS_WITH_MBEDTLS) && defined(LWS_SSL_CLIENT_USE_OS_CA_CERTS)
254 	PCCERT_CONTEXT pcc = NULL;
255 	CERT_ENHKEY_USAGE* ceu = NULL;
256 	DWORD ceu_alloc = 0;
257 	X509_STORE* store;
258 	HCERTSTORE hStore;
259 	int imps = 0;
260 
261 	if (lws_check_opt(vhost->options,
262 			  LWS_SERVER_OPTION_DISABLE_OS_CA_CERTS))
263 		return 0;
264 
265 	/*
266 	 * Windows Trust Store code adapted from curl (MIT) openssl.c
267 	 * https://github.com/warmcat/libwebsockets/pull/2233
268 	 */
269 
270 	store = SSL_CTX_get_cert_store(vhost->tls.ssl_client_ctx);
271 	hStore = CertOpenSystemStore((HCRYPTPROV_LEGACY)NULL, TEXT("ROOT"));
272 
273 	if (!hStore) {
274 		lwsl_notice("%s: no store\n", __func__);
275 		return 1;
276 	}
277 
278 	do {
279 		const unsigned char* ecert;
280 		char cert_name[256];
281 		DWORD req_size = 0;
282 		BYTE key_usage[2];
283 		FILETIME ft;
284 		X509* x509;
285 
286 		pcc = CertEnumCertificatesInStore(hStore, pcc);
287 		if (!pcc)
288 			break;
289 
290 		if (!CertGetNameStringA(pcc, CERT_NAME_SIMPLE_DISPLAY_TYPE,
291 					0, NULL, cert_name, sizeof(cert_name)))
292 			strcpy(cert_name, "Unknown");
293 
294 		lwsl_debug("%s: Checking cert \"%s\"\n", __func__, cert_name);
295 
296 		ecert = (const unsigned char*)pcc->pbCertEncoded;
297 		if (!ecert)
298 			continue;
299 
300 		GetSystemTimeAsFileTime(&ft);
301 		if (CompareFileTime(&pcc->pCertInfo->NotBefore, &ft) > 0 ||
302 		    CompareFileTime(&ft, &pcc->pCertInfo->NotAfter) > 0)
303 			continue;
304 
305 		/* If key usage exists check for signing attribute */
306 		if (CertGetIntendedKeyUsage(pcc->dwCertEncodingType,
307 			pcc->pCertInfo,
308 			key_usage, sizeof(key_usage))) {
309 			if (!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE))
310 				continue;
311 		} else
312 			if (GetLastError())
313 				continue;
314 
315 		/*
316 		 * If enhanced key usage exists check for server auth attribute.
317 		 *
318 		 * Note "In a Microsoft environment, a certificate might also
319 		 * have EKU extended properties that specify valid uses for the
320 		 * certificate."
321 		 * The call below checks both, and behavior varies depending on
322 		 * what is found. For more details see CertGetEnhancedKeyUsage
323 		 * doc.
324 		 */
325 		if (!CertGetEnhancedKeyUsage(pcc, 0, NULL, &req_size))
326 			continue;
327 
328 		if (req_size && req_size > ceu_alloc) {
329 			void* tmp = lws_realloc(ceu, req_size, __func__);
330 
331 			if (!tmp) {
332 				lwsl_err("%s: OOM", __func__);
333 				break;
334 			}
335 
336 			ceu = (CERT_ENHKEY_USAGE*)tmp;
337 			ceu_alloc = req_size;
338 		}
339 
340 		if (!CertGetEnhancedKeyUsage(pcc, 0, ceu, &req_size))
341 			continue;
342 
343 		if (!ceu || (ceu && !ceu->cUsageIdentifier)) {
344 			/*
345 			 * "If GetLastError returns CRYPT_E_NOT_FOUND, the
346 			 * certificate is good for all uses. If it returns
347 			 * zero, the certificate has no valid uses."
348 			 */
349 			if ((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND)
350 				continue;
351 
352 			/* ... allow it... */
353 
354 		} else
355 			if (ceu) {
356 				BOOL found = FALSE;
357 				DWORD i;
358 
359 				/*
360 				 * If there is a CEU, check that it specifies
361 				 * we can use the cert for server validation
362 				 */
363 
364 				for (i = 0; i < ceu->cUsageIdentifier; i++) {
365 					if (strcmp("1.3.6.1.5.5.7.3.1"
366 						   /* OID server auth */,
367 						   ceu->rgpszUsageIdentifier[i]))
368 						continue;
369 
370 					found = TRUE;
371 					break;
372 				}
373 
374 				if (!found)
375 					/* Don't use cert if no usage match */
376 					continue;
377 			}
378 
379 		x509 = d2i_X509(NULL, &ecert, pcc->cbCertEncoded);
380 		if (!x509)
381 			/* We can't parse it as am X.509, skip it */
382 			continue;
383 
384 		if (X509_STORE_add_cert(store, x509) == 1) {
385 			lwsl_debug("%s: Imported cert \"%s\"\n", __func__,
386 				  cert_name);
387 			imps++;
388 		}
389 
390 		/*
391 		 * Treat failure as nonfatal, eg, may be dupe
392 		 */
393 
394 		X509_free(x509);
395 	} while (1);
396 
397 	lws_free(ceu);
398 	CertFreeCertificateContext(pcc);
399 	CertCloseStore(hStore, 0);
400 
401 	lwsl_notice("%s: Imported %d certs from plat store\n", __func__, imps);
402 #endif
403 
404 	return 0;
405 }
406 
407 #endif
408 
409 const char *
lws_plat_inet_ntop(int af,const void * src,char * dst,socklen_t cnt)410 lws_plat_inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
411 {
412 	WCHAR *buffer;
413 	size_t bufferlen = (size_t)cnt;
414 	BOOL ok = FALSE;
415 
416 	buffer = lws_malloc(bufferlen * 2, "inet_ntop");
417 	if (!buffer) {
418 		lwsl_err("Out of memory\n");
419 		return NULL;
420 	}
421 
422 	if (af == AF_INET) {
423 		struct sockaddr_in srcaddr;
424 		memset(&srcaddr, 0, sizeof(srcaddr));
425 		srcaddr.sin_family = AF_INET;
426 		memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
427 
428 		if (!WSAAddressToStringW((struct sockaddr*)&srcaddr,
429 					sizeof(srcaddr), 0, buffer,
430 					(LPDWORD)&bufferlen))
431 			ok = TRUE;
432 #ifdef LWS_WITH_IPV6
433 	} else if (af == AF_INET6) {
434 		struct sockaddr_in6 srcaddr;
435 		memset(&srcaddr, 0, sizeof(srcaddr));
436 		srcaddr.sin6_family = AF_INET6;
437 		memcpy(&(srcaddr.sin6_addr), src, sizeof(srcaddr.sin6_addr));
438 
439 		if (!WSAAddressToStringW((struct sockaddr*)&srcaddr,
440 					 sizeof(srcaddr), 0, buffer,
441 					 (LPDWORD)&bufferlen))
442 			ok = TRUE;
443 #endif
444 	} else
445 		lwsl_err("Unsupported type\n");
446 
447 	if (!ok) {
448 		int rv = WSAGetLastError();
449 		lwsl_err("WSAAddressToString() : %d\n", rv);
450 	} else {
451 		if (WideCharToMultiByte(CP_ACP, 0, buffer, (int)bufferlen, dst,
452 					cnt, 0, NULL) <= 0)
453 			ok = FALSE;
454 	}
455 
456 	lws_free(buffer);
457 	return ok ? dst : NULL;
458 }
459 
460 int
lws_plat_inet_pton(int af,const char * src,void * dst)461 lws_plat_inet_pton(int af, const char *src, void *dst)
462 {
463 	WCHAR *buffer;
464 	size_t bufferlen = strlen(src) + 1;
465 	BOOL ok = FALSE;
466 
467 	buffer = lws_malloc(bufferlen * 2, "inet_pton");
468 	if (!buffer) {
469 		lwsl_err("Out of memory\n");
470 		return -1;
471 	}
472 
473 	if (MultiByteToWideChar(CP_ACP, 0, src, (int)bufferlen, buffer,
474 				(int)bufferlen) <= 0) {
475 		lwsl_err("Failed to convert multi byte to wide char\n");
476 		lws_free(buffer);
477 		return -1;
478 	}
479 
480 	if (af == AF_INET) {
481 		struct sockaddr_in dstaddr;
482 		int dstaddrlen = sizeof(dstaddr);
483 
484 		memset(&dstaddr, 0, sizeof(dstaddr));
485 		dstaddr.sin_family = AF_INET;
486 
487 		if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) {
488 			ok = TRUE;
489 			memcpy(dst, &dstaddr.sin_addr, sizeof(dstaddr.sin_addr));
490 		}
491 #ifdef LWS_WITH_IPV6
492 	} else if (af == AF_INET6) {
493 		struct sockaddr_in6 dstaddr;
494 		int dstaddrlen = sizeof(dstaddr);
495 
496 		memset(&dstaddr, 0, sizeof(dstaddr));
497 		dstaddr.sin6_family = AF_INET6;
498 
499 		if (!WSAStringToAddressW(buffer, af, 0, (struct sockaddr *) &dstaddr, &dstaddrlen)) {
500 			ok = TRUE;
501 			memcpy(dst, &dstaddr.sin6_addr, sizeof(dstaddr.sin6_addr));
502 		}
503 #endif
504 	} else
505 		lwsl_err("Unsupported type\n");
506 
507 	if (!ok) {
508 		int rv = WSAGetLastError();
509 		lwsl_err("WSAAddressToString() : %d\n", rv);
510 	}
511 
512 	lws_free(buffer);
513 	return ok ? 1 : -1;
514 }
515 
516 int
lws_plat_ifname_to_hwaddr(int fd,const char * ifname,uint8_t * hwaddr,int len)517 lws_plat_ifname_to_hwaddr(int fd, const char *ifname, uint8_t *hwaddr, int len)
518 {
519 	lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
520 
521 	return -1;
522 }
523 
524 int
lws_plat_rawudp_broadcast(uint8_t * p,const uint8_t * canned,size_t canned_len,size_t n,int fd,const char * iface)525 lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, size_t canned_len,
526 			  size_t n, int fd, const char *iface)
527 {
528 	lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
529 
530 	return -1;
531 }
532 
533 int
lws_plat_if_up(const char * ifname,int fd,int up)534 lws_plat_if_up(const char *ifname, int fd, int up)
535 {
536 	lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
537 
538 	return -1;
539 }
540 
541 int
lws_plat_BINDTODEVICE(lws_sockfd_type fd,const char * ifname)542 lws_plat_BINDTODEVICE(lws_sockfd_type fd, const char *ifname)
543 {
544 	lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
545 
546 	return -1;
547 }
548 
549 int
lws_plat_ifconfig(int fd,uint8_t * ip,lws_dhcpc_ifstate_t * is)550 lws_plat_ifconfig(int fd, uint8_t *ip, lws_dhcpc_ifstate_t *is)
551 {
552 	lwsl_err("%s: UNIMPLEMENTED on this platform\n", __func__);
553 
554 	return -1;
555 }
556 
557 #if defined(LWS_WITH_MBEDTLS)
558 int
lws_plat_mbedtls_net_send(void * ctx,const uint8_t * buf,size_t len)559 lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len)
560 {
561 	int fd = ((mbedtls_net_context *) ctx)->fd;
562 	int ret, en;
563 
564 	if (fd < 0)
565 		return MBEDTLS_ERR_NET_INVALID_CONTEXT;
566 
567 	ret = send(fd, buf, (unsigned int)len, 0);
568 	if (ret >= 0)
569 		return ret;
570 
571 	en = LWS_ERRNO;
572 	if (en == EAGAIN || en == EWOULDBLOCK)
573 		return MBEDTLS_ERR_SSL_WANT_WRITE;
574 
575 	ret = WSAGetLastError();
576 	lwsl_notice("%s: errno %d, GLE %d\n", __func__, en, ret);
577 	if (ret == WSAECONNRESET )
578             return( MBEDTLS_ERR_NET_CONN_RESET );
579 
580 	return MBEDTLS_ERR_NET_SEND_FAILED;
581 }
582 
583 int
lws_plat_mbedtls_net_recv(void * ctx,unsigned char * buf,size_t len)584 lws_plat_mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len)
585 {
586 	int fd = ((mbedtls_net_context *) ctx)->fd;
587 	int ret, en;
588 
589 	if (fd < 0)
590 		return MBEDTLS_ERR_NET_INVALID_CONTEXT;
591 
592 	ret = (int)recv(fd, buf, (unsigned int)len, 0);
593 	if (ret >= 0)
594 		return ret;
595 
596 	en = LWS_ERRNO;
597 	if (en == EAGAIN || en == EWOULDBLOCK)
598 		return MBEDTLS_ERR_SSL_WANT_READ;
599 
600 	ret = WSAGetLastError();
601 	lwsl_notice("%s: errno %d, GLE %d\n", __func__, en, ret);
602 
603         if (ret == WSAECONNRESET)
604             return MBEDTLS_ERR_NET_CONN_RESET;
605 
606 	return MBEDTLS_ERR_NET_RECV_FAILED;
607 }
608 #endif
609 
610