[glib-networking/wip/openssl] Try to handle bio in a thread safe way



commit 38cfda55d2fd7a73caa113a7233652e6220eeedd
Author: Ignacio Casal Quinteiro <icq gnome org>
Date:   Wed Jan 20 13:40:22 2016 +0100

    Try to handle bio in a thread safe way
    
    We might want to handle more errors!

 tls/openssl/gtlsbio.c                |   74 +++++++++++++++++----------------
 tls/openssl/gtlsbio.h                |    6 ---
 tls/openssl/gtlsconnection-openssl.c |   54 +++++++++++++++++-------
 3 files changed, 76 insertions(+), 58 deletions(-)
---
diff --git a/tls/openssl/gtlsbio.c b/tls/openssl/gtlsbio.c
index dad0d75..e998673 100644
--- a/tls/openssl/gtlsbio.c
+++ b/tls/openssl/gtlsbio.c
@@ -32,8 +32,8 @@ typedef struct {
   GCancellable *write_cancellable;
   gboolean read_blocking;
   gboolean write_blocking;
-  GError **read_error;
-  GError **write_error;
+  GMutex read_mutex;
+  GMutex write_mutex;
 } GTlsBio;
 
 static void
@@ -113,17 +113,29 @@ gtls_bio_write (BIO        *bio,
                 int         inl)
 {
   GTlsBio *gbio;
+  gssize ret;
+  GError *error = NULL;
 
   if (!bio->init || in == NULL || inl == 0)
     return 0;
 
   gbio = (GTlsBio *)bio->ptr;
 
-  return g_pollable_stream_write (g_io_stream_get_output_stream (gbio->io_stream),
-                                  in, inl,
-                                  gbio->write_blocking,
-                                  gbio->write_cancellable,
-                                  gbio->write_error);
+  g_mutex_lock (&gbio->write_mutex);
+  ret = g_pollable_stream_write (g_io_stream_get_output_stream (gbio->io_stream),
+                                 in, inl,
+                                 gbio->write_blocking,
+                                 gbio->write_cancellable,
+                                 &error);
+  g_mutex_unlock (&gbio->write_mutex);
+
+  if (ret == -1)
+    {
+      ret = -error->code;
+      g_error_free (error);
+    }
+
+  return ret;
 }
 
 static int
@@ -132,17 +144,29 @@ gtls_bio_read (BIO  *bio,
                int   outl)
 {
   GTlsBio *gbio;
+  gssize ret;
+  GError *error = NULL;
 
   if (!bio->init || out == NULL || outl == 0)
     return 0;
 
   gbio = (GTlsBio *)bio->ptr;
 
-  return g_pollable_stream_read (g_io_stream_get_input_stream (gbio->io_stream),
-                                 out, outl,
-                                 gbio->read_blocking,
-                                 gbio->read_cancellable,
-                                 gbio->read_error);
+  g_mutex_lock (&gbio->read_mutex);
+  ret = g_pollable_stream_read (g_io_stream_get_input_stream (gbio->io_stream),
+                                out, outl,
+                                gbio->read_blocking,
+                                gbio->read_cancellable,
+                                &error);
+  g_mutex_unlock (&gbio->read_mutex);
+
+  if (ret == -1)
+    {
+      ret = -error->code;
+      g_error_free (error);
+    }
+
+  return ret;
 }
 
 static int
@@ -190,6 +214,8 @@ g_tls_bio_new (GIOStream *io_stream)
 
   gbio = g_new0 (GTlsBio, 1);
   gbio->io_stream = g_object_ref (io_stream);
+  g_mutex_init (&gbio->read_mutex);
+  g_mutex_init (&gbio->write_mutex);
 
   ret->ptr = gbio;
   ret->init = 1;
@@ -222,18 +248,6 @@ g_tls_bio_set_read_blocking (BIO      *bio,
 }
 
 void
