diff --git a/include/polarssl/error.h b/include/polarssl/error.h index e6ad54a04..00c794e3c 100644 --- a/include/polarssl/error.h +++ b/include/polarssl/error.h @@ -65,7 +65,7 @@ * DES 1 0x0032-0x0032 * CTR_DBRG 4 0x0034-0x003A * ENTROPY 3 0x003C-0x0040 - * NET 11 0x0042-0x0056 + * NET 12 0x0042-0x0056 0x0011-0x0011 * ENTROPY 1 0x0058-0x0058 * ASN1 7 0x0060-0x006C * MD2 1 0x0070-0x0070 diff --git a/include/polarssl/net.h b/include/polarssl/net.h index 4271a7ce4..d0c736603 100644 --- a/include/polarssl/net.h +++ b/include/polarssl/net.h @@ -27,9 +27,14 @@ #ifndef POLARSSL_NET_H #define POLARSSL_NET_H +#if !defined(POLARSSL_CONFIG_FILE) +#include "config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + #include -#define POLARSSL_ERR_NET_UNKNOWN_HOST -0x0056 /**< Failed to get an IP address for the given hostname. */ #define POLARSSL_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ #define POLARSSL_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ #define POLARSSL_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ @@ -40,6 +45,8 @@ #define POLARSSL_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ #define POLARSSL_ERR_NET_WANT_READ -0x0052 /**< Connection requires a read call. */ #define POLARSSL_ERR_NET_WANT_WRITE -0x0054 /**< Connection requires a write call. */ +#define POLARSSL_ERR_NET_UNKNOWN_HOST -0x0056 /**< Failed to get an IP address for the given hostname. */ +#define POLARSSL_ERR_NET_TIMEOUT -0x0011 /**< The operation timed out. */ #define POLARSSL_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ @@ -160,6 +167,31 @@ int net_recv( void *ctx, unsigned char *buf, size_t len ); */ int net_send( void *ctx, const unsigned char *buf, size_t len ); +#if defined(POLARSSL_HAVE_TIME) +/** + * \brief Read at most 'len' characters, blocking for at most + * 'timeout' seconds. If no error occurs, the actual amount + * read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * \param timeout Maximum number of seconds to wait for data + * + * \return This function returns the number of bytes received, + * or a non-zero error code: + * POLARSSL_ERR_NET_TIMEOUT if the operation timed out, + * POLARSSL_ERR_NET_WANT_READ if interrupted by a signal. + * + * \note This function will block (until data becomes available or + * timeout is reached) even if the socket is set to + * non-blocking. Handling timeouts with non-blocking reads + * requires a different strategy. + */ +int net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + unsigned char timeout ); +#endif /* POLARSSL_HAVE_TIME */ + /** * \brief Gracefully shutdown the connection * diff --git a/library/error.c b/library/error.c index 35ecb97c3..f3c18c259 100644 --- a/library/error.c +++ b/library/error.c @@ -658,8 +658,6 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) #endif /* POLARSSL_MD5_C */ #if defined(POLARSSL_NET_C) - if( use_ret == -(POLARSSL_ERR_NET_UNKNOWN_HOST) ) - snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); if( use_ret == -(POLARSSL_ERR_NET_SOCKET_FAILED) ) snprintf( buf, buflen, "NET - Failed to open a socket" ); if( use_ret == -(POLARSSL_ERR_NET_CONNECT_FAILED) ) @@ -680,6 +678,10 @@ void polarssl_strerror( int ret, char *buf, size_t buflen ) snprintf( buf, buflen, "NET - Connection requires a read call" ); if( use_ret == -(POLARSSL_ERR_NET_WANT_WRITE) ) snprintf( buf, buflen, "NET - Connection requires a write call" ); + if( use_ret == -(POLARSSL_ERR_NET_UNKNOWN_HOST) ) + snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); + if( use_ret == -(POLARSSL_ERR_NET_TIMEOUT) ) + snprintf( buf, buflen, "NET - The operation timed out" ); #endif /* POLARSSL_NET_C */ #if defined(POLARSSL_OID_C) diff --git a/library/net.c b/library/net.c index a0af807ed..7336f212d 100644 --- a/library/net.c +++ b/library/net.c @@ -583,6 +583,49 @@ int net_recv( void *ctx, unsigned char *buf, size_t len ) return( ret ); } +#if defined(POLARSSL_HAVE_TIME) +/* + * Read at most 'len' characters, blocking for at most 'timeout' seconds + */ +int net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + unsigned char timeout ) +{ + int ret; + struct timeval tv; + fd_set read_fds; + int fd = *((int *) ctx); + + FD_ZERO( &read_fds ); + FD_SET( fd, &read_fds ); + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + ret = select( fd + 1, &read_fds, NULL, NULL, &tv ); + + /* Zero fds ready means we timed out */ + if( ret == 0 ) + return( POLARSSL_ERR_NET_TIMEOUT ); + + if( ret < 0 ) + { +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAEINTR ) + return( POLARSSL_ERR_NET_WANT_READ ); +#else + if( errno == EINTR ) + return( POLARSSL_ERR_NET_WANT_READ ); +#endif + + return( POLARSSL_ERR_NET_RECV_FAILED ); + } + + /* This call will not block */ + return( net_recv( ctx, buf, len ) ); +} +#endif /* POLARSSL_HAVE_TIME */ + /* * Write at most 'len' characters */