[evolution-data-server] [SMTP] Add thread safety around istream/ostream



commit e76c02400c5237d9adbccd24361415a5c6c8d4eb
Author: Milan Crha <mcrha redhat com>
Date:   Tue Aug 11 15:23:21 2015 +0200

    [SMTP] Add thread safety around istream/ostream
    
    It could happen that the code crashed when the message had been sending
    and the service had been disconnected meanwhile, because there was used
    the structure's stream, which was not referenced, thus it had been freed
    while still in use.

 camel/providers/smtp/camel-smtp-transport.c |  291 +++++++++++++++++---------
 camel/providers/smtp/camel-smtp-transport.h |    4 +-
 2 files changed, 193 insertions(+), 102 deletions(-)
---
diff --git a/camel/providers/smtp/camel-smtp-transport.c b/camel/providers/smtp/camel-smtp-transport.c
index 4308422..cba3c8b 100644
--- a/camel/providers/smtp/camel-smtp-transport.c
+++ b/camel/providers/smtp/camel-smtp-transport.c
@@ -67,28 +67,41 @@ enum {
 /* support prototypes */
 static GHashTable *    esmtp_get_authtypes     (const guchar *buffer);
 static gboolean                smtp_helo               (CamelSmtpTransport *transport,
+                                                CamelStreamBuffer *istream,
+                                                CamelStream *ostream,
                                                 GCancellable *cancellable,
                                                 GError **error);
 static gboolean                smtp_mail               (CamelSmtpTransport *transport,
+                                                CamelStreamBuffer *istream,
+                                                CamelStream *ostream,
                                                 const gchar *sender,
                                                 gboolean has_8bit_parts,
                                                 GCancellable *cancellable,
                                                 GError **error);
 static gboolean                smtp_rcpt               (CamelSmtpTransport *transport,
+                                                CamelStreamBuffer *istream,
+                                                CamelStream *ostream,
                                                 const gchar *recipient,
                                                 GCancellable *cancellable,
                                                 GError **error);
 static gboolean                smtp_data               (CamelSmtpTransport *transport,
+                                                CamelStreamBuffer *istream,
+                                                CamelStream *ostream,
                                                 CamelMimeMessage *message,
                                                 GCancellable *cancellable,
                                                 GError **error);
 static gboolean                smtp_rset               (CamelSmtpTransport *transport,
+                                                CamelStreamBuffer *istream,
+                                                CamelStream *ostream,
                                                 GCancellable *cancellable,
                                                 GError **error);
 static gboolean                smtp_quit               (CamelSmtpTransport *transport,
+                                                CamelStreamBuffer *istream,
+                                                CamelStream *ostream,
                                                 GCancellable *cancellable,
                                                 GError **error);
 static void            smtp_set_error          (CamelSmtpTransport *transport,
+                                                CamelStreamBuffer *istream,
                                                 const gchar *respbuf,
                                                 GCancellable *cancellable,
                                                 GError **error);
@@ -104,6 +117,44 @@ G_DEFINE_TYPE_WITH_CODE (
                CAMEL_TYPE_NETWORK_SERVICE,
                camel_network_service_init))
 
+static CamelStreamBuffer *
+smtp_ref_istream (CamelSmtpTransport *transport)
+{
+       CamelStreamBuffer *stream;
+
+       g_return_val_if_fail (CAMEL_IS_SMTP_TRANSPORT (transport), NULL);
+
+       g_mutex_lock (&transport->stream_lock);
+
+       if (transport->istream)
+               stream = g_object_ref (transport->istream);
+       else
+               stream = NULL;
+
+       g_mutex_unlock (&transport->stream_lock);
+
+       return stream;
+}
+
+static CamelStream *
+smtp_ref_ostream (CamelSmtpTransport *transport)
+{
+       CamelStream *stream;
+
+       g_return_val_if_fail (CAMEL_IS_SMTP_TRANSPORT (transport), NULL);
+
+       g_mutex_lock (&transport->stream_lock);
+
+       if (transport->ostream)
+               stream = g_object_ref (transport->ostream);
+       else
+               stream = NULL;
+
+       g_mutex_unlock (&transport->stream_lock);
+
+       return stream;
+}
+
 static gboolean
 connect_to_server (CamelService *service,
                    GCancellable *cancellable,
@@ -113,7 +164,8 @@ connect_to_server (CamelService *service,
        CamelNetworkSettings *network_settings;
        CamelNetworkSecurityMethod method;
        CamelSettings *settings;
-       CamelStream *stream;
+       CamelStream *stream, *ostream = NULL;
+       CamelStreamBuffer *istream = NULL;
        GIOStream *base_stream;
        GIOStream *tls_stream;
        gchar *respbuf = NULL;
@@ -154,17 +206,22 @@ connect_to_server (CamelService *service,
 
        transport->connected = TRUE;
 
+       g_mutex_lock (&transport->stream_lock);
+
        transport->ostream = stream;
-       transport->istream = camel_stream_buffer_new (
-               stream, CAMEL_STREAM_BUFFER_READ);
+       transport->istream = CAMEL_STREAM_BUFFER (camel_stream_buffer_new (
+               stream, CAMEL_STREAM_BUFFER_READ));
+
+       istream = g_object_ref (transport->istream);
+       ostream = g_object_ref (transport->ostream);
+
+       g_mutex_unlock (&transport->stream_lock);
 
        /* Read the greeting, note whether the server is ESMTP or not. */
        do {
                /* Check for "220" */
                g_free (respbuf);
-               respbuf = camel_stream_buffer_read_line (
-                       CAMEL_STREAM_BUFFER (transport->istream),
-                       cancellable, error);
+               respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
                d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
                if (respbuf == NULL) {
                        g_prefix_error (error, _("Welcome response error: "));
@@ -173,8 +230,7 @@ connect_to_server (CamelService *service,
                        goto exit;
                }
                if (strncmp (respbuf, "220", 3)) {
-                       smtp_set_error (
-                               transport, respbuf, cancellable, error);
+                       smtp_set_error (transport, istream, respbuf, cancellable, error);
                        g_prefix_error (error, _("Welcome response error: "));
                        g_free (respbuf);
                        success = FALSE;
@@ -185,7 +241,7 @@ connect_to_server (CamelService *service,
 
        /* Try sending EHLO */
        transport->flags |= CAMEL_SMTP_TRANSPORT_IS_ESMTP;
-       if (!smtp_helo (transport, cancellable, error)) {
+       if (!smtp_helo (transport, istream, ostream, cancellable, error)) {
                if (!transport->connected) {
                        success = FALSE;
                        goto exit;
@@ -195,7 +251,7 @@ connect_to_server (CamelService *service,
                g_clear_error (error);
                transport->flags &= ~CAMEL_SMTP_TRANSPORT_IS_ESMTP;
 
-               if (!smtp_helo (transport, cancellable, error)) {
+               if (!smtp_helo (transport, istream, ostream, cancellable, error)) {
                        success = FALSE;
                        goto exit;
                }
@@ -219,8 +275,7 @@ connect_to_server (CamelService *service,
        }
 
        d (fprintf (stderr, "[SMTP] sending: STARTTLS\r\n"));
-       if (camel_stream_write (
-               stream, "STARTTLS\r\n", 10, cancellable, error) == -1) {
+       if (camel_stream_write (ostream, "STARTTLS\r\n", 10, cancellable, error) == -1) {
                g_prefix_error (error, _("STARTTLS command failed: "));
                success = FALSE;
                goto exit;
@@ -231,9 +286,7 @@ connect_to_server (CamelService *service,
        do {
                /* Check for "220 Ready for TLS" */
                g_free (respbuf);
-               respbuf = camel_stream_buffer_read_line (
-                       CAMEL_STREAM_BUFFER (transport->istream),
-                       cancellable, error);
+               respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
                d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
                if (respbuf == NULL) {
                        g_prefix_error (error, _("STARTTLS command failed: "));
@@ -242,8 +295,7 @@ connect_to_server (CamelService *service,
                        goto exit;
                }
                if (strncmp (respbuf, "220", 3) != 0) {
-                       smtp_set_error (
-                               transport, respbuf, cancellable, error);
+                       smtp_set_error (transport, istream, respbuf, cancellable, error);
                        g_prefix_error (error, _("STARTTLS command failed: "));
                        g_free (respbuf);
                        success = FALSE;
@@ -271,7 +323,7 @@ connect_to_server (CamelService *service,
 
        /* We are supposed to re-EHLO after a successful STARTTLS to
         * re-fetch any supported extensions. */
-       if (!smtp_helo (transport, cancellable, error)) {
+       if (!smtp_helo (transport, istream, ostream, cancellable, error)) {
                success = FALSE;
        }
 
@@ -280,10 +332,18 @@ exit:
 
        if (!success) {
                transport->connected = FALSE;
+
+               g_mutex_lock (&transport->stream_lock);
+
                g_clear_object (&transport->istream);
                g_clear_object (&transport->ostream);
+
+               g_mutex_unlock (&transport->stream_lock);
        }
 
+       g_clear_object (&istream);
+       g_clear_object (&ostream);
+
        return success;
 }
 
@@ -337,6 +397,17 @@ smtp_transport_get_property (GObject *object,
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 }
 
+static void
+smtp_transport_finalize (GObject *object)
+{
+       CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (object);
+
+       g_mutex_clear (&transport->stream_lock);
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (camel_smtp_transport_parent_class)->finalize (object);
+}
+
 static gchar *
 smtp_transport_get_name (CamelService *service,
                          gboolean brief)
@@ -489,16 +560,20 @@ smtp_transport_disconnect_sync (CamelService *service,
 {
        CamelServiceClass *service_class;
        CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service);
+       CamelStreamBuffer *istream;
+       CamelStream *ostream;
 
-       /*if (!service->connected)
-        *      return TRUE;
-        */
+       istream = smtp_ref_istream (transport);
+       ostream = smtp_ref_ostream (transport);
 
-       if (transport->connected && clean) {
+       if (istream && ostream && clean) {
                /* send the QUIT command to the SMTP server */
-               smtp_quit (transport, cancellable, NULL);
+               smtp_quit (transport, istream, ostream, cancellable, NULL);
        }
 
+       g_clear_object (&istream);
+       g_clear_object (&ostream);
+
        /* Chain up to parent's disconnect() method. */
        service_class = CAMEL_SERVICE_CLASS (camel_smtp_transport_parent_class);
        if (!service_class->disconnect_sync (service, clean, cancellable, error))
@@ -510,8 +585,10 @@ smtp_transport_disconnect_sync (CamelService *service,
                transport->authtypes = NULL;
        }
 
+       g_mutex_lock (&transport->stream_lock);
        g_clear_object (&transport->istream);
        g_clear_object (&transport->ostream);
+       g_mutex_unlock (&transport->stream_lock);
        g_clear_object (&transport->local_address);
 
        transport->connected = FALSE;
@@ -528,6 +605,8 @@ smtp_transport_authenticate_sync (CamelService *service,
        CamelSmtpTransport *transport = CAMEL_SMTP_TRANSPORT (service);
        CamelAuthenticationResult result;
        CamelSasl *sasl;
+       CamelStreamBuffer *istream;
+       CamelStream *ostream;
        gchar *cmdbuf, *respbuf = NULL, *challenge;
        gboolean auth_challenge = FALSE;
        GError *local_error = NULL;
@@ -566,19 +645,25 @@ smtp_transport_authenticate_sync (CamelService *service,
                        "AUTH %s\r\n", mechanism);
        }
 
+       istream = smtp_ref_istream (transport);
+       ostream = smtp_ref_ostream (transport);
+
+       if (!istream || !ostream) {
+               g_free (cmdbuf);
+               g_set_error_literal (error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_NOT_CONNECTED,
+                       _("AUTH command failed: Not connected."));
+               goto lose;
+       }
+
        d (fprintf (stderr, "[SMTP] sending: %s", cmdbuf));
-       if (camel_stream_write_string (
-               transport->ostream, cmdbuf,
-               cancellable, error) == -1) {
+       if (camel_stream_write_string (ostream, cmdbuf, cancellable, error) == -1) {
                g_free (cmdbuf);
                g_prefix_error (error, _("AUTH command failed: "));
                goto lose;
        }
        g_free (cmdbuf);
 
-       respbuf = camel_stream_buffer_read_line (
-               CAMEL_STREAM_BUFFER (transport->istream),
-               cancellable, error);
+       respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
        d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
 
        while (!camel_sasl_get_authenticated (sasl)) {
@@ -594,8 +679,7 @@ smtp_transport_authenticate_sync (CamelService *service,
 
                /* the server challenge/response should follow a 334 code */
                if (strncmp (respbuf, "334", 3) != 0) {
-                       smtp_set_error (
-                               transport, respbuf, cancellable, error);
+                       smtp_set_error (transport, istream, respbuf, cancellable, error);
                        g_prefix_error (error, _("AUTH command failed: "));
                        goto lose;
                }
@@ -626,18 +710,14 @@ smtp_transport_authenticate_sync (CamelService *service,
                cmdbuf = g_strdup_printf ("%s\r\n", challenge);
                g_free (challenge);
                d (fprintf (stderr, "[SMTP] sending: %s", cmdbuf));
-               if (camel_stream_write_string (
-                       transport->ostream, cmdbuf,
-                       cancellable, error) == -1) {
+               if (camel_stream_write_string (ostream, cmdbuf, cancellable, error) == -1) {
                        g_free (cmdbuf);
                        goto lose;
                }
                g_free (cmdbuf);
 
                /* get the server's response */
-               respbuf = camel_stream_buffer_read_line (
-                       CAMEL_STREAM_BUFFER (transport->istream),
-                       cancellable, error);
+               respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
                d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
        }
 
@@ -656,9 +736,7 @@ smtp_transport_authenticate_sync (CamelService *service,
                /* Read the continuation, if the server returned it. */
                while (respbuf && respbuf[3] == '-') {
                        g_free (respbuf);
-                       respbuf = camel_stream_buffer_read_line (
-                               CAMEL_STREAM_BUFFER (transport->istream),
-                               cancellable, error);
+                       respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
                        d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
                }
        } else if (strncmp (respbuf, "235", 3) == 0)
@@ -677,15 +755,16 @@ smtp_transport_authenticate_sync (CamelService *service,
 break_and_lose:
        /* Get the server out of "waiting for continuation data" mode. */
        d (fprintf (stderr, "[SMTP] sending: *\n"));
-       camel_stream_write (transport->ostream, "*\r\n", 3, cancellable, NULL);
-       respbuf = camel_stream_buffer_read_line (
-               CAMEL_STREAM_BUFFER (transport->istream), cancellable, NULL);
+       camel_stream_write (ostream, "*\r\n", 3, cancellable, NULL);
+       respbuf = camel_stream_buffer_read_line (istream, cancellable, NULL);
        d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
 
 lose:
        result = CAMEL_AUTHENTICATION_ERROR;
 
 exit:
+       g_clear_object (&istream);
+       g_clear_object (&ostream);
        g_object_unref (sasl);
        g_free (respbuf);
 
@@ -740,13 +819,20 @@ smtp_transport_send_to_sync (CamelTransport *transport,
 {
        CamelSmtpTransport *smtp_transport = CAMEL_SMTP_TRANSPORT (transport);
        CamelInternetAddress *cia;
+       CamelStreamBuffer *istream;
+       CamelStream *ostream;
        gboolean has_8bit_parts;
        const gchar *addr;
        gint i, len;
 
        smtp_debug_print_server_name (CAMEL_SERVICE (transport), "Sending with");
 
-       if (!smtp_transport->connected) {
+       istream = smtp_ref_istream (smtp_transport);
+       ostream = smtp_ref_ostream (smtp_transport);
+
+       if (!smtp_transport->connected || !istream || !ostream) {
+               g_clear_object (&istream);
+               g_clear_object (&ostream);
                g_set_error (
                        error, CAMEL_SERVICE_ERROR,
                        CAMEL_SERVICE_ERROR_NOT_CONNECTED,
@@ -755,6 +841,8 @@ smtp_transport_send_to_sync (CamelTransport *transport,
        }
 
        if (!camel_internet_address_get (CAMEL_INTERNET_ADDRESS (from), 0, NULL, &addr)) {
+               g_clear_object (&istream);
+               g_clear_object (&ostream);
                g_set_error (
                        error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
                        _("Cannot send message: sender address not valid."));
@@ -768,8 +856,10 @@ smtp_transport_send_to_sync (CamelTransport *transport,
 
        /* If the connection needs a ReSET, then do so */
        if (smtp_transport->need_rset &&
-           !smtp_rset (smtp_transport, cancellable, error)) {
+           !smtp_rset (smtp_transport, istream, ostream, cancellable, error)) {
                camel_operation_pop_message (cancellable);
+               g_clear_object (&istream);
+               g_clear_object (&ostream);
                return FALSE;
        }
        smtp_transport->need_rset = FALSE;
@@ -777,8 +867,10 @@ smtp_transport_send_to_sync (CamelTransport *transport,
        /* rfc1652 (8BITMIME) requires that you notify the ESMTP daemon that
         * you'll be sending an 8bit mime message at "MAIL FROM:" time. */
        if (!smtp_mail (
-               smtp_transport, addr, has_8bit_parts, cancellable, error)) {
+               smtp_transport, istream, ostream, addr, has_8bit_parts, cancellable, error)) {
                camel_operation_pop_message (cancellable);
+               g_clear_object (&istream);
+               g_clear_object (&ostream);
                return FALSE;
        }
 
@@ -789,6 +881,8 @@ smtp_transport_send_to_sync (CamelTransport *transport,
                        _("Cannot send message: no recipients defined."));
                camel_operation_pop_message (cancellable);
                smtp_transport->need_rset = TRUE;
+               g_clear_object (&istream);
+               g_clear_object (&ostream);
                return FALSE;
        }
 
@@ -803,26 +897,34 @@ smtp_transport_send_to_sync (CamelTransport *transport,
                                "one or more invalid recipients"));
                        camel_operation_pop_message (cancellable);
                        smtp_transport->need_rset = TRUE;
+                       g_clear_object (&istream);
+                       g_clear_object (&ostream);
                        return FALSE;
                }
 
                enc = camel_internet_address_encode_address (NULL, NULL, addr);
-               if (!smtp_rcpt (smtp_transport, enc, cancellable, error)) {
+               if (!smtp_rcpt (smtp_transport, istream, ostream, enc, cancellable, error)) {
                        g_free (enc);
                        camel_operation_pop_message (cancellable);
                        smtp_transport->need_rset = TRUE;
+                       g_clear_object (&istream);
+                       g_clear_object (&ostream);
                        return FALSE;
                }
                g_free (enc);
        }
 
-       if (!smtp_data (smtp_transport, message, cancellable, error)) {
+       if (!smtp_data (smtp_transport, istream, ostream, message, cancellable, error)) {
                camel_operation_pop_message (cancellable);
                smtp_transport->need_rset = TRUE;
+               g_clear_object (&istream);
+               g_clear_object (&ostream);
                return FALSE;
        }
 
        camel_operation_pop_message (cancellable);
+       g_clear_object (&istream);
+       g_clear_object (&ostream);
 
        return TRUE;
 }
@@ -875,6 +977,7 @@ camel_smtp_transport_class_init (CamelSmtpTransportClass *class)
        object_class = G_OBJECT_CLASS (class);
        object_class->set_property = smtp_transport_set_property;
        object_class->get_property = smtp_transport_get_property;
+       object_class->finalize = smtp_transport_finalize;
 
        service_class = CAMEL_SERVICE_CLASS (class);
        service_class->settings_type = CAMEL_TYPE_SMTP_SETTINGS;
@@ -912,6 +1015,8 @@ camel_smtp_transport_init (CamelSmtpTransport *smtp)
 {
        smtp->flags = 0;
        smtp->connected = FALSE;
+
+       g_mutex_init (&smtp->stream_lock);
 }
 
 static const gchar *
@@ -1127,6 +1232,7 @@ convert_to_local (GString *str)
 
 static void
 smtp_set_error (CamelSmtpTransport *transport,
+               CamelStreamBuffer *istream,
                 const gchar *respbuf,
                 GCancellable *cancellable,
                 GError **error)
@@ -1153,9 +1259,7 @@ smtp_set_error (CamelSmtpTransport *transport,
                g_string_append (string, token);
                if (*(rbuf + 3) == '-') {
                        g_free (buffer);
-                       buffer = camel_stream_buffer_read_line (
-                               CAMEL_STREAM_BUFFER (transport->istream),
-                               cancellable, NULL);
+                       buffer = camel_stream_buffer_read_line (istream, cancellable, NULL);
                        d (fprintf (stderr, "[SMTP] received: %s\n", buffer ? buffer : "(null)"));
                        g_string_append_c (string, '\n');
                } else {
@@ -1206,6 +1310,8 @@ fake_status_code:
 
 static gboolean
 smtp_helo (CamelSmtpTransport *transport,
+          CamelStreamBuffer *istream,
+          CamelStream *ostream,
            GCancellable *cancellable,
            GError **error)
 {
@@ -1264,8 +1370,7 @@ smtp_helo (CamelSmtpTransport *transport,
        g_free (name);
 
        d (fprintf (stderr, "[SMTP] sending: %s", cmdbuf));
-       if (camel_stream_write_string (
-               transport->ostream, cmdbuf, cancellable, error) == -1) {
+       if (camel_stream_write_string (ostream, cmdbuf, cancellable, error) == -1) {
                g_free (cmdbuf);
                g_prefix_error (error, _("HELO command failed: "));
                camel_operation_pop_message (cancellable);
@@ -1277,9 +1382,7 @@ smtp_helo (CamelSmtpTransport *transport,
        do {
                /* Check for "250" */
                g_free (respbuf);
-               respbuf = camel_stream_buffer_read_line (
-                       CAMEL_STREAM_BUFFER (transport->istream),
-                       cancellable, error);
+               respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
                d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
                if (respbuf == NULL) {
                        g_prefix_error (error, _("HELO command failed: "));
@@ -1288,8 +1391,7 @@ smtp_helo (CamelSmtpTransport *transport,
                        return FALSE;
                }
                if (strncmp (respbuf, "250", 3)) {
-                       smtp_set_error (
-                               transport, respbuf, cancellable, error);
+                       smtp_set_error (transport, istream, respbuf, cancellable, error);
                        g_prefix_error (error, _("HELO command failed: "));
                        camel_operation_pop_message (cancellable);
                        g_free (respbuf);
@@ -1347,6 +1449,8 @@ smtp_helo (CamelSmtpTransport *transport,
 
 static gboolean
 smtp_mail (CamelSmtpTransport *transport,
+          CamelStreamBuffer *istream,
+          CamelStream *ostream,
            const gchar *sender,
            gboolean has_8bit_parts,
            GCancellable *cancellable,
@@ -1362,8 +1466,7 @@ smtp_mail (CamelSmtpTransport *transport,
 
        d (fprintf (stderr, "[SMTP] sending: %s", cmdbuf));
 
-       if (camel_stream_write_string (
-               transport->ostream, cmdbuf, cancellable, error) == -1) {
+       if (camel_stream_write_string (ostream, cmdbuf, cancellable, error) == -1) {
                g_free (cmdbuf);
                g_prefix_error (error, _("MAIL FROM command failed: "));
                camel_service_disconnect_sync (
@@ -1376,9 +1479,7 @@ smtp_mail (CamelSmtpTransport *transport,
        do {
                /* Check for "250 Sender OK..." */
                g_free (respbuf);
-               respbuf = camel_stream_buffer_read_line (
-                       CAMEL_STREAM_BUFFER (transport->istream),
-                       cancellable, error);
+               respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
                d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
                if (respbuf == NULL) {
                        g_prefix_error (error, _("MAIL FROM command failed: "));
@@ -1388,8 +1489,7 @@ smtp_mail (CamelSmtpTransport *transport,
                        return FALSE;
                }
                if (strncmp (respbuf, "250", 3)) {
-                       smtp_set_error (
-                               transport, respbuf, cancellable, error);
+                       smtp_set_error (transport, istream, respbuf, cancellable, error);
                        g_prefix_error (
                                error, _("MAIL FROM command failed: "));
                        g_free (respbuf);
@@ -1403,6 +1503,8 @@ smtp_mail (CamelSmtpTransport *transport,
 
 static gboolean
 smtp_rcpt (CamelSmtpTransport *transport,
+          CamelStreamBuffer *istream,
+          CamelStream *ostream,
            const gchar *recipient,
            GCancellable *cancellable,
            GError **error)
@@ -1415,8 +1517,7 @@ smtp_rcpt (CamelSmtpTransport *transport,
 
        d (fprintf (stderr, "[SMTP] sending: %s", cmdbuf));
 
-       if (camel_stream_write_string (
-               transport->ostream, cmdbuf, cancellable, error) == -1) {
+       if (camel_stream_write_string (ostream, cmdbuf, cancellable, error) == -1) {
                g_free (cmdbuf);
                g_prefix_error (error, _("RCPT TO command failed: "));
                camel_service_disconnect_sync (
@@ -1430,9 +1531,7 @@ smtp_rcpt (CamelSmtpTransport *transport,
        do {
                /* Check for "250 Recipient OK..." */
                g_free (respbuf);
-               respbuf = camel_stream_buffer_read_line (
-                       CAMEL_STREAM_BUFFER (transport->istream),
-                       cancellable, error);
+               respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
                d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
                if (respbuf == NULL) {
                        g_prefix_error (
@@ -1443,8 +1542,7 @@ smtp_rcpt (CamelSmtpTransport *transport,
                        return FALSE;
                }
                if (strncmp (respbuf, "250", 3)) {
-                       smtp_set_error (
-                               transport, respbuf, cancellable, error);
+                       smtp_set_error (transport, istream, respbuf, cancellable, error);
                        g_prefix_error (
                                error, _("RCPT TO <%s> failed: "), recipient);
                        g_free (respbuf);
@@ -1487,6 +1585,8 @@ smtp_maybe_update_socket_timeout (CamelStream *strm,
 
 static gboolean
 smtp_data (CamelSmtpTransport *transport,
+          CamelStreamBuffer *istream,
+          CamelStream *ostream,
            CamelMimeMessage *message,
            GCancellable *cancellable,
            GError **error)
@@ -1514,8 +1614,7 @@ smtp_data (CamelSmtpTransport *transport,
 
        d (fprintf (stderr, "[SMTP] sending: %s", cmdbuf));
 
-       if (camel_stream_write_string (
-               transport->ostream, cmdbuf, cancellable, error) == -1) {
+       if (camel_stream_write_string (ostream, cmdbuf, cancellable, error) == -1) {
                g_free (cmdbuf);
                g_prefix_error (error, _("DATA command failed: "));
                camel_service_disconnect_sync (
@@ -1525,8 +1624,7 @@ smtp_data (CamelSmtpTransport *transport,
        }
        g_free (cmdbuf);
 
-       respbuf = camel_stream_buffer_read_line (
-               CAMEL_STREAM_BUFFER (transport->istream), cancellable, error);
+       respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
        d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
        if (respbuf == NULL) {
                g_prefix_error (error, _("DATA command failed: "));
@@ -1539,7 +1637,7 @@ smtp_data (CamelSmtpTransport *transport,
                /* We should have gotten instructions on how to use the DATA
                 * command: 354 Enter mail, end with "." on a line by itself
                 */
-               smtp_set_error (transport, respbuf, cancellable, error);
+               smtp_set_error (transport, istream, respbuf, cancellable, error);
                g_prefix_error (error, _("DATA command failed: "));
                g_free (respbuf);
                return FALSE;
@@ -1574,9 +1672,9 @@ smtp_data (CamelSmtpTransport *transport,
                CAMEL_STREAM (null), NULL, NULL);
 
        /* Set the upload timeout to an equal of 512 bytes per second */
-       smtp_maybe_update_socket_timeout (transport->ostream, null->written / 512);
+       smtp_maybe_update_socket_timeout (ostream, null->written / 512);
 
-       filtered_stream = camel_stream_filter_new (transport->ostream);
+       filtered_stream = camel_stream_filter_new (ostream);
 
        /* setup progress reporting for message sending... */
        filter = camel_mime_filter_progress_new (cancellable, null->written);
@@ -1619,9 +1717,7 @@ smtp_data (CamelSmtpTransport *transport,
 
        d (fprintf (stderr, "[SMTP] sending: \\r\\n.\\r\\n\n"));
 
-       if (camel_stream_write (
-               transport->ostream, "\r\n.\r\n", 5,
-               cancellable, error) == -1) {
+       if (camel_stream_write (ostream, "\r\n.\r\n", 5, cancellable, error) == -1) {
                g_prefix_error (error, _("DATA command failed: "));
                camel_service_disconnect_sync (
                        CAMEL_SERVICE (transport),
@@ -1632,9 +1728,7 @@ smtp_data (CamelSmtpTransport *transport,
        do {
                /* Check for "250 Sender OK..." */
                g_free (respbuf);
-               respbuf = camel_stream_buffer_read_line (
-                       CAMEL_STREAM_BUFFER (transport->istream),
-                       cancellable, error);
+               respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
                d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
                if (respbuf == NULL) {
                        g_prefix_error (error, _("DATA command failed: "));
@@ -1644,8 +1738,7 @@ smtp_data (CamelSmtpTransport *transport,
                        return FALSE;
                }
                if (strncmp (respbuf, "250", 3) != 0) {
-                       smtp_set_error (
-                               transport, respbuf, cancellable, error);
+                       smtp_set_error (transport, istream, respbuf, cancellable, error);
                        g_prefix_error (error, _("DATA command failed: "));
                        g_free (respbuf);
                        return FALSE;
@@ -1658,6 +1751,8 @@ smtp_data (CamelSmtpTransport *transport,
 
 static gboolean
 smtp_rset (CamelSmtpTransport *transport,
+          CamelStreamBuffer *istream,
+          CamelStream *ostream,
            GCancellable *cancellable,
            GError **error)
 {
@@ -1668,8 +1763,7 @@ smtp_rset (CamelSmtpTransport *transport,
 
        d (fprintf (stderr, "[SMTP] sending: %s", cmdbuf));
 
-       if (camel_stream_write_string (
-               transport->ostream, cmdbuf, cancellable, error) == -1) {
+       if (camel_stream_write_string (ostream, cmdbuf, cancellable, error) == -1) {
                g_free (cmdbuf);
                g_prefix_error (error, _("RSET command failed: "));
                camel_service_disconnect_sync (
@@ -1682,9 +1776,7 @@ smtp_rset (CamelSmtpTransport *transport,
        do {
                /* Check for "250" */
                g_free (respbuf);
-               respbuf = camel_stream_buffer_read_line (
-                       CAMEL_STREAM_BUFFER (transport->istream),
-                       cancellable, error);
+               respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
                d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
                if (respbuf == NULL) {
                        g_prefix_error (error, _("RSET command failed: "));
@@ -1694,8 +1786,7 @@ smtp_rset (CamelSmtpTransport *transport,
                        return FALSE;
                }
                if (strncmp (respbuf, "250", 3) != 0) {
-                       smtp_set_error (
-                               transport, respbuf, cancellable, error);
+                       smtp_set_error (transport, istream, respbuf, cancellable, error);
                        g_prefix_error (error, _("RSET command failed: "));
                        g_free (respbuf);
                        return FALSE;
@@ -1708,6 +1799,8 @@ smtp_rset (CamelSmtpTransport *transport,
 
 static gboolean
 smtp_quit (CamelSmtpTransport *transport,
+          CamelStreamBuffer *istream,
+          CamelStream *ostream,
            GCancellable *cancellable,
            GError **error)
 {
@@ -1718,8 +1811,7 @@ smtp_quit (CamelSmtpTransport *transport,
 
        d (fprintf (stderr, "[SMTP] sending: %s", cmdbuf));
 
-       if (camel_stream_write_string (
-               transport->ostream, cmdbuf, cancellable, error) == -1) {
+       if (camel_stream_write_string (ostream, cmdbuf, cancellable, error) == -1) {
                g_free (cmdbuf);
                g_prefix_error (error, _("QUIT command failed: "));
                return FALSE;
@@ -1729,9 +1821,7 @@ smtp_quit (CamelSmtpTransport *transport,
        do {
                /* Check for "221" */
                g_free (respbuf);
-               respbuf = camel_stream_buffer_read_line (
-                       CAMEL_STREAM_BUFFER (transport->istream),
-                       cancellable, error);
+               respbuf = camel_stream_buffer_read_line (istream, cancellable, error);
 
                d (fprintf (stderr, "[SMTP] received: %s\n", respbuf ? respbuf : "(null)"));
                if (respbuf == NULL) {
@@ -1740,8 +1830,7 @@ smtp_quit (CamelSmtpTransport *transport,
                        return FALSE;
                }
                if (strncmp (respbuf, "221", 3) != 0) {
-                       smtp_set_error (
-                               transport, respbuf, cancellable, error);
+                       smtp_set_error (transport, istream, respbuf, cancellable, error);
                        g_prefix_error (error, _("QUIT command failed: "));
                        g_free (respbuf);
                        return FALSE;
diff --git a/camel/providers/smtp/camel-smtp-transport.h b/camel/providers/smtp/camel-smtp-transport.h
index 5d14962..c5a20de 100644
--- a/camel/providers/smtp/camel-smtp-transport.h
+++ b/camel/providers/smtp/camel-smtp-transport.h
@@ -50,7 +50,9 @@ typedef struct _CamelSmtpTransportClass CamelSmtpTransportClass;
 struct _CamelSmtpTransport {
        CamelTransport parent;
 
-       CamelStream *istream, *ostream;
+       GMutex stream_lock;
+       CamelStreamBuffer *istream;
+       CamelStream *ostream;
        GSocketAddress *local_address;
 
        guint32 flags;


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