Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers net_sockets.c Source File

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