Implement timeout back-off (fixed range for now)
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index f6626c9..308d877 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -88,7 +88,7 @@
  * 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 @@
 }
 #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 @@
             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 @@
         {
             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 @@
     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 @@
     /* 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_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 @@
     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 );