PR: 2033
[openssl.git] / ssl / d1_lib.c
index 6450c1de850b2d3e63b7b1dac2e902c43b9f7153..2786b61c29618a08b1bbf232e54250b74e50bf8d 100644 (file)
@@ -68,6 +68,7 @@
 
 static void get_current_time(struct timeval *t);
 const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT;
+int dtls1_listen(SSL *s, struct sockaddr *client);
 
 SSL3_ENC_METHOD DTLSv1_enc_data={
     dtls1_enc,
@@ -188,6 +189,32 @@ void dtls1_clear(SSL *s)
                s->version=DTLS1_VERSION;
        }
 
+long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
+       {
+       int ret=0;
+
+       switch (cmd)
+               {
+       case DTLS_CTRL_GET_TIMEOUT:
+               if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL)
+                       {
+                       ret = 1;
+                       }
+               break;
+       case DTLS_CTRL_HANDLE_TIMEOUT:
+               ret = dtls1_handle_timeout(s);
+               break;
+       case DTLS_CTRL_LISTEN:
+               ret = dtls1_listen(s, parg);
+               break;
+
+       default:
+               ret = ssl3_ctrl(s, cmd, larg, parg);
+               break;
+               }
+       return(ret);
+       }
+
 /*
  * As it's impossible to use stream ciphers in "datagram" mode, this
  * simple filter is designed to disengage them in DTLS. Unfortunately
@@ -295,6 +322,36 @@ void dtls1_stop_timer(SSL *s)
        BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
        }
 
+int dtls1_handle_timeout(SSL *s)
+       {
+       DTLS1_STATE *state;
+
+       /* if no timer is expired, don't do anything */
+       if (!dtls1_is_timer_expired(s))
+               {
+               return 0;
+               }
+
+       dtls1_double_timeout(s);
+       state = s->d1;
+       state->timeout.num_alerts++;
+       if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
+               {
+               /* fail the connection, enough alerts have been sent */
+               SSLerr(SSL_F_DTLS1_HANDLE_TIMEOUT,SSL_R_READ_TIMEOUT_EXPIRED);
+               return 0;
+               }
+
+       state->timeout.read_timeouts++;
+       if ( state->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
+               {
+               state->timeout.read_timeouts = 1;
+               }
+
+       dtls1_start_timer(s);
+       return dtls1_retransmit_buffered_messages(s);
+       }
+
 static void get_current_time(struct timeval *t)
 {
 #ifdef OPENSSL_SYS_WIN32
@@ -311,3 +368,17 @@ static void get_current_time(struct timeval *t)
        gettimeofday(t, NULL);
 #endif
 }
+
+int dtls1_listen(SSL *s, struct sockaddr *client)
+       {
+       int ret;
+
+       SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
+       s->d1->listen = 1;
+
+       ret = SSL_accept(s);
+       if (ret <= 0) return ret;
+       
+       (void) BIO_dgram_get_peer(SSL_get_rbio(s), client);
+       return 1;
+       }