Commit fa4b82cc authored by Alfred E. Heggestad's avatar Alfred E. Heggestad Committed by Bernd Edlinger
Browse files

add callback handler for setting DTLS timer interval

parent 94b5d7aa
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
=pod

=head1 NAME

DTLS_timer_cb,
DTLS_set_timer_cb
- Set callback for controlling DTLS timer duration

=head1 SYNOPSIS

 #include <openssl/ssl.h>

 typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us);

 void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb);

=head1 DESCRIPTION

This function sets an optional callback function for controlling the
timeout interval on the DTLS protocol. The callback function will be
called by DTLS for every new DTLS packet that is sent.

=head1 RETURN VALUES

Returns void.

=head1 HISTORY

This function was added in OpenSSL 1.1.1

=head1 COPYRIGHT

Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the OpenSSL license (the "License").  You may not use
this file except in compliance with the License.  You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.

=cut
+6 −0
Original line number Diff line number Diff line
@@ -2260,6 +2260,12 @@ extern const char SSL_version_str[];

int ERR_load_SSL_strings(void);


typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us);

void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb);


# ifdef  __cplusplus
}
# endif
+41 −8
Original line number Diff line number Diff line
@@ -161,6 +161,8 @@ int dtls1_clear(SSL *s)
    DTLS_RECORD_LAYER_clear(&s->rlayer);

    if (s->d1) {
        DTLS_timer_cb timer_cb = s->d1->timer_cb;

        buffered_messages = s->d1->buffered_messages;
        sent_messages = s->d1->sent_messages;
        mtu = s->d1->mtu;
@@ -170,6 +172,9 @@ int dtls1_clear(SSL *s)

        memset(s->d1, 0, sizeof(*s->d1));

        /* Restore the timer callback from previous state */
        s->d1->timer_cb = timer_cb;

        if (s->server) {
            s->d1->cookie_len = sizeof(s->d1->cookie);
        }
@@ -236,6 +241,8 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)

void dtls1_start_timer(SSL *s)
{
    unsigned int sec, usec;

#ifndef OPENSSL_NO_SCTP
    /* Disable timer for SCTP */
    if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
@@ -244,16 +251,34 @@ void dtls1_start_timer(SSL *s)
    }
#endif

    /* If timer is not set, initialize duration with 1 second */
    /*
     * If timer is not set, initialize duration with 1 second or
     * a user-specified value if the timer callback is installed.
     */
    if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
        s->d1->timeout_duration = 1;

        if (s->d1->timer_cb != NULL)
            s->d1->timeout_duration_us = s->d1->timer_cb(s, 0);
        else
            s->d1->timeout_duration_us = 1000000;
    }

    /* Set timeout to current time */
    get_current_time(&(s->d1->next_timeout));

    /* Add duration to current time */
    s->d1->next_timeout.tv_sec += s->d1->timeout_duration;

    sec  = s->d1->timeout_duration_us / 1000000;
    usec = s->d1->timeout_duration_us - (sec * 1000000);

    s->d1->next_timeout.tv_sec  += sec;
    s->d1->next_timeout.tv_usec += usec;

    if (s->d1->next_timeout.tv_usec >= 1000000) {
        s->d1->next_timeout.tv_sec++;
        s->d1->next_timeout.tv_usec -= 1000000;
    }

    BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
             &(s->d1->next_timeout));
}
@@ -318,9 +343,9 @@ int dtls1_is_timer_expired(SSL *s)

void dtls1_double_timeout(SSL *s)
{
    s->d1->timeout_duration *= 2;
    if (s->d1->timeout_duration > 60)
        s->d1->timeout_duration = 60;
    s->d1->timeout_duration_us *= 2;
    if (s->d1->timeout_duration_us > 60000000)
        s->d1->timeout_duration_us = 60000000;
    dtls1_start_timer(s);
}

@@ -329,7 +354,7 @@ void dtls1_stop_timer(SSL *s)
    /* Reset everything */
    memset(&s->d1->timeout, 0, sizeof(s->d1->timeout));
    memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout));
    s->d1->timeout_duration = 1;
    s->d1->timeout_duration_us = 1000000;
    BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
             &(s->d1->next_timeout));
    /* Clear retransmission buffer */
@@ -367,6 +392,9 @@ int dtls1_handle_timeout(SSL *s)
        return 0;
    }

    if (s->d1->timer_cb != NULL)
        s->d1->timeout_duration_us = s->d1->timer_cb(s, s->d1->timeout_duration_us);
    else
        dtls1_double_timeout(s);

    if (dtls1_check_timeout_num(s) < 0)
@@ -952,3 +980,8 @@ size_t DTLS_get_data_mtu(const SSL *s)

    return mtu;
}

void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb)
{
    s->d1->timer_cb = cb;
}
+5 −1
Original line number Diff line number Diff line
@@ -1624,11 +1624,15 @@ typedef struct dtls1_state_st {
     */
    struct timeval next_timeout;
    /* Timeout duration */
    unsigned short timeout_duration;
    unsigned int timeout_duration_us;

    unsigned int retransmitting;
# ifndef OPENSSL_NO_SCTP
    int shutdown_received;
# endif

    DTLS_timer_cb timer_cb;

} DTLS1_STATE;

# ifndef OPENSSL_NO_EC
+20 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@

static char *cert = NULL;
static char *privkey = NULL;
static unsigned int timer_cb_count;

#define NUM_TESTS   2

@@ -40,6 +41,16 @@ static unsigned char certstatus[] = {

#define RECORD_SEQUENCE 10

static unsigned int timer_cb(SSL *s, unsigned int timer_us)
{
    ++timer_cb_count;

    if (timer_us == 0)
        return 1000000;
    else
        return 2 * timer_us;
}

static int test_dtls_unprocessed(int testidx)
{
    SSL_CTX *sctx = NULL, *cctx = NULL;
@@ -47,6 +58,8 @@ static int test_dtls_unprocessed(int testidx)
    BIO *c_to_s_fbio, *c_to_s_mempacket;
    int testresult = 0;

    timer_cb_count = 0;

    if (!TEST_true(create_ssl_ctx_pair(DTLS_server_method(),
                                       DTLS_client_method(), &sctx,
                                       &cctx, cert, privkey)))
@@ -64,6 +77,8 @@ static int test_dtls_unprocessed(int testidx)
                                      NULL, c_to_s_fbio)))
        goto end;

    DTLS_set_timer_cb(clientssl1, timer_cb);

    if (testidx == 1)
        certstatus[RECORD_SEQUENCE] = 0xff;

@@ -83,6 +98,11 @@ static int test_dtls_unprocessed(int testidx)
                                         SSL_ERROR_NONE)))
        goto end;

    if (timer_cb_count == 0) {
        printf("timer_callback was not called.\n");
        goto end;
    }

    testresult = 1;
 end:
    SSL_free(serverssl1);
Loading