-g_tls_bio_set_read_error (BIO     *bio,
-                          GError **error)
-{
-  GTlsBio *gbio;
-
-  g_return_if_fail (bio != NULL);
-
-  gbio = (GTlsBio *)bio->ptr;
-  gbio->read_error = error;
-}
-
-void
 g_tls_bio_set_write_cancellable (BIO          *bio,
                                  GCancellable *cancellable)
 {
@@ -256,15 +270,3 @@ g_tls_bio_set_write_blocking (BIO          *bio,
   gbio = (GTlsBio *)bio->ptr;
   gbio->write_blocking = blocking;
 }
-
-void
-g_tls_bio_set_write_error (BIO     *bio,
-                           GError **error)
-{
-  GTlsBio *gbio;
-
-  g_return_if_fail (bio != NULL);
-
-  gbio = (GTlsBio *)bio->ptr;
-  gbio->write_error = error;
-}
diff --git a/tls/openssl/gtlsbio.h b/tls/openssl/gtlsbio.h
index 701f5d1..1247dd7 100644
--- a/tls/openssl/gtlsbio.h
+++ b/tls/openssl/gtlsbio.h
@@ -38,18 +38,12 @@ void       g_tls_bio_set_read_cancellable  (BIO          *bio,
 void       g_tls_bio_set_read_blocking     (BIO          *bio,
                                             gboolean      blocking);
 
-void       g_tls_bio_set_read_error        (BIO          *bio,
-                                            GError      **error);
-
 void       g_tls_bio_set_write_cancellable (BIO          *bio,
                                             GCancellable *cancellable);
 
 void       g_tls_bio_set_write_blocking    (BIO          *bio,
                                             gboolean      blocking);
 
-void       g_tls_bio_set_write_error       (BIO          *bio,
-                                            GError      **error);
-
 G_END_DECLS
 
 #endif /* __G_TLS_BIO_H__ */
diff --git a/tls/openssl/gtlsconnection-openssl.c b/tls/openssl/gtlsconnection-openssl.c
index 0607f55..64cbcb5 100644
--- a/tls/openssl/gtlsconnection-openssl.c
+++ b/tls/openssl/gtlsconnection-openssl.c
@@ -163,15 +163,13 @@ end_openssl_io (GTlsConnectionOpenssl  *openssl,
   return G_TLS_CONNECTION_BASE_ERROR;
 }
 
-#define BEGIN_OPENSSL_IO(openssl, direction, blocking, cancellable, operation)        \
-  g_message("start: %s", operation); \
+#define BEGIN_OPENSSL_IO(openssl, direction, blocking, cancellable)        \
   g_tls_connection_base_push_io (G_TLS_CONNECTION_BASE (openssl),        \
                                  direction, blocking, cancellable);        \
   do {
 
-#define END_OPENSSL_IO(openssl, direction, ret, status, errmsg, err, operation)        \
+#define END_OPENSSL_IO(openssl, direction, ret, status, errmsg, err)        \
     status = end_openssl_io (openssl, direction, ret, err, errmsg, ERR_error_string (SSL_get_error (ssl, 
ret), NULL)); \
-    g_message("end: %s", operation); \
   } while (status == G_TLS_CONNECTION_BASE_TRY_AGAIN);
 
 static GTlsConnectionBaseStatus
@@ -195,10 +193,10 @@ g_tls_connection_openssl_request_rehandshake (GTlsConnectionBase  *tls,
 
   ssl = g_tls_connection_openssl_get_ssl (openssl);
 
-  BEGIN_OPENSSL_IO (openssl, G_IO_IN | G_IO_OUT, TRUE, cancellable, "request rehandshake");
+  BEGIN_OPENSSL_IO (openssl, G_IO_IN | G_IO_OUT, TRUE, cancellable);
   ret = SSL_renegotiate (ssl);
   END_OPENSSL_IO (openssl, G_IO_IN | G_IO_OUT, ret, status,
-                  _("Error performing TLS handshake: %s"), error, "request rehandshake");
+                  _("Error performing TLS handshake: %s"), error);
 
   return status;
 }
@@ -291,10 +289,10 @@ g_tls_connection_openssl_handshake (GTlsConnectionBase  *tls,
 
   ssl = g_tls_connection_openssl_get_ssl (openssl);
 
-  BEGIN_OPENSSL_IO (openssl, G_IO_IN | G_IO_OUT, TRUE, cancellable, "rehandshake");
+  BEGIN_OPENSSL_IO (openssl, G_IO_IN | G_IO_OUT, TRUE, cancellable);
   ret = SSL_do_handshake (ssl);
   END_OPENSSL_IO (openssl, G_IO_IN | G_IO_OUT, ret, status,
-                  _("Error performing TLS handshake: %s"), error, "rehandshake");
+                  _("Error performing TLS handshake: %s"), error);
 
   if (ret > 0)
     {
@@ -365,7 +363,6 @@ g_tls_connection_openssl_push_io (GTlsConnectionBase *tls,
       g_tls_bio_set_read_cancellable (priv->bio, cancellable);
       g_tls_bio_set_read_blocking (priv->bio, blocking);
       g_clear_error (&tls->read_error);
-      g_tls_bio_set_read_error (priv->bio, &tls->read_error);
     }
 
   if (direction & G_IO_OUT)
@@ -373,7 +370,6 @@ g_tls_connection_openssl_push_io (GTlsConnectionBase *tls,
       g_tls_bio_set_write_cancellable (priv->bio, cancellable);
       g_tls_bio_set_write_blocking (priv->bio, blocking);
       g_clear_error (&tls->write_error);
-      g_tls_bio_set_write_error (priv->bio, &tls->write_error);
     }
 }
 
@@ -398,6 +394,21 @@ g_tls_connection_openssl_pop_io (GTlsConnectionBase  *tls,
                                                                                       success, error);
 }
 
