#include <gnutls_constate.h>
#include <gnutls/dtls.h>
-/* This function is called once a handshake message is ready to be
- * queued in the next outgoing flight. The actual transmission occurs
- * in _gnutls_dtls_transmit.
- *
- * This function is called from the handshake layer.
- */
-int
-_gnutls_dtls_handshake_enqueue (gnutls_session_t session,
- mbuffer_st* bufel,
- gnutls_handshake_description_t type,
- uint16_t sequence)
-{
- dtls_hsk_retransmit_buffer *msg;
- record_parameters_st * params;
- int ret;
-
- ret = _gnutls_epoch_get( session, EPOCH_WRITE_CURRENT, ¶ms);
- if (ret < 0)
- return gnutls_assert_val(ret);
-
- msg = gnutls_malloc (sizeof(dtls_hsk_retransmit_buffer));
- if (msg == NULL)
- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
-
- msg->bufel = bufel;
-
- msg->next = NULL;
-
- msg->epoch = params->epoch;
- msg->type = type;
- msg->sequence = sequence;
-
- params->usage_cnt++;
-
- _gnutls_dtls_log ("DTLS[%p]: Enqueued Packet[%u] %s(%d) with length: %u on epoch %d\n",
- session, (uint)sequence, _gnutls_handshake2str (type),
- type, msg->bufel->msg.size, msg->epoch);
-
- *(session->internals.dtls.retransmit_end) = msg;
- session->internals.dtls.retransmit_end = &msg->next;
-
- return 0;
-}
/* This function fragments and transmits a previously buffered
* outgoing message. */
static inline int
transmit_message (gnutls_session_t session,
- dtls_hsk_retransmit_buffer *msg)
+ mbuffer_st *bufel)
{
opaque *data, *mtu_data;
int ret = 0;
unsigned int offset, frag_len, data_size;
const uint mtu = session->internals.dtls.hsk_mtu;
- if (msg->type == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC)
+ if (bufel->htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC)
{
- ret = _gnutls_send_int (session, GNUTLS_CHANGE_CIPHER_SPEC, -1,
- msg->epoch,
- _mbuffer_get_uhead_ptr(msg->bufel),
- _mbuffer_get_uhead_size(msg->bufel), 0);
- goto leave_epoch;
+ return _gnutls_send_int (session, GNUTLS_CHANGE_CIPHER_SPEC, -1,
+ bufel->epoch,
+ _mbuffer_get_uhead_ptr(bufel),
+ _mbuffer_get_uhead_size(bufel), 0);
}
mtu_data = gnutls_malloc(mtu + DTLS_HANDSHAKE_HEADER_SIZE);
if (mtu_data == NULL)
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
- data = _mbuffer_get_udata_ptr( msg->bufel);
- data_size = _mbuffer_get_udata_size(msg->bufel);
+ data = _mbuffer_get_udata_ptr( bufel);
+ data_size = _mbuffer_get_udata_size(bufel);
/* Write fixed headers
*/
/* Handshake type */
- mtu_data[0] = (uint8_t) msg->type;
+ mtu_data[0] = (uint8_t) bufel->htype;
/* Total length */
_gnutls_write_uint24 (data_size, &mtu_data[1]);
/* Handshake sequence */
- _gnutls_write_uint16 (msg->sequence, &mtu_data[4]);
+ _gnutls_write_uint16 (bufel->sequence, &mtu_data[4]);
/* Chop up and send handshake message into mtu-size pieces. */
for (offset=0; offset <= data_size; offset += mtu)
/* Fragment length */
_gnutls_write_uint24 (frag_len, &mtu_data[9]);
-
memcpy (&mtu_data[12], data+offset, frag_len);
_gnutls_dtls_log ("DTLS[%p]: Sending Packet[%u] fragment %s(%d) with "
"length: %u, offset: %u, fragment length: %u\n",
- session, msg->sequence,
- _gnutls_handshake2str (msg->type),
- msg->type, data_size, offset, frag_len);
+ session, bufel->sequence,
+ _gnutls_handshake2str (bufel->htype),
+ bufel->htype, data_size, offset, frag_len);
/* FIXME: We should collaborate with the record layer to pack as
* many records possible into a single datagram. We should also
* tell the record layer which epoch to use for encryption.
*/
- ret = _gnutls_send_int (session, GNUTLS_HANDSHAKE, msg->type, msg->epoch,
- mtu_data, DTLS_HANDSHAKE_HEADER_SIZE + frag_len, 0);
+ ret = _gnutls_send_int (session, GNUTLS_HANDSHAKE, bufel->htype,
+ bufel->epoch, mtu_data, DTLS_HANDSHAKE_HEADER_SIZE + frag_len, 0);
if (ret < 0)
break;
}
gnutls_free (mtu_data);
-leave_epoch:
return ret;
}
static int drop_usage_count(gnutls_session_t session)
{
- dtls_hsk_retransmit_buffer *msg;
- record_parameters_st * params;
int ret;
+ record_parameters_st * params;
+ mbuffer_head_st *const send_buffer =
+ &session->internals.handshake_send_buffer;
+ mbuffer_st *cur;
- for (msg = session->internals.dtls.retransmit; msg != NULL; msg = msg->next)
+ for (cur = send_buffer->head;
+ cur != NULL; cur = cur->next)
{
- ret = _gnutls_epoch_get( session, msg->epoch, ¶ms);
+ ret = _gnutls_epoch_get( session, cur->epoch, ¶ms);
if (ret < 0)
return gnutls_assert_val(ret);
params->usage_cnt--;
if (params->usage_cnt < 0)
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
}
+
return 0;
}
int ret;
/* PREPARING -> SENDING state transition */
- dtls_hsk_retransmit_buffer *msg;
+ mbuffer_head_st *const send_buffer =
+ &session->internals.handshake_send_buffer;
+ mbuffer_st *cur;
unsigned int total_timeout = 0;
gnutls_handshake_description_t last_type = 0;
{
_gnutls_dtls_log ("DTLS[%p]: Start of flight transmission.\n", session);
- for (msg = session->internals.dtls.retransmit; msg != NULL; msg = msg->next)
+ for (cur = send_buffer->head;
+ cur != NULL; cur = cur->next)
{
- transmit_message (session, msg);
- last_type = msg->type;
+ transmit_message (session, cur);
+ last_type = cur->htype;
}
ret = _gnutls_io_write_flush (session);
return gnutls_assert_val(ret);
/* last message in handshake -> no ack */
- if (session->security_parameters.entity == GNUTLS_SERVER &&
- last_type == GNUTLS_HANDSHAKE_FINISHED)
+ if (last_type == GNUTLS_HANDSHAKE_FINISHED &&
+ ((session->security_parameters.entity == GNUTLS_SERVER && session->internals.resumed == RESUME_FALSE) ||
+ (session->security_parameters.entity == GNUTLS_CLIENT && session->internals.resumed == RESUME_TRUE)))
{
opaque c;
ret = _gnutls_io_check_recv(session, &c, 1, session->internals.dtls.retrans_timeout);
cleanup:
drop_usage_count(session);
- _gnutls_dtls_clear_outgoing_buffer (session);
+ _mbuffer_clear(send_buffer);
/* SENDING -> WAITING state transition */
return ret;
}
-/* This function clears the outgoing flight buffer. */
-void
-_gnutls_dtls_clear_outgoing_buffer (gnutls_session_t session)
-{
- dtls_hsk_retransmit_buffer *msg, *next;
-
- _gnutls_dtls_log ("DTLS[%p]: Clearing outgoing buffer.\n", session);
-
- for (msg = session->internals.dtls.retransmit; msg != NULL;)
- {
- next = msg->next;
-
- _mbuffer_xfree(&msg->bufel);
- gnutls_free (msg);
-
- msg = next;
- }
-
- session->internals.dtls.retransmit_end = &session->internals.dtls.retransmit;
- session->internals.dtls.retransmit = NULL;
-}
/**
* gnutls_dtls_set_timeouts: