Knight KE / Mbed OS Game_Master
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 #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 */