mirror of https://github.com/openssl/openssl.git
add callback handler for setting DTLS timer interval
Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de> (Merged from https://github.com/openssl/openssl/pull/4011)
This commit is contained in:
parent
94b5d7aae9
commit
fa4b82cc7c
|
@ -0,0 +1,40 @@
|
||||||
|
=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
|
|
@ -2260,6 +2260,12 @@ extern const char SSL_version_str[];
|
||||||
|
|
||||||
int ERR_load_SSL_strings(void);
|
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
|
# ifdef __cplusplus
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
49
ssl/d1_lib.c
49
ssl/d1_lib.c
|
@ -161,6 +161,8 @@ int dtls1_clear(SSL *s)
|
||||||
DTLS_RECORD_LAYER_clear(&s->rlayer);
|
DTLS_RECORD_LAYER_clear(&s->rlayer);
|
||||||
|
|
||||||
if (s->d1) {
|
if (s->d1) {
|
||||||
|
DTLS_timer_cb timer_cb = s->d1->timer_cb;
|
||||||
|
|
||||||
buffered_messages = s->d1->buffered_messages;
|
buffered_messages = s->d1->buffered_messages;
|
||||||
sent_messages = s->d1->sent_messages;
|
sent_messages = s->d1->sent_messages;
|
||||||
mtu = s->d1->mtu;
|
mtu = s->d1->mtu;
|
||||||
|
@ -170,6 +172,9 @@ int dtls1_clear(SSL *s)
|
||||||
|
|
||||||
memset(s->d1, 0, sizeof(*s->d1));
|
memset(s->d1, 0, sizeof(*s->d1));
|
||||||
|
|
||||||
|
/* Restore the timer callback from previous state */
|
||||||
|
s->d1->timer_cb = timer_cb;
|
||||||
|
|
||||||
if (s->server) {
|
if (s->server) {
|
||||||
s->d1->cookie_len = sizeof(s->d1->cookie);
|
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)
|
void dtls1_start_timer(SSL *s)
|
||||||
{
|
{
|
||||||
|
unsigned int sec, usec;
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_SCTP
|
#ifndef OPENSSL_NO_SCTP
|
||||||
/* Disable timer for SCTP */
|
/* Disable timer for SCTP */
|
||||||
if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
|
if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
|
||||||
|
@ -244,16 +251,34 @@ void dtls1_start_timer(SSL *s)
|
||||||
}
|
}
|
||||||
#endif
|
#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) {
|
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 */
|
/* Set timeout to current time */
|
||||||
get_current_time(&(s->d1->next_timeout));
|
get_current_time(&(s->d1->next_timeout));
|
||||||
|
|
||||||
/* Add duration to current time */
|
/* 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,
|
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
|
||||||
&(s->d1->next_timeout));
|
&(s->d1->next_timeout));
|
||||||
}
|
}
|
||||||
|
@ -318,9 +343,9 @@ int dtls1_is_timer_expired(SSL *s)
|
||||||
|
|
||||||
void dtls1_double_timeout(SSL *s)
|
void dtls1_double_timeout(SSL *s)
|
||||||
{
|
{
|
||||||
s->d1->timeout_duration *= 2;
|
s->d1->timeout_duration_us *= 2;
|
||||||
if (s->d1->timeout_duration > 60)
|
if (s->d1->timeout_duration_us > 60000000)
|
||||||
s->d1->timeout_duration = 60;
|
s->d1->timeout_duration_us = 60000000;
|
||||||
dtls1_start_timer(s);
|
dtls1_start_timer(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,7 +354,7 @@ void dtls1_stop_timer(SSL *s)
|
||||||
/* Reset everything */
|
/* Reset everything */
|
||||||
memset(&s->d1->timeout, 0, sizeof(s->d1->timeout));
|
memset(&s->d1->timeout, 0, sizeof(s->d1->timeout));
|
||||||
memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_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,
|
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
|
||||||
&(s->d1->next_timeout));
|
&(s->d1->next_timeout));
|
||||||
/* Clear retransmission buffer */
|
/* Clear retransmission buffer */
|
||||||
|
@ -367,7 +392,10 @@ int dtls1_handle_timeout(SSL *s)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dtls1_double_timeout(s);
|
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)
|
if (dtls1_check_timeout_num(s) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -952,3 +980,8 @@ size_t DTLS_get_data_mtu(const SSL *s)
|
||||||
|
|
||||||
return mtu;
|
return mtu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb)
|
||||||
|
{
|
||||||
|
s->d1->timer_cb = cb;
|
||||||
|
}
|
||||||
|
|
|
@ -1624,11 +1624,15 @@ typedef struct dtls1_state_st {
|
||||||
*/
|
*/
|
||||||
struct timeval next_timeout;
|
struct timeval next_timeout;
|
||||||
/* Timeout duration */
|
/* Timeout duration */
|
||||||
unsigned short timeout_duration;
|
unsigned int timeout_duration_us;
|
||||||
|
|
||||||
unsigned int retransmitting;
|
unsigned int retransmitting;
|
||||||
# ifndef OPENSSL_NO_SCTP
|
# ifndef OPENSSL_NO_SCTP
|
||||||
int shutdown_received;
|
int shutdown_received;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
DTLS_timer_cb timer_cb;
|
||||||
|
|
||||||
} DTLS1_STATE;
|
} DTLS1_STATE;
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_EC
|
# ifndef OPENSSL_NO_EC
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
static char *cert = NULL;
|
static char *cert = NULL;
|
||||||
static char *privkey = NULL;
|
static char *privkey = NULL;
|
||||||
|
static unsigned int timer_cb_count;
|
||||||
|
|
||||||
#define NUM_TESTS 2
|
#define NUM_TESTS 2
|
||||||
|
|
||||||
|
@ -40,6 +41,16 @@ static unsigned char certstatus[] = {
|
||||||
|
|
||||||
#define RECORD_SEQUENCE 10
|
#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)
|
static int test_dtls_unprocessed(int testidx)
|
||||||
{
|
{
|
||||||
SSL_CTX *sctx = NULL, *cctx = NULL;
|
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;
|
BIO *c_to_s_fbio, *c_to_s_mempacket;
|
||||||
int testresult = 0;
|
int testresult = 0;
|
||||||
|
|
||||||
|
timer_cb_count = 0;
|
||||||
|
|
||||||
if (!TEST_true(create_ssl_ctx_pair(DTLS_server_method(),
|
if (!TEST_true(create_ssl_ctx_pair(DTLS_server_method(),
|
||||||
DTLS_client_method(), &sctx,
|
DTLS_client_method(), &sctx,
|
||||||
&cctx, cert, privkey)))
|
&cctx, cert, privkey)))
|
||||||
|
@ -64,6 +77,8 @@ static int test_dtls_unprocessed(int testidx)
|
||||||
NULL, c_to_s_fbio)))
|
NULL, c_to_s_fbio)))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
DTLS_set_timer_cb(clientssl1, timer_cb);
|
||||||
|
|
||||||
if (testidx == 1)
|
if (testidx == 1)
|
||||||
certstatus[RECORD_SEQUENCE] = 0xff;
|
certstatus[RECORD_SEQUENCE] = 0xff;
|
||||||
|
|
||||||
|
@ -83,6 +98,11 @@ static int test_dtls_unprocessed(int testidx)
|
||||||
SSL_ERROR_NONE)))
|
SSL_ERROR_NONE)))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
if (timer_cb_count == 0) {
|
||||||
|
printf("timer_callback was not called.\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
testresult = 1;
|
testresult = 1;
|
||||||
end:
|
end:
|
||||||
SSL_free(serverssl1);
|
SSL_free(serverssl1);
|
||||||
|
|
|
@ -469,3 +469,4 @@ SSL_SESSION_set_max_early_data 469 1_1_1 EXIST::FUNCTION:
|
||||||
SSL_SESSION_set1_alpn_selected 470 1_1_1 EXIST::FUNCTION:
|
SSL_SESSION_set1_alpn_selected 470 1_1_1 EXIST::FUNCTION:
|
||||||
SSL_SESSION_set1_hostname 471 1_1_1 EXIST::FUNCTION:
|
SSL_SESSION_set1_hostname 471 1_1_1 EXIST::FUNCTION:
|
||||||
SSL_SESSION_get0_alpn_selected 472 1_1_1 EXIST::FUNCTION:
|
SSL_SESSION_get0_alpn_selected 472 1_1_1 EXIST::FUNCTION:
|
||||||
|
DTLS_set_timer_cb 473 1_1_1 EXIST::FUNCTION:
|
||||||
|
|
|
@ -18,6 +18,7 @@ BIO_lookup_type datatype
|
||||||
CRYPTO_EX_dup datatype
|
CRYPTO_EX_dup datatype
|
||||||
CRYPTO_EX_free datatype
|
CRYPTO_EX_free datatype
|
||||||
CRYPTO_EX_new datatype
|
CRYPTO_EX_new datatype
|
||||||
|
DTLS_timer_cb datatype
|
||||||
EVP_PKEY_gen_cb datatype
|
EVP_PKEY_gen_cb datatype
|
||||||
EVP_PKEY_METHOD datatype
|
EVP_PKEY_METHOD datatype
|
||||||
GEN_SESSION_CB datatype
|
GEN_SESSION_CB datatype
|
||||||
|
|
Loading…
Reference in New Issue