forked from wolfSSL/wolfssl
wolfio: dtls: retry instead of returning WANT_READ on different peer
If EmbedReceiveFrom() returns WANT_READ, a blocking socket will not know how to deal with the error. Retry the recvfrom instead adjusting the timeout.
This commit is contained in:
188
src/wolfio.c
188
src/wolfio.c
@@ -51,6 +51,14 @@ Possible IO enable options:
|
|||||||
* HAVE_HTTP_CLIENT: Enables HTTP client API's default: off
|
* HAVE_HTTP_CLIENT: Enables HTTP client API's default: off
|
||||||
(unless HAVE_OCSP or HAVE_CRL_IO defined)
|
(unless HAVE_OCSP or HAVE_CRL_IO defined)
|
||||||
* HAVE_IO_TIMEOUT: Enables support for connect timeout default: off
|
* HAVE_IO_TIMEOUT: Enables support for connect timeout default: off
|
||||||
|
*
|
||||||
|
* DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER: This flag has effect only if
|
||||||
|
* ASN_NO_TIME is enabled. If enabled invalid peers messages are ignored
|
||||||
|
* indefinetely. If not enabled EmbedReceiveFrom will return timeout after
|
||||||
|
* DTLS_RECEIVEFROM_MAX_INVALID_PEER number of packets from invalid peers. When
|
||||||
|
* enabled, without a timer, EmbedReceivefrom can't check if the timeout is
|
||||||
|
* expired and it may never return under a continous flow of invalid packets.
|
||||||
|
* default: off
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -59,6 +67,11 @@ Possible IO enable options:
|
|||||||
but they'll still need SetCallback xxx() at end of file
|
but they'll still need SetCallback xxx() at end of file
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(NO_ASN_TIME) && !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER) \
|
||||||
|
&& !defined(DTLS_RECEIVEFROM_MAX_INVALID_PEER)
|
||||||
|
#define DTLS_RECEIVEFROM_MAX_INVALID_PEER 10
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
|
#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT)
|
||||||
|
|
||||||
/* Translates return codes returned from
|
/* Translates return codes returned from
|
||||||
@@ -400,6 +413,11 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
|
|||||||
SOCKADDR_S lclPeer;
|
SOCKADDR_S lclPeer;
|
||||||
SOCKADDR_S* peer;
|
SOCKADDR_S* peer;
|
||||||
XSOCKLENT peerSz = 0;
|
XSOCKLENT peerSz = 0;
|
||||||
|
#ifndef NO_ASN_TIME
|
||||||
|
word32 start = 0;
|
||||||
|
#elif !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
|
||||||
|
word32 invalidPeerPackets = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
WOLFSSL_ENTER("EmbedReceiveFrom");
|
WOLFSSL_ENTER("EmbedReceiveFrom");
|
||||||
|
|
||||||
@@ -438,10 +456,26 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
|
|||||||
}
|
}
|
||||||
#endif /* WOLFSSL_DTLS13 */
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
|
||||||
if (!doDtlsTimeout)
|
do {
|
||||||
dtls_timeout = 0;
|
|
||||||
|
|
||||||
if (!wolfSSL_get_using_nonblock(ssl)) {
|
if (!doDtlsTimeout) {
|
||||||
|
dtls_timeout = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#ifndef NO_ASN_TIME
|
||||||
|
if (start == 0) {
|
||||||
|
start = LowResTimer();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dtls_timeout -= LowResTimer() - start;
|
||||||
|
start = LowResTimer();
|
||||||
|
if (dtls_timeout < 0 || dtls_timeout > DTLS_TIMEOUT_MAX)
|
||||||
|
return WOLFSSL_CBIO_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wolfSSL_get_using_nonblock(ssl)) {
|
||||||
#ifdef USE_WINDOWS_API
|
#ifdef USE_WINDOWS_API
|
||||||
DWORD timeout = dtls_timeout * 1000;
|
DWORD timeout = dtls_timeout * 1000;
|
||||||
#ifdef WOLFSSL_DTLS13
|
#ifdef WOLFSSL_DTLS13
|
||||||
@@ -464,87 +498,101 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
|
|||||||
#endif /* WOLFSSL_DTLS13 */
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
timeout.tv_sec = dtls_timeout;
|
timeout.tv_sec = dtls_timeout;
|
||||||
#endif
|
#endif
|
||||||
if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
|
if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
|
||||||
sizeof(timeout)) != 0) {
|
sizeof(timeout)) != 0) {
|
||||||
WOLFSSL_MSG("setsockopt rcvtimeo failed");
|
WOLFSSL_MSG("setsockopt rcvtimeo failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#ifndef NO_ASN_TIME
|
#ifndef NO_ASN_TIME
|
||||||
else if(IsSCR(ssl)) {
|
else if (IsSCR(ssl)) {
|
||||||
if (ssl->dtls_start_timeout &&
|
if (ssl->dtls_start_timeout &&
|
||||||
LowResTimer() - ssl->dtls_start_timeout > (word32)dtls_timeout) {
|
LowResTimer() - ssl->dtls_start_timeout >
|
||||||
ssl->dtls_start_timeout = 0;
|
(word32)dtls_timeout) {
|
||||||
return WOLFSSL_CBIO_ERR_TIMEOUT;
|
ssl->dtls_start_timeout = 0;
|
||||||
|
return WOLFSSL_CBIO_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
else if (!ssl->dtls_start_timeout) {
|
||||||
|
ssl->dtls_start_timeout = LowResTimer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (!ssl->dtls_start_timeout) {
|
|
||||||
ssl->dtls_start_timeout = LowResTimer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* !NO_ASN_TIME */
|
#endif /* !NO_ASN_TIME */
|
||||||
|
|
||||||
recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
|
recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
|
||||||
(SOCKADDR*)peer, peer != NULL ? &peerSz : NULL);
|
(SOCKADDR*)peer, peer != NULL ? &peerSz : NULL);
|
||||||
|
|
||||||
/* From the RECV(2) man page
|
/* From the RECV(2) man page
|
||||||
* The returned address is truncated if the buffer provided is too small; in
|
* The returned address is truncated if the buffer provided is too
|
||||||
* this case, addrlen will return a value greater than was supplied to the
|
* small; in this case, addrlen will return a value greater than was
|
||||||
* call.
|
* supplied to the call.
|
||||||
*/
|
*/
|
||||||
if (dtlsCtx->connected) {
|
if (dtlsCtx->connected) {
|
||||||
/* No need to sanitize the value of peerSz */
|
/* No need to sanitize the value of peerSz */
|
||||||
}
|
|
||||||
else if (dtlsCtx->userSet) {
|
|
||||||
/* Truncate peer size */
|
|
||||||
if (peerSz > (XSOCKLENT)sizeof(lclPeer))
|
|
||||||
peerSz = (XSOCKLENT)sizeof(lclPeer);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Truncate peer size */
|
|
||||||
if (peerSz > (XSOCKLENT)dtlsCtx->peer.bufSz)
|
|
||||||
peerSz = (XSOCKLENT)dtlsCtx->peer.bufSz;
|
|
||||||
}
|
|
||||||
|
|
||||||
recvd = TranslateReturnCode(recvd, sd);
|
|
||||||
|
|
||||||
if (recvd < 0) {
|
|
||||||
WOLFSSL_MSG("Embed Receive From error");
|
|
||||||
recvd = TranslateIoError(recvd);
|
|
||||||
if (recvd == WOLFSSL_CBIO_ERR_WANT_READ &&
|
|
||||||
!wolfSSL_dtls_get_using_nonblock(ssl)) {
|
|
||||||
recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
|
|
||||||
}
|
}
|
||||||
return recvd;
|
else if (dtlsCtx->userSet) {
|
||||||
}
|
/* Truncate peer size */
|
||||||
else if (recvd == 0) {
|
if (peerSz > (XSOCKLENT)sizeof(lclPeer))
|
||||||
if (!isDGramSock(sd)) {
|
peerSz = (XSOCKLENT)sizeof(lclPeer);
|
||||||
/* Closed TCP connection */
|
|
||||||
recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
WOLFSSL_MSG("Ignoring 0-length datagram");
|
/* Truncate peer size */
|
||||||
|
if (peerSz > (XSOCKLENT)dtlsCtx->peer.bufSz)
|
||||||
|
peerSz = (XSOCKLENT)dtlsCtx->peer.bufSz;
|
||||||
}
|
}
|
||||||
return recvd;
|
|
||||||
}
|
recvd = TranslateReturnCode(recvd, sd);
|
||||||
else if (dtlsCtx->connected) {
|
|
||||||
/* Nothing to do */
|
if (recvd < 0) {
|
||||||
}
|
WOLFSSL_MSG("Embed Receive From error");
|
||||||
else if (dtlsCtx->userSet) {
|
recvd = TranslateIoError(recvd);
|
||||||
/* Check we received the packet from the correct peer */
|
if (recvd == WOLFSSL_CBIO_ERR_WANT_READ &&
|
||||||
if (dtlsCtx->peer.sz > 0 &&
|
!wolfSSL_dtls_get_using_nonblock(ssl)) {
|
||||||
(peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
|
recvd = WOLFSSL_CBIO_ERR_TIMEOUT;
|
||||||
!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
|
}
|
||||||
dtlsCtx->peer.sz))) {
|
return recvd;
|
||||||
WOLFSSL_MSG(" Ignored packet from invalid peer");
|
}
|
||||||
return WOLFSSL_CBIO_ERR_WANT_READ;
|
else if (recvd == 0) {
|
||||||
|
if (!isDGramSock(sd)) {
|
||||||
|
/* Closed TCP connection */
|
||||||
|
recvd = WOLFSSL_CBIO_ERR_CONN_CLOSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WOLFSSL_MSG("Ignoring 0-length datagram");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return recvd;
|
||||||
|
}
|
||||||
|
else if (dtlsCtx->connected) {
|
||||||
|
/* Nothing to do */
|
||||||
|
}
|
||||||
|
else if (dtlsCtx->userSet) {
|
||||||
|
/* Check we received the packet from the correct peer */
|
||||||
|
if (dtlsCtx->peer.sz > 0 &&
|
||||||
|
(peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
|
||||||
|
!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
|
||||||
|
dtlsCtx->peer.sz))) {
|
||||||
|
WOLFSSL_MSG(" Ignored packet from invalid peer");
|
||||||
|
#if defined(NO_ASN_TIME) && \
|
||||||
|
!defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
|
||||||
|
if (doDtlsTimeout) {
|
||||||
|
invalidPeerPackets++;
|
||||||
|
if (invalidPeerPackets > DTLS_RECEIVEFROM_MAX_INVALID_PEER)
|
||||||
|
return wolfSSL_dtls_get_using_nonblock(ssl)
|
||||||
|
? WOLFSSL_CBIO_ERR_WANT_READ
|
||||||
|
: WOLFSSL_CBIO_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
#endif /* NO_ASN_TIME && !DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Store size of saved address */
|
||||||
|
dtlsCtx->peer.sz = peerSz;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Store size of saved address */
|
|
||||||
dtlsCtx->peer.sz = peerSz;
|
|
||||||
}
|
|
||||||
#ifndef NO_ASN_TIME
|
#ifndef NO_ASN_TIME
|
||||||
ssl->dtls_start_timeout = 0;
|
ssl->dtls_start_timeout = 0;
|
||||||
#endif /* !NO_ASN_TIME */
|
#endif /* !NO_ASN_TIME */
|
||||||
|
break;
|
||||||
|
} while (1);
|
||||||
|
|
||||||
return recvd;
|
return recvd;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user