Adding a method to change the initial DTLS retransmission timer value.
This allows an application to override the default of 1 second, which is what's instructed in RFC 6347 but is not an absolute requirement. Change-Id: I0bbb16e31990fbcab44a29325b6ec7757d5789e5 Reviewed-on: https://boringssl-review.googlesource.com/7930 Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
parent
0e01eb534c
commit
376a0fed24
@ -487,6 +487,16 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code);
|
||||
* and zero on failure. */
|
||||
OPENSSL_EXPORT int SSL_set_mtu(SSL *ssl, unsigned mtu);
|
||||
|
||||
/* DTLSv1_set_initial_timeout_duration sets the initial duration for a DTLS
|
||||
* handshake timeout.
|
||||
*
|
||||
* This duration overrides the default of 1 second, which is the strong
|
||||
* recommendation of RFC 6347 (see section 4.2.4.1). However, there may exist
|
||||
* situations where a shorter timeout would be beneficial, such as for
|
||||
* time-sensitive applications. */
|
||||
OPENSSL_EXPORT void DTLSv1_set_initial_timeout_duration(SSL *ssl,
|
||||
unsigned duration_ms);
|
||||
|
||||
/* DTLSv1_get_timeout queries the next DTLS handshake timeout. If there is a
|
||||
* timeout in progress, it sets |*out| to the time remaining and returns one.
|
||||
* Otherwise, it returns zero.
|
||||
@ -3882,6 +3892,10 @@ struct ssl_st {
|
||||
struct ssl3_state_st *s3; /* SSLv3 variables */
|
||||
struct dtls1_state_st *d1; /* DTLSv1 variables */
|
||||
|
||||
/* initial_timeout_duration_ms is the default DTLS timeout duration in
|
||||
* milliseconds. It's used to initialize the timer any time it's restarted. */
|
||||
unsigned initial_timeout_duration_ms;
|
||||
|
||||
/* callback that allows applications to peek at protocol messages */
|
||||
void (*msg_callback)(int write_p, int version, int content_type,
|
||||
const void *buf, size_t len, SSL *ssl, void *arg);
|
||||
|
23
ssl/d1_lib.c
23
ssl/d1_lib.c
@ -157,17 +157,26 @@ int dtls1_supports_cipher(const SSL_CIPHER *cipher) {
|
||||
return cipher->algorithm_enc != SSL_RC4 && cipher->algorithm_enc != SSL_eNULL;
|
||||
}
|
||||
|
||||
void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) {
|
||||
ssl->initial_timeout_duration_ms = duration_ms;
|
||||
}
|
||||
|
||||
void dtls1_start_timer(SSL *ssl) {
|
||||
/* If timer is not set, initialize duration with 1 second */
|
||||
/* If timer is not set, initialize duration (by default, 1 second) */
|
||||
if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
|
||||
ssl->d1->timeout_duration = 1;
|
||||
ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
|
||||
}
|
||||
|
||||
/* Set timeout to current time */
|
||||
get_current_time(ssl, &ssl->d1->next_timeout);
|
||||
|
||||
/* Add duration to current time */
|
||||
ssl->d1->next_timeout.tv_sec += ssl->d1->timeout_duration;
|
||||
ssl->d1->next_timeout.tv_sec += ssl->d1->timeout_duration_ms / 1000;
|
||||
ssl->d1->next_timeout.tv_usec += (ssl->d1->timeout_duration_ms % 1000) * 1000;
|
||||
if (ssl->d1->next_timeout.tv_usec >= 1000000) {
|
||||
ssl->d1->next_timeout.tv_sec++;
|
||||
ssl->d1->next_timeout.tv_usec -= 1000000;
|
||||
}
|
||||
BIO_ctrl(SSL_get_rbio(ssl), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
|
||||
&ssl->d1->next_timeout);
|
||||
}
|
||||
@ -230,9 +239,9 @@ int dtls1_is_timer_expired(SSL *ssl) {
|
||||
}
|
||||
|
||||
void dtls1_double_timeout(SSL *ssl) {
|
||||
ssl->d1->timeout_duration *= 2;
|
||||
if (ssl->d1->timeout_duration > 60) {
|
||||
ssl->d1->timeout_duration = 60;
|
||||
ssl->d1->timeout_duration_ms *= 2;
|
||||
if (ssl->d1->timeout_duration_ms > 60000) {
|
||||
ssl->d1->timeout_duration_ms = 60000;
|
||||
}
|
||||
dtls1_start_timer(ssl);
|
||||
}
|
||||
@ -241,7 +250,7 @@ void dtls1_stop_timer(SSL *ssl) {
|
||||
/* Reset everything */
|
||||
ssl->d1->num_timeouts = 0;
|
||||
memset(&ssl->d1->next_timeout, 0, sizeof(struct timeval));
|
||||
ssl->d1->timeout_duration = 1;
|
||||
ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
|
||||
BIO_ctrl(SSL_get_rbio(ssl), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
|
||||
&ssl->d1->next_timeout);
|
||||
/* Clear retransmission buffer */
|
||||
|
@ -956,8 +956,8 @@ typedef struct dtls1_state_st {
|
||||
* timeout. */
|
||||
struct timeval next_timeout;
|
||||
|
||||
/* Timeout duration */
|
||||
unsigned short timeout_duration;
|
||||
/* timeout_duration_ms is the timeout duration in milliseconds. */
|
||||
unsigned timeout_duration_ms;
|
||||
} DTLS1_STATE;
|
||||
|
||||
extern const SSL3_ENC_METHOD TLSv1_enc_data;
|
||||
|
@ -369,6 +369,10 @@ SSL *SSL_new(SSL_CTX *ctx) {
|
||||
ssl->min_version = ctx->min_version;
|
||||
ssl->max_version = ctx->max_version;
|
||||
|
||||
/* RFC 6347 states that implementations SHOULD use an initial timer value of
|
||||
* 1 second. */
|
||||
ssl->initial_timeout_duration_ms = 1000;
|
||||
|
||||
ssl->options = ctx->options;
|
||||
ssl->mode = ctx->mode;
|
||||
ssl->max_cert_list = ctx->max_cert_list;
|
||||
|
@ -1317,6 +1317,10 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (config->initial_timeout_duration_ms > 0) {
|
||||
DTLSv1_set_initial_timeout_duration(ssl.get(),
|
||||
config->initial_timeout_duration_ms);
|
||||
}
|
||||
|
||||
int sock = Connect(config->port);
|
||||
if (sock == -1) {
|
||||
|
@ -4583,6 +4583,24 @@ var timeouts = []time.Duration{
|
||||
60 * time.Second,
|
||||
}
|
||||
|
||||
// shortTimeouts is an alternate set of timeouts which would occur if the
|
||||
// initial timeout duration was set to 250ms.
|
||||
var shortTimeouts = []time.Duration{
|
||||
250 * time.Millisecond,
|
||||
500 * time.Millisecond,
|
||||
1 * time.Second,
|
||||
2 * time.Second,
|
||||
4 * time.Second,
|
||||
8 * time.Second,
|
||||
16 * time.Second,
|
||||
32 * time.Second,
|
||||
60 * time.Second,
|
||||
60 * time.Second,
|
||||
60 * time.Second,
|
||||
60 * time.Second,
|
||||
60 * time.Second,
|
||||
}
|
||||
|
||||
func addDTLSRetransmitTests() {
|
||||
// Test that this is indeed the timeout schedule. Stress all
|
||||
// four patterns of handshake.
|
||||
@ -4659,6 +4677,31 @@ func addDTLSRetransmitTests() {
|
||||
},
|
||||
flags: []string{"-async"},
|
||||
})
|
||||
|
||||
// Test the timeout schedule when a shorter initial timeout duration is set.
|
||||
testCases = append(testCases, testCase{
|
||||
protocol: dtls,
|
||||
name: "DTLS-Retransmit-Short-Client",
|
||||
config: Config{
|
||||
Bugs: ProtocolBugs{
|
||||
TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
|
||||
},
|
||||
},
|
||||
resumeSession: true,
|
||||
flags: []string{"-async", "-initial-timeout-duration-ms", "250"},
|
||||
})
|
||||
testCases = append(testCases, testCase{
|
||||
protocol: dtls,
|
||||
testType: serverTest,
|
||||
name: "DTLS-Retransmit-Short-Server",
|
||||
config: Config{
|
||||
Bugs: ProtocolBugs{
|
||||
TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
|
||||
},
|
||||
},
|
||||
resumeSession: true,
|
||||
flags: []string{"-async", "-initial-timeout-duration-ms", "250"},
|
||||
})
|
||||
}
|
||||
|
||||
func addExportKeyingMaterialTests() {
|
||||
|
@ -148,6 +148,7 @@ const Flag<int> kIntFlags[] = {
|
||||
&TestConfig::expect_server_key_exchange_hash },
|
||||
{ "-expect-key-exchange-info",
|
||||
&TestConfig::expect_key_exchange_info },
|
||||
{ "-initial-timeout-duration-ms", &TestConfig::initial_timeout_duration_ms },
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -104,6 +104,7 @@ struct TestConfig {
|
||||
bool use_sparse_dh_prime = false;
|
||||
int expect_key_exchange_info = 0;
|
||||
bool use_old_client_cert_callback = false;
|
||||
int initial_timeout_duration_ms = 0;
|
||||
};
|
||||
|
||||
bool ParseConfig(int argc, char **argv, TestConfig *out_config);
|
||||
|
Loading…
Reference in New Issue
Block a user