2 * Copyright (C) 2009-2012 Free Software Foundation, Inc.
4 * Author: Jonathan Bastien-Filiatrault
6 * This file is part of GNUTLS.
8 * The GNUTLS library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
27 #include <gnutls_int.h>
28 #include <gnutls_buffers.h>
29 #include <gnutls_mbuffers.h>
30 #include <gnutls_constate.h>
33 int _dtls_transmit(gnutls_session_t session
);
34 int _dtls_record_check(struct record_parameters_st
*rp
, uint64
* _seq
);
35 void _dtls_reset_hsk_state(gnutls_session_t session
);
37 #define MAX_DTLS_TIMEOUT 60000
39 unsigned int _dtls_timespec_sub_ms (struct timespec
*a
, struct timespec
*b
);
41 #define RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, r) { \
42 struct timespec now; \
46 diff = _dtls_timespec_sub_ms(&now, &session->internals.dtls.handshake_start_time); \
47 if (diff > session->internals.dtls.total_timeout_ms) \
49 _gnutls_dtls_log("Session timeout: %u ms\n", diff); \
50 return gnutls_assert_val(GNUTLS_E_TIMEDOUT); \
55 if (r != GNUTLS_E_INTERRUPTED) rr = GNUTLS_E_AGAIN; \
57 if (session->internals.dtls.blocking != 0) \
59 return gnutls_assert_val(rr); \
64 int _dtls_wait_and_retransmit(gnutls_session_t session
);
66 /* returns true or false depending on whether we need to
67 * handle asynchronously handshake data.
69 inline static int _dtls_is_async(gnutls_session_t session
)
71 if ((session
->security_parameters
.entity
== GNUTLS_SERVER
&& session
->internals
.resumed
== RESUME_FALSE
) ||
72 (session
->security_parameters
.entity
== GNUTLS_CLIENT
&& session
->internals
.resumed
== RESUME_TRUE
))
78 inline static void _dtls_async_timer_init(gnutls_session_t session
)
80 if (_dtls_is_async(session
))
82 _gnutls_dtls_log ("DTLS[%p]: Initializing timer for handshake state.\n", session
);
83 session
->internals
.dtls
.async_term
= gnutls_time(0) + MAX_DTLS_TIMEOUT
/1000;
87 _dtls_reset_hsk_state(session
);
88 _gnutls_handshake_io_buffer_clear (session
);
89 _gnutls_epoch_gc(session
);
90 session
->internals
.dtls
.async_term
= 0;
94 void _dtls_async_timer_delete(gnutls_session_t session
);
96 /* Checks whether it is time to terminate the timer
98 inline static void _dtls_async_timer_check(gnutls_session_t session
)
100 if (!IS_DTLS(session
))
103 if (session
->internals
.dtls
.async_term
!= 0)
105 time_t now
= time(0);
107 /* check if we need to expire the queued handshake data */
108 if (now
> session
->internals
.dtls
.async_term
)
110 _dtls_async_timer_delete(session
);
115 /* Returns non-zero if the async timer is active */
116 inline static int _dtls_async_timer_active(gnutls_session_t session
)
118 if (!IS_DTLS(session
))
121 return session
->internals
.dtls
.async_term
;
124 /* This function is to be called from record layer once
125 * a handshake replay is detected. It will make sure
126 * it transmits only once per few seconds. Otherwise
127 * it is the same as _dtls_transmit().
129 inline static int _dtls_retransmit(gnutls_session_t session
)
131 return _dtls_transmit(session
);