Implement timeout back-off (fixed range for now)
This commit is contained in:
parent
ce8588c9ef
commit
0ac247fd88
2 changed files with 67 additions and 17 deletions
|
@ -261,6 +261,13 @@
|
|||
#define SSL_RETRANS_WAITING 2
|
||||
#define SSL_RETRANS_FINISHED 3
|
||||
|
||||
/*
|
||||
* Default range for DTLS retransmission timer value, in milliseconds.
|
||||
* RFC 6347 4.2.4.1 says from 1 second to 60 seconds.
|
||||
*/
|
||||
#define SSL_DTLS_TIMEOUT_DFL_MIN 1000
|
||||
#define SSL_DTLS_TIMEOUT_DFL_MAX 60000
|
||||
|
||||
/**
|
||||
* \name SECTION: Module settings
|
||||
*
|
||||
|
@ -652,6 +659,7 @@ struct _ssl_handshake_params
|
|||
|
||||
unsigned char *hs_msg; /*!< Reassembled handshake message */
|
||||
|
||||
uint32_t retransmit_timeout; /*!< Current value of timeout */
|
||||
unsigned char retransmit_state; /*!< Retransmission state */
|
||||
ssl_flight_item *flight; /*!< Current outgoing flight */
|
||||
ssl_flight_item *cur_msg; /*!< Current message in flight */
|
||||
|
|
|
@ -88,7 +88,7 @@ static inline size_t ssl_ep_len( const ssl_context *ssl )
|
|||
* Passing millisecs = 0 cancels a running timer.
|
||||
* The timer is already running iff time_limit != 0.
|
||||
*/
|
||||
void ssl_set_timer( ssl_context *ssl, unsigned long millisecs )
|
||||
void ssl_set_timer( ssl_context *ssl, uint32_t millisecs )
|
||||
{
|
||||
ssl->time_limit = millisecs;
|
||||
get_timer( &ssl->time_info, 1 );
|
||||
|
@ -109,6 +109,40 @@ int ssl_check_timer( ssl_context *ssl )
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Double the retransmit timeout value, within the allowed range,
|
||||
* returning -1 if the maximum value has already been reached.
|
||||
*/
|
||||
static int ssl_double_retransmit_timeout( ssl_context *ssl )
|
||||
{
|
||||
uint32_t new_timeout;
|
||||
|
||||
if( ssl->handshake->retransmit_timeout >= SSL_DTLS_TIMEOUT_DFL_MAX )
|
||||
return( -1 );
|
||||
|
||||
new_timeout = 2 * ssl->handshake->retransmit_timeout;
|
||||
|
||||
/* Avoid arithmetic overflow and range overflow */
|
||||
if( new_timeout < ssl->handshake->retransmit_timeout ||
|
||||
new_timeout > SSL_DTLS_TIMEOUT_DFL_MAX )
|
||||
{
|
||||
new_timeout = SSL_DTLS_TIMEOUT_DFL_MAX;
|
||||
}
|
||||
|
||||
ssl->handshake->retransmit_timeout = new_timeout;
|
||||
SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
|
||||
ssl->handshake->retransmit_timeout ) );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void ssl_reset_retransmit_timeout( ssl_context *ssl )
|
||||
{
|
||||
ssl->handshake->retransmit_timeout = SSL_DTLS_TIMEOUT_DFL_MIN;
|
||||
SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs",
|
||||
ssl->handshake->retransmit_timeout ) );
|
||||
}
|
||||
|
||||
#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
|
||||
/*
|
||||
* Convert max_fragment_length codes to length.
|
||||
|
@ -1951,12 +1985,12 @@ int ssl_fetch_input( ssl_context *ssl, size_t nb_want )
|
|||
return( POLARSSL_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
|
||||
// TODO-DTLS: for now, use constant timeout = 1 sec/datagram
|
||||
len = SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
|
||||
if( ssl->f_recv_timeout != NULL &&
|
||||
ssl->handshake != NULL ) /* No resend outside handshake */
|
||||
ssl->handshake != NULL ) /* No timeout outside handshake */
|
||||
{
|
||||
ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, 1 );
|
||||
ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len,
|
||||
ssl->handshake->retransmit_timeout / 1000 );
|
||||
}
|
||||
else
|
||||
ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len );
|
||||
|
@ -1972,6 +2006,12 @@ int ssl_fetch_input( ssl_context *ssl, size_t nb_want )
|
|||
{
|
||||
SSL_DEBUG_MSG( 2, ( "recv timeout" ) );
|
||||
|
||||
if( ssl_double_retransmit_timeout( ssl ) != 0 )
|
||||
{
|
||||
SSL_DEBUG_MSG( 1, ( "handshake timeout" ) );
|
||||
return( POLARSSL_ERR_NET_TIMEOUT );
|
||||
}
|
||||
|
||||
if( ( ret = ssl_resend( ssl ) ) != 0 )
|
||||
{
|
||||
SSL_DEBUG_RET( 1, "ssl_resend", ret );
|
||||
|
@ -2247,8 +2287,7 @@ int ssl_resend( ssl_context *ssl )
|
|||
else
|
||||
ssl->handshake->retransmit_state = SSL_RETRANS_WAITING;
|
||||
|
||||
/* WIP: hardcoded 1 sec will be replaced */
|
||||
ssl_set_timer( ssl, 1000 );
|
||||
ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
|
||||
|
||||
SSL_DEBUG_MSG( 2, ( "<= ssl_resend" ) );
|
||||
|
||||
|
@ -2268,8 +2307,9 @@ void ssl_recv_flight_completed( ssl_context *ssl )
|
|||
/* The next incoming flight will start with this msg_seq */
|
||||
ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq;
|
||||
|
||||
/* Cancel timer */
|
||||
/* Cancel timer and reset timeout value */
|
||||
ssl_set_timer( ssl, 0 );
|
||||
ssl_reset_retransmit_timeout( ssl );
|
||||
|
||||
if( ssl->in_msgtype == SSL_MSG_HANDSHAKE &&
|
||||
ssl->in_msg[0] == SSL_HS_FINISHED )
|
||||
|
@ -2285,8 +2325,7 @@ void ssl_recv_flight_completed( ssl_context *ssl )
|
|||
*/
|
||||
void ssl_send_flight_completed( ssl_context *ssl )
|
||||
{
|
||||
/* WIP: hardcoded 1 sec is temporary */
|
||||
ssl_set_timer( ssl, 1000 );
|
||||
ssl_set_timer( ssl, ssl->handshake->retransmit_timeout );
|
||||
|
||||
if( ssl->in_msgtype == SSL_MSG_HANDSHAKE &&
|
||||
ssl->in_msg[0] == SSL_HS_FINISHED )
|
||||
|
@ -4489,16 +4528,19 @@ static int ssl_handshake_init( ssl_context *ssl )
|
|||
ssl->handshake->key_cert = ssl->key_cert;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We may not know yet if we're using DTLS,
|
||||
* so always initiliase DTLS-specific fields.
|
||||
*/
|
||||
#if defined(POLARSSL_SSL_PROTO_DTLS)
|
||||
if( ssl->transport == SSL_TRANSPORT_DATAGRAM )
|
||||
{
|
||||
ssl->handshake->alt_transform_out = ssl->transform_out;
|
||||
ssl->handshake->alt_transform_out = ssl->transform_out;
|
||||
|
||||
if( ssl->endpoint == SSL_IS_CLIENT )
|
||||
ssl->handshake->retransmit_state = SSL_RETRANS_PREPARING;
|
||||
else
|
||||
ssl->handshake->retransmit_state = SSL_RETRANS_WAITING;
|
||||
}
|
||||
ssl->handshake->retransmit_timeout = SSL_DTLS_TIMEOUT_DFL_MIN;
|
||||
|
||||
if( ssl->endpoint == SSL_IS_CLIENT )
|
||||
ssl->handshake->retransmit_state = SSL_RETRANS_PREPARING;
|
||||
else
|
||||
ssl->handshake->retransmit_state = SSL_RETRANS_WAITING;
|
||||
#endif
|
||||
|
||||
return( 0 );
|
||||
|
|
Loading…
Reference in a new issue