From: Nikos Mavrogiannopoulos Date: Fri, 18 Feb 2011 10:41:11 +0000 (+0100) Subject: use similar API when caching messages in DTLS or TLS. X-Git-Tag: gnutls_2_99_0~224 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=91b08751670b65705d66aeed7aec53405e9e5d02;p=thirdparty%2Fgnutls.git use similar API when caching messages in DTLS or TLS. --- diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c index 692e61bc2e..9e078455c9 100644 --- a/lib/gnutls_buffers.c +++ b/lib/gnutls_buffers.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -841,6 +842,10 @@ _gnutls_handshake_io_write_flush (gnutls_session_t session) _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)) { @@ -877,12 +882,17 @@ _gnutls_handshake_io_write_flush (gnutls_session_t session) * 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); @@ -892,7 +902,7 @@ _gnutls_handshake_io_cache_int (gnutls_session_t session, ("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 diff --git a/lib/gnutls_buffers.h b/lib/gnutls_buffers.h index 3dfad550fe..3546fc6e58 100644 --- a/lib/gnutls_buffers.h +++ b/lib/gnutls_buffers.h @@ -56,7 +56,7 @@ int _gnutls_handshake_buffer_get_ptr (gnutls_session_t session, 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); diff --git a/lib/gnutls_dtls.c b/lib/gnutls_dtls.c index 2cc67f7667..20d238e4f2 100644 --- a/lib/gnutls_dtls.c +++ b/lib/gnutls_dtls.c @@ -30,6 +30,7 @@ #include "debug.h" #include "gnutls_dtls.h" #include "gnutls_record.h" +#include /* This function is called once a handshake message is ready to be * queued in the next outgoing flight. The actual transmission occurs @@ -39,8 +40,7 @@ */ 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) { @@ -53,17 +53,7 @@ _gnutls_dtls_handshake_enqueue (gnutls_session_t session, 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 */ @@ -73,7 +63,7 @@ _gnutls_dtls_handshake_enqueue (gnutls_session_t session, _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; @@ -87,61 +77,65 @@ static inline int 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 @@ -183,7 +177,7 @@ _gnutls_dtls_clear_outgoing_buffer (gnutls_session_t session) { next = msg->next; - gnutls_free (msg->msg.data); + _mbuffer_xfree(&msg->bufel); gnutls_free (msg); msg = next; diff --git a/lib/gnutls_dtls.h b/lib/gnutls_dtls.h index f870c1bc7b..4a9aa127ca 100644 --- a/lib/gnutls_dtls.h +++ b/lib/gnutls_dtls.h @@ -27,11 +27,11 @@ #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); diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index c6c699fd45..34d30fbed8 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -33,7 +33,6 @@ #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" @@ -1241,17 +1240,19 @@ _gnutls_send_handshake (gnutls_session_t session, mbuffer_st * bufel, _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) { @@ -2867,8 +2868,6 @@ _gnutls_handshake_client (gnutls_session_t session) STATE = STATE1; IMED_RET ("send hello", ret, 1); - _gnutls_dtls_transmit(session); - case STATE11: if (_gnutls_is_dtls (session)) { @@ -2964,7 +2963,6 @@ _gnutls_handshake_client (gnutls_session_t 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: @@ -3038,7 +3036,6 @@ _gnutls_send_handshake_final (gnutls_session_t session, int init) return ret; } - _gnutls_dtls_transmit(session); STATE = STATE0; default: break; diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 90efdb5eae..7cd9a32689 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -284,6 +284,25 @@ typedef struct mbuffer_head_st 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 */ @@ -531,27 +550,6 @@ typedef struct 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