[glib-networking/wip/pwithnall/dtls: 1/13] gnutls: Add support for timeouts on GnuTLS pulls



commit 0795cd14651c965659ccef33630872a53a7bc8ec
Author: Olivier CrĂȘte <olivier crete collabora com>
Date:   Fri Jul 3 12:43:45 2015 +0100

    gnutls: Add support for timeouts on GnuTLS pulls
    
    Set a gnutls_pull_timeout_func for GnuTLS to use. This is necessary for
    supporting timeouts and for DTLS.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=697908

 tls/gnutls/gtlsconnection-gnutls.c |   63 ++++++++++++++++++++++++++++++++++++
 1 files changed, 63 insertions(+), 0 deletions(-)
---
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
index e334515..5a62b4d 100644
--- a/tls/gnutls/gtlsconnection-gnutls.c
+++ b/tls/gnutls/gtlsconnection-gnutls.c
@@ -59,6 +59,10 @@ static ssize_t g_tls_connection_gnutls_pull_func (gnutls_transport_ptr_t  transp
                                                  void                   *buf,
                                                  size_t                  buflen);
 
+static int     g_tls_connection_gnutls_pull_timeout_func (gnutls_transport_ptr_t transport_data,
+                                                          unsigned int           ms);
+
+
 static void     g_tls_connection_gnutls_initable_iface_init (GInitableIface  *iface);
 static gboolean g_tls_connection_gnutls_initable_init       (GInitable       *initable,
                                                             GCancellable    *cancellable,
@@ -316,6 +320,8 @@ g_tls_connection_gnutls_initable_init (GInitable     *initable,
                                      g_tls_connection_gnutls_push_func);
   gnutls_transport_set_pull_function (gnutls->priv->session,
                                      g_tls_connection_gnutls_pull_func);
+  gnutls_transport_set_pull_timeout_function (gnutls->priv->session,
+                                              g_tls_connection_gnutls_pull_timeout_func);
   gnutls_transport_set_ptr (gnutls->priv->session, gnutls);
 
   gnutls->priv->tls_istream = g_tls_input_stream_gnutls_new (gnutls);
@@ -1142,6 +1148,63 @@ g_tls_connection_gnutls_push_func (gnutls_transport_ptr_t  transport_data,
   return ret;
 }
 
+static gboolean
+read_cb (GPollableInputStream *istream,
+         gpointer              user_data)
+{
+  gboolean *read_done = user_data;
+
+  *read_done = TRUE;
+
+  return G_SOURCE_CONTINUE;
+}
+
+static int
+g_tls_connection_gnutls_pull_timeout_func (gnutls_transport_ptr_t transport_data,
+                                           unsigned int           ms)
+{
+  GTlsConnectionGnutls *gnutls = transport_data;
+  GMainContext *ctx = NULL;
+  GSource *read_source;
+  gboolean read_done = FALSE;
+  GPollableInputStream *pollable_stream;
+
+  pollable_stream = G_POLLABLE_INPUT_STREAM (gnutls->priv->base_istream);
+
+  /* Fast path. */
+  if (g_pollable_input_stream_is_readable (pollable_stream) ||
+      g_cancellable_is_cancelled (gnutls->priv->read_cancellable))
+    return 1;
+  else if (ms == 0)
+    return 0;
+
+  /* Slow path: wait for readability. */
+  ctx = g_main_context_new ();
+
+  read_source = g_pollable_input_stream_create_source (pollable_stream,
+                                                       gnutls->priv->read_cancellable);
+  g_source_set_ready_time (read_source, g_get_monotonic_time () + ms * 1000);
+  g_source_set_callback (read_source, (GSourceFunc) read_cb,
+                         &read_done, NULL);
+  g_source_attach (read_source, ctx);
+
+  while (!read_done)
+    g_main_context_iteration (ctx, TRUE);
+
+  g_source_destroy (read_source);
+
+  g_main_context_unref (ctx);
+  g_source_unref (read_source);
+
+  /* If @read_source was dispatched due to cancellation, the resulting error
+   * will be handled in g_tls_connection_gnutls_pull_func(). */
+  if (g_pollable_input_stream_is_readable (pollable_stream) ||
+      g_cancellable_is_cancelled (gnutls->priv->read_cancellable))
+    return 1;
+
+  return 0;
+}
+
 static GTlsCertificate *
 get_peer_certificate_from_session (GTlsConnectionGnutls *gnutls)
 {


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