I have updated the last patch, considering the suggestions of Daniel
Mentz.
The previous solutions were done in the BIO object, which was not a
good choice. Additionally they didn't allow non-blocking sockets to be
used.
This approach doesn't rely on socket errors anymore. The timer stuff
is completely rewritten and now part of the DTLS implementation, where
it belongs to. If a timer is started, it also tells the BIO object
when it will expire, so that the BIO object is able to adjust its
sockets timeouts if necessary. This prevents needless waiting time
during handshakes if the socket timeouts are set too generous by the
user or the socket timer starts just before the message timer is about
to expire. With every retransmission the duration of the timer is
doubled up to 60 seconds unless the expected message arrived. Non-
Blocking sockets shouldn't be problem anymore, too.
--- crypto/bio/bio.h 2009-04-14 16:33:12.000000000 +0200
+++ crypto/bio/bio.h 2009-05-12 10:20:24.000000000 +0200
@@ -159,7 +159,8 @@
#define BIO_CTRL_DGRAM_SET_PEER 44 /* Destination for the
data */
-#define BIO_CTRL_DGRAM_SET_TIMEOUT 45
+#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT 45 /* Next DTLS handshake
timeout to
+ * adjust socket
timeouts */
/* modifiers */
#define BIO_FP_READ 0x02
--- crypto/bio/bss_dgram.c 2009-04-14 17:13:35.000000000 +0200
+++ crypto/bio/bss_dgram.c 2009-05-12 11:08:04.000000000 +0200
@@ -108,8 +108,8 @@
unsigned int connected;
unsigned int _errno;
unsigned int mtu;
- struct timeval hstimeoutdiff;
- struct timeval hstimeout;
+ struct timeval next_timeout;
+ struct timeval socket_timeout;
} bio_dgram_data;
BIO_METHOD *BIO_s_datagram(void)
@@ -171,7 +171,95 @@
}
return(1);
}
-
+
+static void dgram_adjust_rcv_timeout(BIO *b)
+ {
+#if defined(SO_RCVTIMEO)
+ bio_dgram_data *data = (bio_dgram_data *)b->ptr;
+ int sz = sizeof(int);
+
+ /* Is a timer active? */
+ if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0)
+ {
+ struct timeval timenow, timeleft;
+
+ /* Read current socket timeout */
+#ifdef OPENSSL_SYS_WINDOWS
+ struct _timeb tb;
+ int timeout;
+ if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
+ (void*)&timeout, &sz) < 0)
+ { perror("getsockopt"); }
+ else
+ {
+ data->socket_timeout.tv_sec = timeout / 1000;
+ data->socket_timeout.tv_usec = (timeout % 1000) * 1000;
+ }
+#else
+ if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
+ &(data->socket_timeout), (void
*)&sz) < 0)
+ { perror("getsockopt"); }
+#endif
+
+ /* Get current time */
+#ifdef OPENSSL_SYS_WIN32
+ _ftime(&tb);
+ timenow.tv_sec = (long) tb.time;
+ timenow.tv_usec = (long) tb.millitm * 1000;
+#else
+ gettimeofday(&timenow, NULL);
+#endif
+
+ /* Calculate time left until timer expires */
+ memcpy(&timeleft, &(data->next_timeout), sizeof(struct
timeval));
+ timeleft.tv_sec -= timenow.tv_sec;
+ timeleft.tv_usec -= timenow.tv_usec;
+ if (timeleft.tv_usec < 0)
+ {
+ timeleft.tv_sec--;
+ timeleft.tv_usec += 1000000;
+ }
+
+ /* Adjust socket timeout if next handhake message timer
+ * will expire earlier.
+ */
+ if (data->socket_timeout.tv_sec < timeleft.tv_sec ||
+ (data->socket_timeout.tv_sec == timeleft.tv_sec &&
+ data->socket_timeout.tv_usec <= timeleft.tv_usec))
+ {
+#ifdef OPENSSL_SYS_WINDOWS
+ timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec /
1000;
+ if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
+ (void*)&timeout,
sizeof(timeout)) < 0)
+ { perror("setsockopt"); }
+#else
+ if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
&timeleft,
+ sizeof(struct timeval))
< 0)
+ { perror("setsockopt"); }
+#endif
+ }
+ }
+#endif
+ }
+
+static void dgram_reset_rcv_timeout(BIO *b)
+ {
+#if defined(SO_RCVTIMEO)
+ bio_dgram_data *data = (bio_dgram_data *)b->ptr;
+#ifdef OPENSSL_SYS_WINDOWS
+ int timeout = data->socket_timeout.tv_sec * 1000 +
+ data->socket_timeout.tv_usec / 1000;
+ if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
+ (void*)&timeout, sizeof(timeout)) < 0)
+ { perror("setsockopt"); }
+#else
+ if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &(data-
>socket_timeout),
+ sizeof(struct timeval)) < 0)
+ { perror("setsockopt"); }
+#endif
+#endif
+ }
+
static int dgram_read(BIO *b, char *out, int outl)
{
int ret=0;
@@ -189,7 +277,9 @@
* but this is not universal. Cast to (void *) to avoid
* compiler warnings.
*/
+ dgram_adjust_rcv_timeout(b);
ret=recvfrom(b->num,out,outl,0,&peer,(void *)&peerlen);
+ dgram_reset_rcv_timeout(b);
if ( ! data->connected && ret > 0)
BIO_ctrl(b, BIO_CTRL_DGRAM_CONNECT, 0, &peer);
@@ -202,30 +292,6 @@
BIO_set_retry_read(b);
data->_errno = get_last_socket_error();
}
- memset(&(data->hstimeout), 0, sizeof(struct timeval));
- }
- else
- {
- if (data->hstimeout.tv_sec > 0 ||
data->hstimeout.tv_usec > 0)
- {
- struct timeval curtime;
-#ifdef OPENSSL_SYS_WIN32
- struct _timeb tb;
- _ftime(&tb);
- curtime.tv_sec = (long)tb.time;
- curtime.tv_usec = (long)tb.millitm * 1000;
-#else
- gettimeofday(&curtime, NULL);
-#endif
-
- if (curtime.tv_sec >= data->hstimeout.tv_sec &&
- curtime.tv_usec >=
data->hstimeout.tv_usec)
- {
- data->_errno = EAGAIN;
- ret = -1;
- memset(&(data->hstimeout), 0,
sizeof(struct timeval));
- }
- }
}
}
return(ret);
@@ -375,29 +441,8 @@
memcpy(&(data->peer), to, sizeof(struct sockaddr));
break;
- case BIO_CTRL_DGRAM_SET_TIMEOUT:
- if (num > 0)
- {
-#ifdef OPENSSL_SYS_WIN32
- struct _timeb tb;
- _ftime(&tb);
- data->hstimeout.tv_sec = (long)tb.time;
- data->hstimeout.tv_usec = (long)tb.millitm * 1000;
-#else
- gettimeofday(&(data->hstimeout), NULL);
-#endif
- data->hstimeout.tv_sec += data->hstimeoutdiff.tv_sec;
- data->hstimeout.tv_usec += data->hstimeoutdiff.tv_usec;
- if (data->hstimeout.tv_usec >= 1000000)
- {
- data->hstimeout.tv_sec++;
- data->hstimeout.tv_usec -= 1000000;
- }
- }
- else
- {
- memset(&(data->hstimeout), 0, sizeof(struct timeval));
- }
+ case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
+ memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
break;
#if defined(SO_RCVTIMEO)
case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
@@ -414,7 +459,6 @@
sizeof(struct timeval)) < 0)
{ perror("setsockopt"); ret = -1; }
#endif
- memcpy(&(data->hstimeoutdiff), ptr, sizeof(struct timeval));
break;
case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
#ifdef OPENSSL_SYS_WINDOWS
--- ssl/d1_both.c 2009-04-19 20:03:11.000000000 +0200
+++ ssl/d1_both.c 2009-05-12 10:44:13.000000000 +0200
@@ -882,7 +882,6 @@
int dtls1_read_failed(SSL *s, int code)
{
DTLS1_STATE *state;
- BIO *bio;
int send_alert = 0;
if ( code > 0)
@@ -891,8 +890,7 @@
return 1;
}
- bio = SSL_get_rbio(s);
- if ( ! BIO_dgram_recv_timedout(bio))
+ if (!dtls1_is_timer_expired(s))
{
/* not a timeout, none of our business,
let higher layers handle this. in fact it's probably an
error */
@@ -905,6 +903,7 @@
return code;
}
+ dtls1_double_timeout(s);
state = s->d1;
state->timeout.num_alerts++;
if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
--- ssl/d1_clnt.c 2009-05-11 17:48:38.000000000 +0200
+++ ssl/d1_clnt.c 2009-05-12 10:53:41.000000000 +0200
@@ -230,7 +230,7 @@
/* every DTLS ClientHello resets Finished MAC */
ssl3_init_finished_mac(s);
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_client_hello(s);
if (ret <= 0) goto end;
@@ -256,7 +256,7 @@
if (ret <= 0) goto end;
else
{
- BIO_ctrl(SSL_get_rbio(s),
BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
+ dtls1_stop_timer(s);
if (s->hit)
s->state=SSL3_ST_CR_FINISHED_A;
else
@@ -271,7 +271,7 @@
ret = dtls1_get_hello_verify(s);
if ( ret <= 0)
goto end;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
0, NULL);
+ dtls1_stop_timer(s);
if ( s->d1->send_cookie) /* start again, with a cookie
*/
s->state=SSL3_ST_CW_CLNT_HELLO_A;
else
@@ -333,7 +333,7 @@
case SSL3_ST_CW_CERT_B:
case SSL3_ST_CW_CERT_C:
case SSL3_ST_CW_CERT_D:
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_send_client_certificate(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_CW_KEY_EXCH_A;
@@ -342,7 +342,7 @@
case SSL3_ST_CW_KEY_EXCH_A:
case SSL3_ST_CW_KEY_EXCH_B:
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_send_client_key_exchange(s);
if (ret <= 0) goto end;
/* EAY EAY EAY need to check for DH fix cert
@@ -364,7 +364,7 @@
case SSL3_ST_CW_CERT_VRFY_A:
case SSL3_ST_CW_CERT_VRFY_B:
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_send_client_verify(s);
if (ret <= 0) goto end;
s->state=SSL3_ST_CW_CHANGE_A;
@@ -374,7 +374,7 @@
case SSL3_ST_CW_CHANGE_A:
case SSL3_ST_CW_CHANGE_B:
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_send_change_cipher_spec(s,
SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
if (ret <= 0) goto end;
@@ -409,7 +409,7 @@
case SSL3_ST_CW_FINISHED_A:
case SSL3_ST_CW_FINISHED_B:
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_send_finished(s,
SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
s->method->ssl3_enc->client_finished_label,
@@ -442,7 +442,7 @@
ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
SSL3_ST_CR_FINISHED_B);
if (ret <= 0) goto end;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
0, NULL);
+ dtls1_stop_timer(s);
if (s->hit)
s->state=SSL3_ST_CW_CHANGE_A;
--- ssl/d1_lib.c 2009-04-19 20:03:12.000000000 +0200
+++ ssl/d1_lib.c 2009-05-12 10:41:39.000000000 +0200
@@ -61,6 +61,10 @@
#include <openssl/objects.h>
#include "ssl_locl.h"
+#ifdef OPENSSL_SYS_WIN32
+#include <sys/timeb.h>
+#endif
+
const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT;
SSL3_ENC_METHOD DTLSv1_enc_data={
@@ -201,3 +205,110 @@
return ciph;
}
+
+void dtls1_start_timer(SSL *s)
+ {
+#ifdef OPENSSL_SYS_WIN32
+ struct _timeb tb;
+#endif
+
+ /* If timer is not set, initialize duration with 1 second */
+ if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec
== 0)
+ {
+ s->d1->timeout_duration = 1;
+ }
+
+ /* Set timeout to current time */
+#ifdef OPENSSL_SYS_WIN32
+ _ftime(&tb);
+ s->d1->next_timeout.tv_sec = (long) tb.time;
+ s->d1->next_timeout.tv_usec = (long) tb.millitm * 1000;
+#else
+ gettimeofday(&(s->d1->next_timeout), NULL);
+#endif
+
+ /* Add duration to current time */
+ s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s-
>d1->next_timeout));
+ }
+
+struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft)
+ {
+#ifdef OPENSSL_SYS_WIN32
+ struct _timeb tb;
+#endif
+ struct timeval timenow;
+
+ /* If no timeout is set, just return NULL */
+ if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec
== 0)
+ {
+ return NULL;
+ }
+
+ /* Get current time */
+#ifdef OPENSSL_SYS_WIN32
+ _ftime(&tb);
+ timenow.tv_sec = (long) tb.time;
+ timenow.tv_usec = (long) tb.millitm * 1000;
+#else
+ gettimeofday(&timenow, NULL);
+#endif
+
+ /* If timer already expired, set remaining time to 0 */
+ if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
+ (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
+ s->d1->next_timeout.tv_usec <= timenow.tv_usec))
+ {
+ memset(timeleft, 0, sizeof(struct timeval));
+ return timeleft;
+ }
+
+ /* Calculate time left until timer expires */
+ memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
+ timeleft->tv_sec -= timenow.tv_sec;
+ timeleft->tv_usec -= timenow.tv_usec;
+ if (timeleft->tv_usec < 0)
+ {
+ timeleft->tv_sec--;
+ timeleft->tv_usec += 1000000;
+ }
+
+ return timeleft;
+ }
+
+int dtls1_is_timer_expired(SSL *s)
+ {
+ struct timeval timeleft;
+
+ /* Get time left until timeout, return false if no timer running */
+ if (dtls1_get_timeout(s, &timeleft) == NULL)
+ {
+ return 0;
+ }
+
+ /* Return false if timer is not expired yet */
+ if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0)
+ {
+ return 0;
+ }
+
+ /* Timer expired, so return true */
+ return 1;
+ }
+
+void dtls1_double_timeout(SSL *s)
+ {
+ s->d1->timeout_duration *= 2;
+ if (s->d1->timeout_duration > 60)
+ s->d1->timeout_duration = 60;
+ dtls1_start_timer(s);
+ }
+
+void dtls1_stop_timer(SSL *s)
+ {
+ /* Reset everything */
+ memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
+ s->d1->timeout_duration = 1;
+ BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s-
>d1->next_timeout));
+ }
+
--- ssl/d1_pkt.c 2009-04-21 17:11:59.000000000 +0200
+++ ssl/d1_pkt.c 2009-05-12 10:48:14.000000000 +0200
@@ -762,7 +762,14 @@
pitem_free(item);
}
}
-
+
+ /* Check for timeout */
+ if (dtls1_is_timer_expired(s))
+ {
+ if (dtls1_read_failed(s, -1) > 0);
+ goto start;
+ }
+
/* get new packet if necessary */
if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
{
--- ssl/d1_srvr.c 2009-04-19 20:03:12.000000000 +0200
+++ ssl/d1_srvr.c 2009-05-12 10:57:26.000000000 +0200
@@ -249,7 +249,7 @@
case SSL3_ST_SW_HELLO_REQ_B:
s->shutdown=0;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_send_hello_request(s);
if (ret <= 0) goto end;
s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
@@ -270,7 +270,7 @@
s->shutdown=0;
ret=ssl3_get_client_hello(s);
if (ret <= 0) goto end;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
0, NULL);
+ dtls1_stop_timer(s);
s->new_session = 2;
if (s->d1->send_cookie)
@@ -284,7 +284,7 @@
case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
1, NULL);
+ dtls1_start_timer(s);
ret = dtls1_send_hello_verify_request(s);
if ( ret <= 0) goto end;
s->d1->send_cookie = 0;
@@ -298,7 +298,7 @@
case SSL3_ST_SW_SRVR_HELLO_A:
case SSL3_ST_SW_SRVR_HELLO_B:
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_send_server_hello(s);
if (ret <= 0) goto end;
@@ -314,7 +314,7 @@
/* Check if it is anon DH */
if (!(s->s3->tmp.new_cipher->algorithm_auth &
SSL_aNULL))
{
- BIO_ctrl(SSL_get_rbio(s),
BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_send_server_certificate(s);
if (ret <= 0) goto end;
}
@@ -356,7 +356,7 @@
)
)
{
- BIO_ctrl(SSL_get_rbio(s),
BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_send_server_key_exchange(s);
if (ret <= 0) goto end;
}
@@ -393,7 +393,7 @@
else
{
s->s3->tmp.cert_request=1;
- BIO_ctrl(SSL_get_rbio(s),
BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_send_certificate_request(s);
if (ret <= 0) goto end;
#ifndef NETSCAPE_HANG_BUG
@@ -408,7 +408,7 @@
case SSL3_ST_SW_SRVR_DONE_A:
case SSL3_ST_SW_SRVR_DONE_B:
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
1, NULL);
+ dtls1_start_timer(s);
ret=dtls1_send_server_done(s);
if (ret <= 0) goto end;
s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
@@ -436,7 +436,7 @@
ret = ssl3_check_client_hello(s);
if (ret <= 0)
goto end;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
0, NULL);
+ dtls1_stop_timer(s);
if (ret == 2)
s->state = SSL3_ST_SR_CLNT_HELLO_C;
else {
@@ -444,7 +444,7 @@
* have not asked for it :-) */
ret=ssl3_get_client_certificate(s);
if (ret <= 0) goto end;
- BIO_ctrl(SSL_get_rbio(s),
BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
+ dtls1_stop_timer(s);
s->init_num=0;
s->state=SSL3_ST_SR_KEY_EXCH_A;
}
@@ -454,7 +454,7 @@
case SSL3_ST_SR_KEY_EXCH_B:
ret=ssl3_get_client_key_exchange(s);
if (ret <= 0) goto end;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
0, NULL);
+ dtls1_stop_timer(s);
s->state=SSL3_ST_SR_CERT_VRFY_A;
s->init_num=0;
@@ -475,7 +475,7 @@
/* we should decide if we expected this one */
ret=ssl3_get_cert_verify(s);
if (ret <= 0) goto end;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
0, NULL);
+ dtls1_stop_timer(s);
s->state=SSL3_ST_SR_FINISHED_A;
s->init_num=0;
@@ -486,7 +486,7 @@
ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
SSL3_ST_SR_FINISHED_B);
if (ret <= 0) goto end;
- BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT,
0, NULL);
+ dtls1_stop_timer(s);
if (s->hit)
s->state=SSL_ST_OK;
else
--- ssl/dtls1.h 2009-04-19 20:03:12.000000000 +0200
+++ ssl/dtls1.h 2009-05-12 11:02:03.000000000 +0200
@@ -210,7 +210,13 @@
struct hm_header_st r_msg_hdr;
struct dtls1_timeout_st timeout;
-
+
+ /* Indicates when the last handshake msg sent will timeout */
+ struct timeval next_timeout;
+
+ /* Timeout duration */
+ unsigned short timeout_duration;
+
/* storage for Alert/Handshake protocol data received but not
* yet processed by ssl3_read_bytes: */
unsigned char alert_fragment[DTLS1_AL_HEADER_LENGTH];
--- ssl/ssl_locl.h 2009-04-15 16:49:36.000000000 +0200
+++ ssl/ssl_locl.h 2009-05-12 12:20:19.000000000 +0200
@@ -942,6 +942,7 @@
void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st
*ccs_hdr);
void dtls1_reset_seq_numbers(SSL *s, int rw);
long dtls1_default_timeout(void);
+struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft);
const SSL_CIPHER *dtls1_get_cipher(unsigned int u);
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [email protected]