[glib-networking/wip/pwithnall/dtls: 68/74] gnutls: Implement a vectored push callback function for GnuTLS



commit 2d653212f1c7d964fc0c4cc1de65629bda71f9d4
Author: Philip Withnall <philip withnall collabora co uk>
Date:   Fri Jul 3 18:50:29 2015 +0100

    gnutls: Implement a vectored push callback function for GnuTLS
    
    If operating in DTLS mode, this allows GnuTLS to do vectored writes to
    the base GDatagramBased, which should improve performance a little.
    
    This is not *required* for DTLS support, as the normal non-vectored push
    function also works. It is not implemented for normal TLS as
    GOutputStream does not support vectored I/O.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=697908

 tls/gnutls/gtlsconnection-gnutls.c |   67 ++++++++++++++++++++++++++++++++++++
 1 files changed, 67 insertions(+), 0 deletions(-)
---
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
index 30c0eec..4ec41cd 100644
--- a/tls/gnutls/gtlsconnection-gnutls.c
+++ b/tls/gnutls/gtlsconnection-gnutls.c
@@ -87,6 +87,9 @@
 static ssize_t g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t  transport_data,
                                                  const void             *buf,
                                                  size_t                  buflen);
+static ssize_t g_tls_connection_gnutls_vec_push_func (gnutls_transport_ptr_t  transport_data,
+                                                      const giovec_t         *iov,
+                                                      int                     iovcnt);
 static ssize_t g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t  transport_data,
                                                  void                   *buf,
                                                  size_t                  buflen);
@@ -381,6 +384,13 @@ g_tls_connection_gnutls_initable_init (GInitable     *initable,
                                               g_tls_connection_gnutls_pull_timeout_func);
   gnutls_transport_set_ptr (gnutls->priv->session, gnutls);
 
+  /* GDatagramBased supports vectored I/O; GPollableOutputStream does not. */
+  if (gnutls->priv->base_socket != NULL)
+    {
+      gnutls_transport_set_vec_push_function (gnutls->priv->session,
+                                              g_tls_connection_gnutls_vec_push_func);
+    }
+
   /* Create output streams if operating in streaming mode. */
   if (!(flags & GNUTLS_DATAGRAM))
     {
@@ -1419,6 +1429,63 @@ g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t  transport_data,
   return ret;
 }
 
+static ssize_t
+g_tls_connection_gnutls_vec_push_func (gnutls_transport_ptr_t  transport_data,
+                                       const giovec_t         *iov,
+                                       int                     iovcnt)
+{
+  GTlsConnectionGnutls *gnutls = transport_data;
+  ssize_t ret;
+  GOutputMessage message = { NULL, };
+  GOutputVector *vectors;
+
+  /* This function should only be set if we’re using base_socket. */
+  g_assert (gnutls->priv->base_socket != NULL);
+
+  /* See comment in pull_func. */
+  g_clear_error (&gnutls->priv->write_error);
+
+  /* this entire expression will be evaluated at compile time */
+  if (sizeof *iov == sizeof *vectors &&
+      sizeof iov->iov_base == sizeof vectors->buffer &&
+      G_STRUCT_OFFSET (giovec_t, iov_base) ==
+      G_STRUCT_OFFSET (GOutputVector, buffer) &&
+      sizeof iov->iov_len == sizeof vectors->size &&
+      G_STRUCT_OFFSET (giovec_t, iov_len) ==
+      G_STRUCT_OFFSET (GOutputVector, size))
+    /* ABI is compatible */
+    {
+      message.vectors = (GOutputVector *) iov;
+      message.num_vectors = iovcnt;
+    }
+  else
+    /* ABI is incompatible */
+    {
+      gint i;
+
+      message.vectors = g_newa (GOutputVector, iovcnt);
+      for (i = 0; i < iovcnt; i++)
+        {
+          message.vectors[i].buffer = (void *) iov[i].iov_base;
+          message.vectors[i].size = iov[i].iov_len;
+        }
+      message.num_vectors = iovcnt;
+    }
+
+  ret = g_datagram_based_send_messages (gnutls->priv->base_socket,
+                                        &message, 1, 0,
+                                        gnutls->priv->write_blocking,
+                                        gnutls->priv->write_cancellable,
+                                        &gnutls->priv->write_error);
+
+  if (ret > 0)
+    ret = message.bytes_sent;
+  else if (ret < 0)
+    set_gnutls_error (gnutls, gnutls->priv->write_error);
+
+  return ret;
+}
+
 static gboolean
 read_pollable_cb (GPollableInputStream *istream,
                   gpointer user_data)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]