Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
net_sockets.c
00001 /* 00002 * TCP/IP or UDP/IP networking functions 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 00022 #if !defined(MBEDTLS_CONFIG_FILE) 00023 #include "mbedtls/config.h" 00024 #else 00025 #include MBEDTLS_CONFIG_FILE 00026 #endif 00027 00028 #if defined(MBEDTLS_NET_C) 00029 00030 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ 00031 !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) 00032 #error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h" 00033 #endif 00034 00035 #if defined(MBEDTLS_PLATFORM_C) 00036 #include "mbedtls/platform.h" 00037 #else 00038 #include <stdlib.h> 00039 #endif 00040 00041 #include "mbedtls/net_sockets.h" 00042 00043 #include <string.h> 00044 00045 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ 00046 !defined(EFI32) 00047 00048 #define IS_EINTR( ret ) ( ( ret ) == WSAEINTR ) 00049 00050 #ifdef _WIN32_WINNT 00051 #undef _WIN32_WINNT 00052 #endif 00053 /* Enables getaddrinfo() & Co */ 00054 #define _WIN32_WINNT 0x0501 00055 #include <ws2tcpip.h> 00056 00057 #include <winsock2.h> 00058 #include <windows.h> 00059 00060 #if defined(_MSC_VER) 00061 #if defined(_WIN32_WCE) 00062 #pragma comment( lib, "ws2.lib" ) 00063 #else 00064 #pragma comment( lib, "ws2_32.lib" ) 00065 #endif 00066 #endif /* _MSC_VER */ 00067 00068 #define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 ) 00069 #define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 ) 00070 #define close(fd) closesocket(fd) 00071 00072 static int wsa_init_done = 0; 00073 00074 #else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ 00075 00076 #include <sys/types.h> 00077 #include <sys/socket.h> 00078 #include <netinet/in.h> 00079 #include <arpa/inet.h> 00080 #include <sys/time.h> 00081 #include <unistd.h> 00082 #include <signal.h> 00083 #include <fcntl.h> 00084 #include <netdb.h> 00085 #include <errno.h> 00086 00087 #define IS_EINTR( ret ) ( ( ret ) == EINTR ) 00088 00089 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ 00090 00091 /* Some MS functions want int and MSVC warns if we pass size_t, 00092 * but the standard functions use socklen_t, so cast only for MSVC */ 00093 #if defined(_MSC_VER) 00094 #define MSVC_INT_CAST (int) 00095 #else 00096 #define MSVC_INT_CAST 00097 #endif 00098 00099 #include <stdio.h> 00100 00101 #include <time.h> 00102 00103 #include <stdint.h> 00104 00105 /* 00106 * Prepare for using the sockets interface 00107 */ 00108 static int net_prepare( void ) 00109 { 00110 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00111 !defined(EFI32) 00112 WSADATA wsaData; 00113 00114 if( wsa_init_done == 0 ) 00115 { 00116 if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) 00117 return( MBEDTLS_ERR_NET_SOCKET_FAILED ); 00118 00119 wsa_init_done = 1; 00120 } 00121 #else 00122 #if !defined(EFIX64) && !defined(EFI32) 00123 signal( SIGPIPE, SIG_IGN ); 00124 #endif 00125 #endif 00126 return( 0 ); 00127 } 00128 00129 /* 00130 * Initialize a context 00131 */ 00132 void mbedtls_net_init( mbedtls_net_context *ctx ) 00133 { 00134 ctx->fd = -1; 00135 } 00136 00137 /* 00138 * Initiate a TCP connection with host:port and the given protocol 00139 */ 00140 int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, 00141 const char *port, int proto ) 00142 { 00143 int ret; 00144 struct addrinfo hints, *addr_list, *cur; 00145 00146 if( ( ret = net_prepare() ) != 0 ) 00147 return( ret ); 00148 00149 /* Do name resolution with both IPv6 and IPv4 */ 00150 memset( &hints, 0, sizeof( hints ) ); 00151 hints.ai_family = AF_UNSPEC; 00152 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; 00153 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; 00154 00155 if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) 00156 return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); 00157 00158 /* Try the sockaddrs until a connection succeeds */ 00159 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; 00160 for( cur = addr_list; cur != NULL; cur = cur->ai_next ) 00161 { 00162 ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, 00163 cur->ai_protocol ); 00164 if( ctx->fd < 0 ) 00165 { 00166 ret = MBEDTLS_ERR_NET_SOCKET_FAILED; 00167 continue; 00168 } 00169 00170 if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) 00171 { 00172 ret = 0; 00173 break; 00174 } 00175 00176 close( ctx->fd ); 00177 ret = MBEDTLS_ERR_NET_CONNECT_FAILED; 00178 } 00179 00180 freeaddrinfo( addr_list ); 00181 00182 return( ret ); 00183 } 00184 00185 /* 00186 * Create a listening socket on bind_ip:port 00187 */ 00188 int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) 00189 { 00190 int n, ret; 00191 struct addrinfo hints, *addr_list, *cur; 00192 00193 if( ( ret = net_prepare() ) != 0 ) 00194 return( ret ); 00195 00196 /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ 00197 memset( &hints, 0, sizeof( hints ) ); 00198 hints.ai_family = AF_UNSPEC; 00199 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; 00200 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; 00201 if( bind_ip == NULL ) 00202 hints.ai_flags = AI_PASSIVE; 00203 00204 if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) 00205 return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); 00206 00207 /* Try the sockaddrs until a binding succeeds */ 00208 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; 00209 for( cur = addr_list; cur != NULL; cur = cur->ai_next ) 00210 { 00211 ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, 00212 cur->ai_protocol ); 00213 if( ctx->fd < 0 ) 00214 { 00215 ret = MBEDTLS_ERR_NET_SOCKET_FAILED; 00216 continue; 00217 } 00218 00219 n = 1; 00220 if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, 00221 (const char *) &n, sizeof( n ) ) != 0 ) 00222 { 00223 close( ctx->fd ); 00224 ret = MBEDTLS_ERR_NET_SOCKET_FAILED; 00225 continue; 00226 } 00227 00228 if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) 00229 { 00230 close( ctx->fd ); 00231 ret = MBEDTLS_ERR_NET_BIND_FAILED; 00232 continue; 00233 } 00234 00235 /* Listen only makes sense for TCP */ 00236 if( proto == MBEDTLS_NET_PROTO_TCP ) 00237 { 00238 if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) 00239 { 00240 close( ctx->fd ); 00241 ret = MBEDTLS_ERR_NET_LISTEN_FAILED; 00242 continue; 00243 } 00244 } 00245 00246 /* Bind was successful */ 00247 ret = 0; 00248 break; 00249 } 00250 00251 freeaddrinfo( addr_list ); 00252 00253 return( ret ); 00254 00255 } 00256 00257 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00258 !defined(EFI32) 00259 /* 00260 * Check if the requested operation would be blocking on a non-blocking socket 00261 * and thus 'failed' with a negative return value. 00262 */ 00263 static int net_would_block( const mbedtls_net_context *ctx ) 00264 { 00265 ((void) ctx); 00266 return( WSAGetLastError() == WSAEWOULDBLOCK ); 00267 } 00268 #else 00269 /* 00270 * Check if the requested operation would be blocking on a non-blocking socket 00271 * and thus 'failed' with a negative return value. 00272 * 00273 * Note: on a blocking socket this function always returns 0! 00274 */ 00275 static int net_would_block( const mbedtls_net_context *ctx ) 00276 { 00277 int err = errno; 00278 00279 /* 00280 * Never return 'WOULD BLOCK' on a non-blocking socket 00281 */ 00282 if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK ) 00283 { 00284 errno = err; 00285 return( 0 ); 00286 } 00287 00288 switch( errno = err ) 00289 { 00290 #if defined EAGAIN 00291 case EAGAIN: 00292 #endif 00293 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN 00294 case EWOULDBLOCK: 00295 #endif 00296 return( 1 ); 00297 } 00298 return( 0 ); 00299 } 00300 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ 00301 00302 /* 00303 * Accept a connection from a remote client 00304 */ 00305 int mbedtls_net_accept( mbedtls_net_context *bind_ctx, 00306 mbedtls_net_context *client_ctx, 00307 void *client_ip, size_t buf_size, size_t *ip_len ) 00308 { 00309 int ret; 00310 int type; 00311 00312 struct sockaddr_storage client_addr; 00313 00314 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ 00315 defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) 00316 socklen_t n = (socklen_t) sizeof( client_addr ); 00317 socklen_t type_len = (socklen_t) sizeof( type ); 00318 #else 00319 int n = (int) sizeof( client_addr ); 00320 int type_len = (int) sizeof( type ); 00321 #endif 00322 00323 /* Is this a TCP or UDP socket? */ 00324 if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, 00325 (void *) &type, &type_len ) != 0 || 00326 ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) 00327 { 00328 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00329 } 00330 00331 if( type == SOCK_STREAM ) 00332 { 00333 /* TCP: actual accept() */ 00334 ret = client_ctx->fd = (int) accept( bind_ctx->fd, 00335 (struct sockaddr *) &client_addr, &n ); 00336 } 00337 else 00338 { 00339 /* UDP: wait for a message, but keep it in the queue */ 00340 char buf[1] = { 0 }; 00341 00342 ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, 00343 (struct sockaddr *) &client_addr, &n ); 00344 00345 #if defined(_WIN32) 00346 if( ret == SOCKET_ERROR && 00347 WSAGetLastError() == WSAEMSGSIZE ) 00348 { 00349 /* We know buf is too small, thanks, just peeking here */ 00350 ret = 0; 00351 } 00352 #endif 00353 } 00354 00355 if( ret < 0 ) 00356 { 00357 if( net_would_block( bind_ctx ) != 0 ) 00358 return( MBEDTLS_ERR_SSL_WANT_READ ); 00359 00360 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00361 } 00362 00363 /* UDP: hijack the listening socket to communicate with the client, 00364 * then bind a new socket to accept new connections */ 00365 if( type != SOCK_STREAM ) 00366 { 00367 struct sockaddr_storage local_addr; 00368 int one = 1; 00369 00370 if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) 00371 return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); 00372 00373 client_ctx->fd = bind_ctx->fd; 00374 bind_ctx->fd = -1; /* In case we exit early */ 00375 00376 n = sizeof( struct sockaddr_storage ); 00377 if( getsockname( client_ctx->fd, 00378 (struct sockaddr *) &local_addr, &n ) != 0 || 00379 ( bind_ctx->fd = (int) socket( local_addr.ss_family, 00380 SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || 00381 setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, 00382 (const char *) &one, sizeof( one ) ) != 0 ) 00383 { 00384 return( MBEDTLS_ERR_NET_SOCKET_FAILED ); 00385 } 00386 00387 if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) 00388 { 00389 return( MBEDTLS_ERR_NET_BIND_FAILED ); 00390 } 00391 } 00392 00393 if( client_ip != NULL ) 00394 { 00395 if( client_addr.ss_family == AF_INET ) 00396 { 00397 struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; 00398 *ip_len = sizeof( addr4->sin_addr.s_addr ); 00399 00400 if( buf_size < *ip_len ) 00401 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); 00402 00403 memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); 00404 } 00405 else 00406 { 00407 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; 00408 *ip_len = sizeof( addr6->sin6_addr.s6_addr ); 00409 00410 if( buf_size < *ip_len ) 00411 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); 00412 00413 memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); 00414 } 00415 } 00416 00417 return( 0 ); 00418 } 00419 00420 /* 00421 * Set the socket blocking or non-blocking 00422 */ 00423 int mbedtls_net_set_block( mbedtls_net_context *ctx ) 00424 { 00425 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00426 !defined(EFI32) 00427 u_long n = 0; 00428 return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); 00429 #else 00430 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); 00431 #endif 00432 } 00433 00434 int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) 00435 { 00436 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00437 !defined(EFI32) 00438 u_long n = 1; 00439 return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); 00440 #else 00441 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); 00442 #endif 00443 } 00444 00445 /* 00446 * Check if data is available on the socket 00447 */ 00448 00449 int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ) 00450 { 00451 int ret; 00452 struct timeval tv; 00453 00454 fd_set read_fds; 00455 fd_set write_fds; 00456 00457 int fd = ctx->fd; 00458 00459 if( fd < 0 ) 00460 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00461 00462 #if defined(__has_feature) 00463 #if __has_feature(memory_sanitizer) 00464 /* Ensure that memory sanitizers consider read_fds and write_fds as 00465 * initialized even on platforms such as Glibc/x86_64 where FD_ZERO 00466 * is implemented in assembly. */ 00467 memset( &read_fds, 0, sizeof( read_fds ) ); 00468 memset( &write_fds, 0, sizeof( write_fds ) ); 00469 #endif 00470 #endif 00471 00472 FD_ZERO( &read_fds ); 00473 if( rw & MBEDTLS_NET_POLL_READ ) 00474 { 00475 rw &= ~MBEDTLS_NET_POLL_READ; 00476 FD_SET( fd, &read_fds ); 00477 } 00478 00479 FD_ZERO( &write_fds ); 00480 if( rw & MBEDTLS_NET_POLL_WRITE ) 00481 { 00482 rw &= ~MBEDTLS_NET_POLL_WRITE; 00483 FD_SET( fd, &write_fds ); 00484 } 00485 00486 if( rw != 0 ) 00487 return( MBEDTLS_ERR_NET_BAD_INPUT_DATA ); 00488 00489 tv.tv_sec = timeout / 1000; 00490 tv.tv_usec = ( timeout % 1000 ) * 1000; 00491 00492 do 00493 { 00494 ret = select( fd + 1, &read_fds, &write_fds, NULL, 00495 timeout == (uint32_t) -1 ? NULL : &tv ); 00496 } 00497 while( IS_EINTR( ret ) ); 00498 00499 if( ret < 0 ) 00500 return( MBEDTLS_ERR_NET_POLL_FAILED ); 00501 00502 ret = 0; 00503 if( FD_ISSET( fd, &read_fds ) ) 00504 ret |= MBEDTLS_NET_POLL_READ; 00505 if( FD_ISSET( fd, &write_fds ) ) 00506 ret |= MBEDTLS_NET_POLL_WRITE; 00507 00508 return( ret ); 00509 } 00510 00511 /* 00512 * Portable usleep helper 00513 */ 00514 void mbedtls_net_usleep( unsigned long usec ) 00515 { 00516 #if defined(_WIN32) 00517 Sleep( ( usec + 999 ) / 1000 ); 00518 #else 00519 struct timeval tv; 00520 tv.tv_sec = usec / 1000000; 00521 #if defined(__unix__) || defined(__unix) || \ 00522 ( defined(__APPLE__) && defined(__MACH__) ) 00523 tv.tv_usec = (suseconds_t) usec % 1000000; 00524 #else 00525 tv.tv_usec = usec % 1000000; 00526 #endif 00527 select( 0, NULL, NULL, NULL, &tv ); 00528 #endif 00529 } 00530 00531 /* 00532 * Read at most 'len' characters 00533 */ 00534 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) 00535 { 00536 int ret; 00537 int fd = ((mbedtls_net_context *) ctx)->fd; 00538 00539 if( fd < 0 ) 00540 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00541 00542 ret = (int) read( fd, buf, len ); 00543 00544 if( ret < 0 ) 00545 { 00546 if( net_would_block( ctx ) != 0 ) 00547 return( MBEDTLS_ERR_SSL_WANT_READ ); 00548 00549 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00550 !defined(EFI32) 00551 if( WSAGetLastError() == WSAECONNRESET ) 00552 return( MBEDTLS_ERR_NET_CONN_RESET ); 00553 #else 00554 if( errno == EPIPE || errno == ECONNRESET ) 00555 return( MBEDTLS_ERR_NET_CONN_RESET ); 00556 00557 if( errno == EINTR ) 00558 return( MBEDTLS_ERR_SSL_WANT_READ ); 00559 #endif 00560 00561 return( MBEDTLS_ERR_NET_RECV_FAILED ); 00562 } 00563 00564 return( ret ); 00565 } 00566 00567 /* 00568 * Read at most 'len' characters, blocking for at most 'timeout' ms 00569 */ 00570 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, 00571 size_t len, uint32_t timeout ) 00572 { 00573 int ret; 00574 struct timeval tv; 00575 fd_set read_fds; 00576 int fd = ((mbedtls_net_context *) ctx)->fd; 00577 00578 if( fd < 0 ) 00579 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00580 00581 FD_ZERO( &read_fds ); 00582 FD_SET( fd, &read_fds ); 00583 00584 tv.tv_sec = timeout / 1000; 00585 tv.tv_usec = ( timeout % 1000 ) * 1000; 00586 00587 ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); 00588 00589 /* Zero fds ready means we timed out */ 00590 if( ret == 0 ) 00591 return( MBEDTLS_ERR_SSL_TIMEOUT ); 00592 00593 if( ret < 0 ) 00594 { 00595 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00596 !defined(EFI32) 00597 if( WSAGetLastError() == WSAEINTR ) 00598 return( MBEDTLS_ERR_SSL_WANT_READ ); 00599 #else 00600 if( errno == EINTR ) 00601 return( MBEDTLS_ERR_SSL_WANT_READ ); 00602 #endif 00603 00604 return( MBEDTLS_ERR_NET_RECV_FAILED ); 00605 } 00606 00607 /* This call will not block */ 00608 return( mbedtls_net_recv( ctx, buf, len ) ); 00609 } 00610 00611 /* 00612 * Write at most 'len' characters 00613 */ 00614 int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) 00615 { 00616 int ret; 00617 int fd = ((mbedtls_net_context *) ctx)->fd; 00618 00619 if( fd < 0 ) 00620 return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); 00621 00622 ret = (int) write( fd, buf, len ); 00623 00624 if( ret < 0 ) 00625 { 00626 if( net_would_block( ctx ) != 0 ) 00627 return( MBEDTLS_ERR_SSL_WANT_WRITE ); 00628 00629 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ 00630 !defined(EFI32) 00631 if( WSAGetLastError() == WSAECONNRESET ) 00632 return( MBEDTLS_ERR_NET_CONN_RESET ); 00633 #else 00634 if( errno == EPIPE || errno == ECONNRESET ) 00635 return( MBEDTLS_ERR_NET_CONN_RESET ); 00636 00637 if( errno == EINTR ) 00638 return( MBEDTLS_ERR_SSL_WANT_WRITE ); 00639 #endif 00640 00641 return( MBEDTLS_ERR_NET_SEND_FAILED ); 00642 } 00643 00644 return( ret ); 00645 } 00646 00647 /* 00648 * Gracefully close the connection 00649 */ 00650 void mbedtls_net_free( mbedtls_net_context *ctx ) 00651 { 00652 if( ctx->fd == -1 ) 00653 return; 00654 00655 shutdown( ctx->fd, 2 ); 00656 close( ctx->fd ); 00657 00658 ctx->fd = -1; 00659 } 00660 00661 #endif /* MBEDTLS_NET_C */
Generated on Tue Jul 12 2022 12:45:36 by
1.7.2