+static void
+convert_code_to_io_error(int      code,
+                         GError **error)
+{
+  if (code == -G_IO_ERROR_WOULD_BLOCK)
+    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
+                         "Operation would block");
+  else if (code == -G_IO_ERROR_TIMED_OUT)
+    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
+                         "Operation timed out");
+  else
+    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                         "Operation failed");
+}
+
 static GTlsConnectionBaseStatus
 g_tls_connection_openssl_read (GTlsConnectionBase    *tls,
                                void                  *buffer,
@@ -414,10 +425,13 @@ g_tls_connection_openssl_read (GTlsConnectionBase    *tls,
 
   ssl = g_tls_connection_openssl_get_ssl (openssl);
 
-  BEGIN_OPENSSL_IO (openssl, G_IO_IN, blocking, cancellable, "read");
+  BEGIN_OPENSSL_IO (openssl, G_IO_IN, blocking, cancellable);
   ret = SSL_read (ssl, buffer, count);
+  if (ret < 0) {
+    convert_code_to_io_error(ret, &tls->read_error);
+  }
   END_OPENSSL_IO (openssl, G_IO_IN, ret, status,
-                  _("Error reading data from TLS socket: %s"), error, "read");
+                  _("Error reading data from TLS socket: %s"), error);
 
   if (ret >= 0)
     *nread = ret;
@@ -440,10 +454,13 @@ g_tls_connection_openssl_write (GTlsConnectionBase    *tls,
 
   ssl = g_tls_connection_openssl_get_ssl (openssl);
 
-  BEGIN_OPENSSL_IO (openssl, G_IO_OUT, blocking, cancellable, "write");
+  BEGIN_OPENSSL_IO (openssl, G_IO_OUT, blocking, cancellable);
   ret = SSL_write (ssl, buffer, count);
+  if (ret < 0) {
+    convert_code_to_io_error(ret, &tls->write_error);
+  }
   END_OPENSSL_IO (openssl, G_IO_OUT, ret, status,
-                  _("Error writing data to TLS socket: %s"), error, "write");
+                  _("Error writing data to TLS socket: %s"), error);
 
   if (ret >= 0)
     *nwrote = ret;
@@ -466,10 +483,13 @@ g_tls_connection_openssl_close (GTlsConnectionBase  *tls,
 
   priv->shutting_down = TRUE;
 
-  BEGIN_OPENSSL_IO (openssl, G_IO_IN | G_IO_OUT, TRUE, cancellable, "close");
+  BEGIN_OPENSSL_IO (openssl, G_IO_IN | G_IO_OUT, TRUE, cancellable);
   ret = SSL_shutdown (ssl);
+  if (ret < 0) {
+    convert_code_to_io_error(ret, &tls->read_error);
+  }
   END_OPENSSL_IO (openssl, G_IO_IN | G_IO_OUT, ret, status,
-                  _("Error performing TLS close: %s"), error, "close");
+                  _("Error performing TLS close: %s"), error);
 
   return status;
 }
@@ -513,6 +533,8 @@ g_tls_connection_openssl_initable_init (GInitable     *initable,
   priv->bio = g_tls_bio_new (tls->base_io_stream);
 
   SSL_set_bio (ssl, priv->bio, priv->bio);
+  SSL_set_mode (ssl, SSL_MODE_ENABLE_PARTIAL_WRITE |
+                     SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
 
   return TRUE;
 }


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