[evolution-data-server] [SMTP] Add thread safety around istream/ostream
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] [SMTP] Add thread safety around istream/ostream
- Date: Tue, 11 Aug 2015 13:27:08 +0000 (UTC)
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]