[glib-networking/mcatanzaro/#20: 6/7] gnutls: account for internal TLS buffer in check function




commit 82cf7e0173868c4b747f9500faebe56324cdfebf
Author: Michael Catanzaro <mcatanzaro gnome org>
Date:   Sun Jan 26 14:33:09 2020 -0600

    gnutls: account for internal TLS buffer in check function
    
    If the GnuTLS buffer has readable data, then we must report that we are
    readable, or applications could stall forever waiting to read the data
    that is already present.
    
    Fixes #20

 tls/base/gtlsconnection-base.c     | 10 ++++++++++
 tls/base/gtlsconnection-base.h     |  3 +++
 tls/gnutls/gtlsconnection-gnutls.c | 14 ++++++++++++++
 3 files changed, 27 insertions(+)
---
diff --git a/tls/base/gtlsconnection-base.c b/tls/base/gtlsconnection-base.c
index d06a97e..896e5b9 100644
--- a/tls/base/gtlsconnection-base.c
+++ b/tls/base/gtlsconnection-base.c
@@ -921,6 +921,16 @@ g_tls_connection_base_check (GTlsConnectionBase  *tls,
       ((condition & G_IO_OUT) && (priv->writing || priv->write_closing)))
     goto out;
 
+  /* If base class says we are ready, then we are, regardless of the base
+   * stream status. This accounts for TLS-level buffers.
+   */
+  if (G_TLS_CONNECTION_BASE_GET_CLASS (tls)->check &&
+      G_TLS_CONNECTION_BASE_GET_CLASS (tls)->check (tls, condition))
+    {
+      ret = TRUE;
+      goto out;
+    }
+
   /* Defer to the base stream or GDatagramBased. */
   ret = g_tls_connection_base_base_check (tls, condition);
 
diff --git a/tls/base/gtlsconnection-base.h b/tls/base/gtlsconnection-base.h
index 45c14e5..8642502 100644
--- a/tls/base/gtlsconnection-base.h
+++ b/tls/base/gtlsconnection-base.h
@@ -79,6 +79,9 @@ struct _GTlsConnectionBaseClass
 
   gboolean                    (*is_session_resumed)         (GTlsConnectionBase   *tls);
 
+  gboolean                    (*check)                      (GTlsConnectionBase   *tls,
+                                                             GIOCondition          direction);
+
   void                        (*push_io)                    (GTlsConnectionBase   *tls,
                                                              GIOCondition          direction,
                                                              gint64                timeout,
diff --git a/tls/gnutls/gtlsconnection-gnutls.c b/tls/gnutls/gtlsconnection-gnutls.c
index 1e09957..3aab9e4 100644
--- a/tls/gnutls/gtlsconnection-gnutls.c
+++ b/tls/gnutls/gtlsconnection-gnutls.c
@@ -848,6 +848,19 @@ g_tls_connection_gnutls_is_session_resumed (GTlsConnectionBase *tls)
   return gnutls_session_is_resumed (priv->session);
 }
 
+static gboolean
+g_tls_connection_gnutls_check (GTlsConnectionBase *tls,
+                               GIOCondition        direction)
+{
+  GTlsConnectionGnutls *gnutls = G_TLS_CONNECTION_GNUTLS (tls);
+  GTlsConnectionGnutlsPrivate *priv = g_tls_connection_gnutls_get_instance_private (gnutls);
+
+  if (direction & G_IO_IN)
+    return !!gnutls_record_check_pending (priv->session);
+
+  return FALSE;
+}
+
 static GTlsConnectionBaseStatus
 g_tls_connection_gnutls_read (GTlsConnectionBase  *tls,
                               void                *buffer,
@@ -1071,6 +1084,7 @@ g_tls_connection_gnutls_class_init (GTlsConnectionGnutlsClass *klass)
   base_class->retrieve_peer_certificate                  = g_tls_connection_gnutls_retrieve_peer_certificate;
   base_class->complete_handshake                         = g_tls_connection_gnutls_complete_handshake;
   base_class->is_session_resumed                         = g_tls_connection_gnutls_is_session_resumed;
+  base_class->check                                      = g_tls_connection_gnutls_check;
   base_class->read_fn                                    = g_tls_connection_gnutls_read;
   base_class->read_message_fn                            = g_tls_connection_gnutls_read_message;
   base_class->write_fn                                   = g_tls_connection_gnutls_write;


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