]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Combined DTLS buffers and normal TLS buffers.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 20 Feb 2011 09:38:33 +0000 (10:38 +0100)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Sun, 20 Feb 2011 09:38:33 +0000 (10:38 +0100)
lib/gnutls_buffers.c
lib/gnutls_dtls.c
lib/gnutls_dtls.h
lib/gnutls_int.h
lib/gnutls_state.c

index 41b024488f8531a70f1493f1a428e7b1efa1a921..4df1d57154b9bfee4bbf72f45242e3628b903ffc 100644 (file)
@@ -57,7 +57,7 @@
 #include <gnutls_state.h>
 #include <gnutls_dtls.h>
 #include <system.h>
-
+#include <gnutls_constate.h> /* gnutls_epoch_get */
 #include <errno.h>
 
 #ifndef EAGAIN
@@ -827,7 +827,6 @@ _gnutls_handshake_io_write_flush (gnutls_session_t session)
   if (IS_DTLS(session))
     return _gnutls_dtls_transmit(session);
 
-
   for (cur = _mbuffer_get_first (send_buffer, &msg);
        cur != NULL; cur = _mbuffer_get_first (send_buffer, &msg))
     {
@@ -870,9 +869,22 @@ _gnutls_handshake_io_cache_int (gnutls_session_t session,
                                 mbuffer_st * bufel)
 {
   mbuffer_head_st * send_buffer;
-  
+
   if (IS_DTLS(session))
-    return _gnutls_dtls_handshake_enqueue(session, bufel, htype, session->internals.dtls.hsk_write_seq-1);
+    {
+      record_parameters_st * params;
+      int ret;
+
+      ret = _gnutls_epoch_get( session, EPOCH_WRITE_CURRENT, &params);
+      if (ret < 0)
+        return gnutls_assert_val(ret);
+
+      bufel->epoch = params->epoch;
+      bufel->htype = htype;
+      bufel->sequence = session->internals.dtls.hsk_write_seq-1;
+
+      params->usage_cnt++;
+    }
   
   send_buffer =
     &session->internals.handshake_send_buffer;
index fdb8479347d117f221ac1a622b95cabeed7bc0f9..43ce1e824c822cf87ffa1a63676e29aedd8cb03c 100644 (file)
 #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, &params);
-  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)
@@ -133,46 +89,48 @@ transmit_message (gnutls_session_t session,
       /* 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, &params);
+      ret = _gnutls_epoch_get( session, cur->epoch, &params);
       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;
 }
 
@@ -188,7 +146,9 @@ _gnutls_dtls_transmit (gnutls_session_t session)
 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;
 
@@ -196,10 +156,11 @@ int ret;
     {
       _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);
@@ -207,8 +168,9 @@ int ret;
         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);
@@ -244,33 +206,12 @@ int ret;
 
 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:
index 80958dd6f25f2ad322c048e9c34c46175542d55b..d3a4870bbbf9d3753b40cbfe744f8cb78e844573 100644 (file)
 
 #include "gnutls_int.h"
 
-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);
 
 #endif
index d3da01d6efcae4af20077621fbd355010ac1a5eb..45bfbeb2edec1ec4ab203f804b8de460efdd40b4 100644 (file)
@@ -265,8 +265,15 @@ typedef struct mbuffer_st
   unsigned int user_mark;       /* only used during fill in */
   size_t maximum_size;
   
-  gnutls_handshake_description_t htype;
+  /* record layer content type */
   content_type_t type;
+
+  /* Record layer epoch of message */
+  uint16_t epoch;
+
+  /* Handshake layer type and sequence of message */
+  gnutls_handshake_description_t htype;
+  uint16_t sequence;
 } mbuffer_st;
 
 typedef struct mbuffer_head_st
@@ -278,25 +285,6 @@ 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 */
@@ -568,10 +556,6 @@ typedef struct
   unsigned int retrans_timeout;
   unsigned int total_timeout;
 
-  /* Head of the next outgoing flight. */
-  dtls_hsk_retransmit_buffer *retransmit;
-  dtls_hsk_retransmit_buffer **retransmit_end;
-
   unsigned int hsk_hello_verify_requests;
 } dtls_st;
 
index ab2350e2cd99262ebdd9881fb3a53fc6b5eaf967..4ab2c09b94ed2eeb7750c9e430ae89383a7e482b 100644 (file)
@@ -405,9 +405,6 @@ gnutls_init_dtls (gnutls_session_t * session,
   (*session)->internals.dtls.hsk_mtu = DTLS_DEFAULT_MTU;
   (*session)->internals.transport = GNUTLS_DGRAM;
 
-  /* Initialize pointer used to enqueue messages for retransmit. */
-  (*session)->internals.dtls.retransmit_end = &(*session)->internals.dtls.retransmit;
-
   (*session)->internals.dtls.retrans_timeout = 1000;
   (*session)->internals.dtls.total_timeout = 4000;