提交 fa4b82cc 编写于 作者: A Alfred E. Heggestad 提交者: Bernd Edlinger

add callback handler for setting DTLS timer interval

Reviewed-by: NMatt Caswell <matt@openssl.org>
Reviewed-by: NBernd Edlinger <bernd.edlinger@hotmail.de>
(Merged from https://github.com/openssl/openssl/pull/4011)
上级 94b5d7aa
=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);
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
......
......@@ -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,7 +392,10 @@ int dtls1_handle_timeout(SSL *s)
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)
return -1;
......@@ -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;
}
......@@ -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
......
......@@ -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);
......
......@@ -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_hostname 471 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_free datatype
CRYPTO_EX_new datatype
DTLS_timer_cb datatype
EVP_PKEY_gen_cb datatype
EVP_PKEY_METHOD datatype
GEN_SESSION_CB datatype
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册