#include <gnutls_buffers.h>
#include <gnutls_mbuffers.h>
#include <gnutls_state.h>
+#include <gnutls_dtls.h>
#include <system.h>
#include <errno.h>
_gnutls_write_log ("HWRITE FLUSH: %d bytes in buffer.\n",
(int) send_buffer->byte_length);
+ if (IS_DTLS)
+ return _gnutls_dtls_transmit(session);
+
+
for (cur = _mbuffer_get_first (send_buffer, &msg);
cur != NULL; cur = _mbuffer_get_first (send_buffer, &msg))
{
* protocol. Just makes sure that all data have been sent.
*
*/
-void
+int
_gnutls_handshake_io_cache_int (gnutls_session_t session,
gnutls_handshake_description_t htype,
mbuffer_st * bufel)
{
- mbuffer_head_st *const send_buffer =
+ mbuffer_head_st * send_buffer;
+
+ if (IS_DTLS)
+ return _gnutls_dtls_handshake_enqueue(session, bufel, htype, session->internals.dtls.hsk_write_seq-1);
+
+ send_buffer =
&session->internals.handshake_send_buffer;
_mbuffer_enqueue (send_buffer, bufel);
("HWRITE: enqueued %d. Total %d bytes.\n",
(int) bufel->msg.size, (int) send_buffer->byte_length);
- return;
+ return 0;
}
/* This is a receive function for the gnutls handshake
ssize_t _gnutls_handshake_io_recv_int (gnutls_session_t, content_type_t,
gnutls_handshake_description_t, void *,
size_t);
-void _gnutls_handshake_io_cache_int (gnutls_session_t,
+int _gnutls_handshake_io_cache_int (gnutls_session_t,
gnutls_handshake_description_t,
mbuffer_st * bufel);
ssize_t _gnutls_io_write_flush (gnutls_session_t session);
#include "debug.h"
#include "gnutls_dtls.h"
#include "gnutls_record.h"
+#include <gnutls_mbuffers.h>
/* This function is called once a handshake message is ready to be
* queued in the next outgoing flight. The actual transmission occurs
*/
int
_gnutls_dtls_handshake_enqueue (gnutls_session_t session,
- opaque *data,
- uint32_t datasize,
+ mbuffer_st* bufel,
gnutls_handshake_description_t type,
uint16_t sequence)
{
return GNUTLS_E_MEMORY_ERROR;
}
- msg->msg.size = datasize - DTLS_HANDSHAKE_HEADER_SIZE;
-
- msg->msg.data = gnutls_malloc (msg->msg.size);
- if (msg->msg.data == NULL)
- {
- gnutls_free (msg);
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- memcpy (msg->msg.data, data + DTLS_HANDSHAKE_HEADER_SIZE, msg->msg.size);
+ msg->bufel = bufel;
msg->next = NULL;
/* FIXME: dummy epoch */
_gnutls_dtls_log ("DTLS[%p]: Enqueued Packet[%u] %s(%d) with length: %u\n",
session, (uint)sequence, _gnutls_handshake2str (type),
- type, msg->msg.size);
+ type, msg->bufel->msg.size);
*(session->internals.dtls.retransmit_end) = msg;
session->internals.dtls.retransmit_end = &msg->next;
transmit_message (gnutls_session_t session,
dtls_hsk_retransmit_buffer *msg)
{
- opaque *data;
- uint offset, frag_len;
+ opaque *data, *mtu_data;
+ int ret = 0;
+ unsigned int offset, frag_len, data_size;
const uint mtu = session->internals.dtls.hsk_mtu;
- data = gnutls_malloc (DTLS_HANDSHAKE_HEADER_SIZE + mtu);
- if (data == NULL)
- {
- gnutls_assert ();
- return GNUTLS_E_MEMORY_ERROR;
- }
+ 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);
/* Write fixed headers
*/
/* Handshake type */
- data[0] = (uint8_t) msg->type;
+ mtu_data[0] = (uint8_t) msg->type;
/* Total length */
- _gnutls_write_uint24 (msg->msg.size, &data[1]);
+ _gnutls_write_uint24 (data_size, &mtu_data[1]);
/* Handshake sequence */
- _gnutls_write_uint16 (msg->sequence, &data[4]);
+ _gnutls_write_uint16 (msg->sequence, &mtu_data[4]);
/* Chop up and send handshake message into mtu-size pieces. */
- for (offset=0; offset < msg->msg.size; offset += mtu)
+ for (offset=0; offset < data_size; offset += mtu)
{
/* Calculate fragment length */
- if(offset + mtu > msg->msg.size)
- frag_len = msg->msg.size - offset;
+ if(offset + mtu > data_size)
+ frag_len = data_size - offset;
else
frag_len = mtu;
/* Fragment offset */
- _gnutls_write_uint24 (offset, &data[6]);
+ _gnutls_write_uint24 (offset, &mtu_data[6]);
/* Fragment length */
- _gnutls_write_uint24 (frag_len, &data[9]);
+ _gnutls_write_uint24 (frag_len, &mtu_data[9]);
- memcpy (&data[12], msg->msg.data + offset, frag_len);
+
+ 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, msg->msg.size, offset, frag_len);
+ msg->type, 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. */
- _gnutls_send_int (session, GNUTLS_HANDSHAKE, msg->type, EPOCH_WRITE_CURRENT,
- data, DTLS_HANDSHAKE_HEADER_SIZE + frag_len, 0);
+ ret = _gnutls_send_int (session, GNUTLS_HANDSHAKE, msg->type, EPOCH_WRITE_CURRENT,
+ mtu_data, DTLS_HANDSHAKE_HEADER_SIZE + frag_len, 0);
+ if (ret < 0)
+ break;
}
- gnutls_free (data);
- return 0;
+ gnutls_free (mtu_data);
+ return ret;
}
/* This function transmits the flight that has been previously
{
next = msg->next;
- gnutls_free (msg->msg.data);
+ _mbuffer_xfree(&msg->bufel);
gnutls_free (msg);
msg = next;
#include "gnutls_int.h"
-int _gnutls_dtls_handshake_enqueue(gnutls_session_t session,
- opaque *data,
- uint32_t datasize,
- gnutls_handshake_description_t type,
- uint16_t sequence);
+int
+_gnutls_dtls_handshake_enqueue (gnutls_session_t session,
+ mbuffer_st* bufel,
+ gnutls_handshake_description_t type,
+ uint16_t sequence);
int _gnutls_dtls_transmit(gnutls_session_t session);
void _gnutls_dtls_clear_outgoing_buffer(gnutls_session_t session);
#include "gnutls_algorithms.h"
#include "gnutls_compress.h"
#include "gnutls_cipher.h"
-#include "gnutls_dtls.h"
#include "gnutls_buffers.h"
#include "gnutls_mbuffers.h"
#include "gnutls_kx.h"
_gnutls_handshake_hash_add_sent (session, type, data, datasize)) < 0)
{
gnutls_assert ();
- gnutls_free (bufel);
+ _mbuffer_xfree(&bufel);
return ret;
}
session->internals.last_handshake_out = type;
- if (_gnutls_is_dtls(session))
- _gnutls_dtls_handshake_enqueue (session, data, datasize, type,
- session->internals.dtls.hsk_write_seq-1);
- else
- _gnutls_handshake_io_cache_int (session, type, bufel);
+ ret = _gnutls_handshake_io_cache_int (session, type, bufel);
+ if (ret < 0)
+ {
+ _mbuffer_xfree(&bufel);
+ gnutls_assert();
+ return ret;
+ }
switch (type)
{
STATE = STATE1;
IMED_RET ("send hello", ret, 1);
- _gnutls_dtls_transmit(session);
-
case STATE11:
if (_gnutls_is_dtls (session))
{
_gnutls_send_client_certificate_verify (session, AGAIN (STATE9));
STATE = STATE9;
IMED_RET ("send client certificate verify", ret, 1);
- _gnutls_dtls_transmit(session);
STATE = STATE0;
default:
return ret;
}
- _gnutls_dtls_transmit(session);
STATE = STATE0;
default:
break;
size_t byte_length;
} mbuffer_head_st;
+/* This is a linked list used to buffer the next flight of outgoing
+ handshake messages. Messages are queued whole; they are fragmented
+ dynamically on transmit. */
+typedef struct dtls_hsk_retransmit_buffer
+{
+ struct dtls_hsk_retransmit_buffer *next;
+
+ /* The actual handshake message */
+ mbuffer_st* bufel;
+
+ /* Record layer epoch of message */
+ uint16_t epoch;
+
+ /* Handshake layer type and sequence of message */
+ gnutls_handshake_description_t type;
+ uint16_t sequence;
+} dtls_hsk_retransmit_buffer;
+
+
typedef enum
{
HANDSHAKE_MAC_TYPE_10 = 1, /* TLS 1.0 style */
int free_rsa_params;
} internal_params_st;
-struct dtls_hsk_retransmit_buffer;
-typedef struct dtls_hsk_retransmit_buffer dtls_hsk_retransmit_buffer;
-
-/* This is a linked list used to buffer the next flight of outgoing
- handshake messages. Messages are queued whole; they are fragmented
- dynamically on transmit. */
-struct dtls_hsk_retransmit_buffer
-{
- dtls_hsk_retransmit_buffer *next;
-
- /* The actual handshake message */
- gnutls_datum_t msg;
-
- /* Record layer epoch of message */
- uint16_t epoch;
-
- /* Handshake layer type and sequence of message */
- gnutls_handshake_description_t type;
- uint16_t sequence;
-};
-
/* DTLS session state
*/
typedef struct