Fix TCP with Timeout

wolfSSL remains agnostic to network socket behavior be it blocking or non-blocking. The non-blocking flag was meant for the default EmbedRecvFrom() callback for use with UDP to assist the timing of the handshake.

1. Deprecate wolfSSL_set_using_nonblock() and wolfSSL_get_using_nonblock() for use with TLS sockets. They become don't-cares when used with TLS sessions.
2. Added functions wolfSSL_dtls_set_using_nonblock() and wolfSSL_dtls_get_using_nonblock().
3. Removed a test case from EmbedReceive() that only applied to UDP.
4. Removed the checks for non-blocking sockets from EmbedReceive().
5. Socket timeouts only apply to DTLS sessions.
This commit is contained in:
John Safranek 2018-05-23 11:29:16 -07:00
parent d8c33c5551
commit b1ed852f36
7 changed files with 111 additions and 100 deletions

View File

@ -485,7 +485,6 @@
#define CyaDTLSv1_2_client_method wolfDTLSv1_2_client_method
#define CyaDTLSv1_2_server_method wolfDTLSv1_2_server_method
#define CyaSSL_set_group_messages wolfSSL_set_group_messages
#define CyaSSL_set_using_nonblock wolfSSL_set_using_nonblock
#define CyaSSL_CTX_set_cipher_list wolfSSL_CTX_set_cipher_list
#define CyaSSL_CTX_set_group_messages wolfSSL_CTX_set_group_messages
#define CyaSSL_CTX_set_session_cache_mode wolfSSL_CTX_set_session_cache_mode
@ -623,6 +622,7 @@
#define CyaSSL_dtls_get_peer wolfSSL_dtls_get_peer
#define CyaSSL_dtls_got_timeout wolfSSL_dtls_got_timeout
#define CyaSSL_dtls_get_current_timeout wolfSSL_dtls_get_current_timeout
#define CyaSSL_set_using_nonblock wolfSSL_dtls_set_using_nonblock
/* Certificate Manager */
#define CyaSSL_CertManagerNew wolfSSL_CertManagerNew

View File

@ -1570,65 +1570,6 @@ WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl);
\sa wolfSSL_set_fd
*/
WOLFSSL_API int wolfSSL_get_fd(const WOLFSSL*);
/*!
\ingroup Setup
\brief This function informs the WOLFSSL object that the underlying
I/O is non-blocking. After an application creates a WOLFSSL object,
if it will be used with a non-blocking socket, call
wolfSSL_set_using_nonblock() on it. This lets the WOLFSSL object know
that receiving EWOULDBLOCK means that the recvfrom call would
block rather than that it timed out.
\return none No return.
\param ssl pointer to the SSL session, created with wolfSSL_new().
\param nonblock value used to set non-blocking flag on WOLFSSL object.
Use 1 to specify non-blocking, otherwise 0.
_Example_
\code
WOLFSSL* ssl = 0;
...
wolfSSL_set_using_nonblock(ssl, 1);
\endcode
\sa wolfSSL_get_using_nonblock
\sa wolfSSL_dtls_got_timeout
\sa wolfSSL_dtls_get_current_timeout
*/
WOLFSSL_API void wolfSSL_set_using_nonblock(WOLFSSL*, int);
/*!
\ingroup IO
\brief This function allows the application to determine if wolfSSL is
using non-blocking I/O. If wolfSSL is using non-blocking I/O, this
function will return 1, otherwise 0. After an application creates a
WOLFSSL object, if it will be used with a non-blocking socket, call
wolfSSL_set_using_nonblock() on it. This lets the WOLFSSL object know
that receiving EWOULDBLOCK means that the recvfrom call would block
rather than that it timed out.
\return 0 underlying I/O is blocking.
\return 1 underlying I/O is non-blocking.
\param ssl pointer to the SSL session, created with wolfSSL_new().
_Example_
\code
int ret = 0;
WOLFSSL* ssl = 0;
...
ret = wolfSSL_get_using_nonblock(ssl);
if (ret == 1) {
// underlying I/O is non-blocking
}
...
\endcode
\sa wolfSSL_set_session
*/
WOLFSSL_API int wolfSSL_get_using_nonblock(WOLFSSL*);
/*!
\ingroup IO
@ -2996,6 +2937,64 @@ WOLFSSL_API int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX*, const char*);
\sa wolfSSL_new
*/
WOLFSSL_API int wolfSSL_set_cipher_list(WOLFSSL*, const char*);
/*!
\brief This function informs the WOLFSSL DTLS object that the underlying
UDP I/O is non-blocking. After an application creates a WOLFSSL object,
if it will be used with a non-blocking UDP socket, call
wolfSSL_dtls_set_using_nonblock() on it. This lets the WOLFSSL object know
that receiving EWOULDBLOCK means that the recvfrom call would
block rather than that it timed out.
\return none No return.
\param ssl pointer to the DTLS session, created with wolfSSL_new().
\param nonblock value used to set non-blocking flag on WOLFSSL object.
Use 1 to specify non-blocking, otherwise 0.
_Example_
\code
WOLFSSL* ssl = 0;
...
wolfSSL_dtls_set_using_nonblock(ssl, 1);
\endcode
\sa wolfSSL_dtls_get_using_nonblock
\sa wolfSSL_dtls_got_timeout
\sa wolfSSL_dtls_get_current_timeout
*/
WOLFSSL_API void wolfSSL_dtls_set_using_nonblock(WOLFSSL*, int);
/*!
\brief This function allows the application to determine if wolfSSL is
using non-blocking I/O with UDP. If wolfSSL is using non-blocking I/O, this
function will return 1, otherwise 0. After an application creates a
WOLFSSL object, if it will be used with a non-blocking UDP socket, call
wolfSSL_dtls_set_using_nonblock() on it. This lets the WOLFSSL object know
that receiving EWOULDBLOCK means that the recvfrom call would block
rather than that it timed out. This function is only meaningful to DTLS
sessions.
\return 0 underlying I/O is blocking.
\return 1 underlying I/O is non-blocking.
\param ssl pointer to the DTLS session, created with wolfSSL_new().
_Example_
\code
int ret = 0;
WOLFSSL* ssl = 0;
...
ret = wolfSSL_dtls_get_using_nonblock(ssl);
if (ret == 1) {
// underlying I/O is non-blocking
}
...
\endcode
\sa wolfSSL_dtls_set_using_nonblock
\sa wolfSSL_dtls_got_timeout
\sa wolfSSL_dtls_set_using_nonblock
*/
WOLFSSL_API int wolfSSL_dtls_get_using_nonblock(WOLFSSL*);
/*!
\brief This function returns the current timeout value in seconds for
the WOLFSSL object. When using non-blocking sockets, something in the user

View File

@ -6311,8 +6311,8 @@ retry:
ssl->options.isClosed = 1;
return -1;
#ifdef WOLFSSL_DTLS
case WOLFSSL_CBIO_ERR_TIMEOUT:
#ifdef WOLFSSL_DTLS
if (IsDtlsNotSctpMode(ssl) &&
!ssl->options.handShakeDone &&
DtlsMsgPoolTimeout(ssl) == 0 &&
@ -6320,8 +6320,8 @@ retry:
goto retry;
}
#endif
return -1;
#endif
default:
return recvd;

View File

@ -737,14 +737,6 @@ int wolfSSL_get_fd(const WOLFSSL* ssl)
}
int wolfSSL_get_using_nonblock(WOLFSSL* ssl)
{
WOLFSSL_ENTER("wolfSSL_get_using_nonblock");
WOLFSSL_LEAVE("wolfSSL_get_using_nonblock", ssl->options.usingNonblock);
return ssl->options.usingNonblock;
}
int wolfSSL_dtls(WOLFSSL* ssl)
{
return ssl->options.dtls;
@ -752,13 +744,6 @@ int wolfSSL_dtls(WOLFSSL* ssl)
#ifndef WOLFSSL_LEANPSK
void wolfSSL_set_using_nonblock(WOLFSSL* ssl, int nonblock)
{
WOLFSSL_ENTER("wolfSSL_set_using_nonblock");
ssl->options.usingNonblock = (nonblock != 0);
}
int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
{
#ifdef WOLFSSL_DTLS
@ -8273,13 +8258,47 @@ int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list)
}
int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl)
{
int useNb = 0;
WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock");
if (ssl->options.dtls) {
#ifdef WOLFSSL_DTLS
useNb = ssl->options.dtlsUseNonblock;
#endif
}
else {
WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is "
"DEPRECATED for non-DTLS use.");
}
return useNb;
}
#ifndef WOLFSSL_LEANPSK
void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock)
{
(void)nonblock;
WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock");
if (ssl->options.dtls) {
#ifdef WOLFSSL_DTLS
ssl->options.dtlsUseNonblock = (nonblock != 0);
#endif
}
else {
WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is "
"DEPRECATED for non-DTLS use.");
}
}
#ifdef WOLFSSL_DTLS
int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl)
{
(void)ssl;
return ssl->dtls_timeout;
}

View File

@ -200,14 +200,8 @@ int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
WOLFSSL_MSG("Embed Receive error");
if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
if (wolfSSL_get_using_nonblock(ssl)) {
WOLFSSL_MSG("\tWould block");
return WOLFSSL_CBIO_ERR_WANT_READ;
}
else {
WOLFSSL_MSG("\tSocket timeout");
return WOLFSSL_CBIO_ERR_TIMEOUT;
}
WOLFSSL_MSG("\tWould block");
return WOLFSSL_CBIO_ERR_WANT_READ;
}
else if (err == SOCKET_ECONNRESET) {
WOLFSSL_MSG("\tConnection reset");
@ -217,10 +211,6 @@ int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
WOLFSSL_MSG("\tSocket interrupted");
return WOLFSSL_CBIO_ERR_ISR;
}
else if (err == SOCKET_ECONNREFUSED) {
WOLFSSL_MSG("\tConnection refused");
return WOLFSSL_CBIO_ERR_WANT_READ;
}
else if (err == SOCKET_ECONNABORTED) {
WOLFSSL_MSG("\tConnection aborted");
return WOLFSSL_CBIO_ERR_CONN_CLOSE;
@ -327,7 +317,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
WOLFSSL_MSG("Embed Receive From error");
if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
if (wolfSSL_get_using_nonblock(ssl)) {
if (wolfSSL_dtls_get_using_nonblock(ssl)) {
WOLFSSL_MSG("\tWould block");
return WOLFSSL_CBIO_ERR_WANT_READ;
}
@ -438,7 +428,7 @@ int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx)
WOLFSSL_MSG("Embed Receive From error");
if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) {
if (wolfSSL_get_using_nonblock(ssl)) {
if (wolfSSL_dtls_get_using_nonblock(ssl)) {
WOLFSSL_MSG("\tWould block");
return WOLFSSL_CBIO_ERR_WANT_READ;
}
@ -1694,7 +1684,7 @@ int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
{
int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
if (wolfSSL_dtls(ssl)
&& !wolfSSL_get_using_nonblock(ssl)
&& !wolfSSL_dtls_get_using_nonblock(ssl)
&& dtls_timeout != 0) {
/* needs timeout in milliseconds */
NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
@ -1711,7 +1701,7 @@ int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx)
if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
err == NET_ERR_FAULT_LOCK_ACQUIRE) {
if (!wolfSSL_dtls(ssl) || wolfSSL_get_using_nonblock(ssl)) {
if (!wolfSSL_dtls(ssl) || wolfSSL_dtls_get_using_nonblock(ssl)) {
WOLFSSL_MSG("\tWould block");
return WOLFSSL_CBIO_ERR_WANT_READ;
}
@ -1751,7 +1741,7 @@ int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
if (ssl->options.handShakeDone)
dtls_timeout = 0;
if (!wolfSSL_get_using_nonblock(ssl)) {
if (!wolfSSL_dtls_get_using_nonblock(ssl)) {
/* needs timeout in milliseconds */
NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err);
if (err != NET_SOCK_ERR_NONE) {
@ -1766,7 +1756,7 @@ int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY ||
err == NET_ERR_FAULT_LOCK_ACQUIRE) {
if (wolfSSL_get_using_nonblock(ssl)) {
if (wolfSSL_dtls_get_using_nonblock(ssl)) {
WOLFSSL_MSG("\tWould block");
return WOLFSSL_CBIO_ERR_WANT_READ;
}

View File

@ -3010,7 +3010,6 @@ typedef struct Options {
word16 quietShutdown:1; /* don't send close notify */
word16 certOnly:1; /* stop once we get cert */
word16 groupMessages:1; /* group handshake messages */
word16 usingNonblock:1; /* are we using nonblocking socket */
word16 saveArrays:1; /* save array Memory for user get keys
or psk */
word16 weOwnRng:1; /* will be true unless CTX owns */
@ -3030,6 +3029,7 @@ typedef struct Options {
#endif
#endif
#ifdef WOLFSSL_DTLS
word16 dtlsUseNonblock:1; /* are we using nonblocking socket */
word16 dtlsHsRetain:1; /* DTLS retaining HS data */
word16 haveMcast:1; /* using multicast ? */
#ifdef WOLFSSL_SCTP

View File

@ -540,8 +540,6 @@ WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf,
int len);
WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_get_fd(const WOLFSSL*);
WOLFSSL_API void wolfSSL_set_using_nonblock(WOLFSSL*, int);
WOLFSSL_API int wolfSSL_get_using_nonblock(WOLFSSL*);
/* please see note at top of README if you get an error from connect */
WOLFSSL_API int wolfSSL_connect(WOLFSSL*);
WOLFSSL_API int wolfSSL_write(WOLFSSL*, const void*, int);
@ -660,6 +658,11 @@ WOLFSSL_API int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX*, const char*);
WOLFSSL_API int wolfSSL_set_cipher_list(WOLFSSL*, const char*);
/* Nonblocking DTLS helper functions */
WOLFSSL_API void wolfSSL_dtls_set_using_nonblock(WOLFSSL*, int);
WOLFSSL_API int wolfSSL_dtls_get_using_nonblock(WOLFSSL*);
#define wolfSSL_set_using_nonblock wolfSSL_dtls_set_using_nonblock
#define wolfSSL_get_using_nonblock wolfSSL_dtls_get_using_nonblock
/* The old names are deprecated. */
WOLFSSL_API int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int);
WOLFSSL_API int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int);