summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Catanzaro <mcatanzaro@gnome.org>2020-01-26 14:33:09 -0600
committerMichael Catanzaro <mcatanzaro@gnome.org>2020-09-01 13:24:12 -0500
commit4dbb780f40f5b1dfb0159acb697b48e2e4acce26 (patch)
tree10d6c11a75fdb7deb0af35564c928e8ecbbb9694
parentf561e162326f3e6c3f88a28f65c0989c9e1d935b (diff)
downloadglib-networking-4dbb780f40f5b1dfb0159acb697b48e2e4acce26.tar.gz
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
-rw-r--r--tls/base/gtlsconnection-base.c10
-rw-r--r--tls/base/gtlsconnection-base.h3
-rw-r--r--tls/gnutls/gtlsconnection-gnutls.c14
3 files changed, 27 insertions, 0 deletions
diff --git a/tls/base/gtlsconnection-base.c b/tls/base/gtlsconnection-base.c
index 5d8ab2b..e184552 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;