[evolution-data-server] CamelIMAPXServer: Add a "stream" property.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] CamelIMAPXServer: Add a "stream" property.
- Date: Thu, 30 Aug 2012 21:08:55 +0000 (UTC)
commit 2449ff17a92b80bc8e9ed7a19907cfe391a7805b
Author: Matthew Barnes <mbarnes redhat com>
Date: Thu Aug 30 11:29:46 2012 -0400
CamelIMAPXServer: Add a "stream" property.
Protect the stream with a mutex and add camel_imapx_server_ref_stream().
Additionally, the stream pointer is now in the private structure, and
is explicitly passed to various parsing functions to ensure a reference
is held on the stream for the duration of a parser thread iteration.
This alters the signature of CamelIMAPUntaggedRespHandler.
I am, however, NOT changing libcamel's soname for these changes since
only evolution-kolab is affected and a soname bump at this point in the
development cycle is extremely disruptive to the rest of GNOME.
camel/camel-imapx-server.c | 467 +++++++++++++++++++++++--------
camel/camel-imapx-server.h | 12 +-
camel/camel-imapx-store.c | 15 +-
docs/reference/camel/camel-sections.txt | 1 +
4 files changed, 375 insertions(+), 120 deletions(-)
---
diff --git a/camel/camel-imapx-server.c b/camel/camel-imapx-server.c
index f006dc4..88ce604 100644
--- a/camel/camel-imapx-server.c
+++ b/camel/camel-imapx-server.c
@@ -195,20 +195,62 @@ struct _CamelIMAPXServerUntaggedContext {
};
/* internal untagged handler prototypes */
-static gboolean imapx_untagged_bye (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_capability (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_exists (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_expunge (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_fetch (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_flags (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_list (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_lsub (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_namespace (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_ok_no_bad (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_preauth (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_recent (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_status (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
-static gboolean imapx_untagged_vanished (CamelIMAPXServer *is, GCancellable *cancellable, GError **error);
+static gboolean imapx_untagged_bye (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_capability (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_exists (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_expunge (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_fetch (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_flags (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_list (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_lsub (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_namespace (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_ok_no_bad (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_preauth (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_recent (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_status (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_untagged_vanished (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
enum {
IMAPX_UNTAGGED_ID_BAD = 0,
@@ -252,6 +294,14 @@ static const CamelIMAPXUntaggedRespHandlerDesc _untagged_descr[] = {
struct _CamelIMAPXServerPrivate {
CamelIMAPXServerUntaggedContext *context;
GHashTable *untagged_handlers;
+
+ CamelIMAPXStream *stream;
+ GMutex stream_lock;
+};
+
+enum {
+ PROP_0,
+ PROP_STREAM
};
enum {
@@ -265,12 +315,19 @@ static guint signals[LAST_SIGNAL];
void imapx_uidset_init (struct _uidset_state *ss, gint total, gint limit);
gint imapx_uidset_done (struct _uidset_state *ss, struct _CamelIMAPXCommand *ic);
gint imapx_uidset_add (struct _uidset_state *ss, struct _CamelIMAPXCommand *ic, const gchar *uid);
-static gboolean imapx_command_idle_stop (CamelIMAPXServer *is, GError **error);
-static gboolean imapx_continuation (CamelIMAPXServer *is, gboolean litplus, GCancellable *cancellable, GError **error);
-static gboolean imapx_disconnect (CamelIMAPXServer *is);
-static gint imapx_uid_cmp (gconstpointer ap, gconstpointer bp, gpointer data);
-static gboolean imapx_is_command_queue_empty (CamelIMAPXServer *is);
+static gboolean imapx_command_idle_stop (CamelIMAPXServer *is,
+ GError **error);
+static gboolean imapx_continuation (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
+ gboolean litplus,
+ GCancellable *cancellable,
+ GError **error);
+static gboolean imapx_disconnect (CamelIMAPXServer *is);
+static gboolean imapx_is_command_queue_empty (CamelIMAPXServer *is);
+static gint imapx_uid_cmp (gconstpointer ap,
+ gconstpointer bp,
+ gpointer data);
/* states for the connection? */
enum {
@@ -660,10 +717,13 @@ imapx_command_start (CamelIMAPXServer *is,
GCancellable *cancellable,
GError **error)
{
+ CamelIMAPXStream *stream = NULL;
CamelIMAPXCommandPart *cp;
gboolean cp_continuation;
gboolean cp_literal_plus;
GList *head;
+ gboolean success = FALSE;
+ gchar *string;
gint retval;
camel_imapx_command_close (ic);
@@ -686,34 +746,41 @@ imapx_command_start (CamelIMAPXServer *is,
g_static_rec_mutex_lock (&is->ostream_lock);
+ stream = camel_imapx_server_ref_stream (is);
+
+ if (stream == NULL) {
+ g_set_error (
+ error, CAMEL_IMAPX_ERROR, 1,
+ "Cannot issue command, no stream available");
+ goto err;
+ }
+
c (is->tagprefix, "Starting command (active=%d,%s) %c%05u %s\r\n", camel_imapx_command_queue_get_length (is->active), is->literal?" literal":"", is->tagprefix, ic->tag, cp->data && g_str_has_prefix (cp->data, "LOGIN") ? "LOGIN..." : cp->data);
- if (is->stream != NULL) {
- gchar *string;
- string = g_strdup_printf ("%c%05u %s\r\n", is->tagprefix, ic->tag, cp->data);
- retval = camel_stream_write_string ((CamelStream *) is->stream, string, cancellable, NULL);
- g_free (string);
- } else
- retval = -1;
+ string = g_strdup_printf (
+ "%c%05u %s\r\n", is->tagprefix, ic->tag, cp->data);
+ retval = camel_stream_write_string (
+ CAMEL_STREAM (stream), string, cancellable, NULL);
+ g_free (string);
+
if (retval == -1) {
g_set_error (
error, CAMEL_IMAPX_ERROR, 1,
"Failed to issue the command");
goto err;
}
+
while (is->literal == ic && cp_literal_plus) {
/* Sent LITERAL+ continuation immediately */
- if (!imapx_continuation (is, TRUE, cancellable, error))
+ if (!imapx_continuation (is, stream, TRUE, cancellable, error))
goto err;
}
- g_static_rec_mutex_unlock (&is->ostream_lock);
+ success = TRUE;
- return TRUE;
+ goto exit;
err:
- g_static_rec_mutex_unlock (&is->ostream_lock);
-
camel_imapx_command_queue_remove (is->active, ic);
/* HACK: Since we're failing, make sure the command has a status
@@ -730,7 +797,13 @@ err:
if (ic != NULL && ic->complete != NULL)
ic->complete (is, ic, NULL);
- return FALSE;
+exit:
+ if (stream != NULL)
+ g_object_unref (stream);
+
+ g_static_rec_mutex_unlock (&is->ostream_lock);
+
+ return success;
}
static gboolean
@@ -1242,6 +1315,7 @@ invalidate_local_cache (CamelIMAPXFolder *ifolder,
static gboolean
imapx_untagged_capability (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1251,7 +1325,7 @@ imapx_untagged_capability (CamelIMAPXServer *is,
if (is->cinfo)
imapx_free_capability (is->cinfo);
- is->cinfo = imapx_parse_capability (is->stream, cancellable, error);
+ is->cinfo = imapx_parse_capability (stream, cancellable, error);
if (is->cinfo == NULL)
return FALSE;
c (is->tagprefix, "got capability flags %08x\n", is->cinfo->capa);
@@ -1260,6 +1334,7 @@ imapx_untagged_capability (CamelIMAPXServer *is,
static gboolean
imapx_untagged_expunge (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1293,6 +1368,7 @@ imapx_untagged_expunge (CamelIMAPXServer *is,
static gboolean
imapx_untagged_vanished (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1308,21 +1384,21 @@ imapx_untagged_vanished (CamelIMAPXServer *is,
/* cancellable may be NULL */
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- tok = camel_imapx_stream_token (is->stream, &token, &len, cancellable, error);
+ tok = camel_imapx_stream_token (stream, &token, &len, cancellable, error);
if (tok < 0)
return FALSE;
if (tok == '(') {
unsolicited = FALSE;
while (tok != ')') {
/* We expect this to be 'EARLIER' */
- tok = camel_imapx_stream_token (is->stream, &token, &len, cancellable, error);
+ tok = camel_imapx_stream_token (stream, &token, &len, cancellable, error);
if (tok < 0)
return FALSE;
}
} else
- camel_imapx_stream_ungettoken (is->stream, tok, token, len);
+ camel_imapx_stream_ungettoken (stream, tok, token, len);
- uids = imapx_parse_uids (is->stream, cancellable, error);
+ uids = imapx_parse_uids (stream, cancellable, error);
if (uids == NULL)
return FALSE;
@@ -1356,6 +1432,7 @@ imapx_untagged_vanished (CamelIMAPXServer *is,
static gboolean
imapx_untagged_namespace (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1367,7 +1444,7 @@ imapx_untagged_namespace (CamelIMAPXServer *is,
/* cancellable may be NULL */
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- nsl = imapx_parse_namespace_list (is->stream, cancellable, error);
+ nsl = imapx_parse_namespace_list (stream, cancellable, error);
if (nsl == NULL)
return FALSE;
@@ -1391,6 +1468,7 @@ imapx_untagged_namespace (CamelIMAPXServer *is,
static gboolean
imapx_untagged_exists (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1414,6 +1492,7 @@ imapx_untagged_exists (CamelIMAPXServer *is,
static gboolean
imapx_untagged_flags (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1423,7 +1502,7 @@ imapx_untagged_flags (CamelIMAPXServer *is,
/* cancellable may be NULL */
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- imapx_parse_flags (is->stream, &flags, NULL, cancellable, error);
+ imapx_parse_flags (stream, &flags, NULL, cancellable, error);
c (is->tagprefix, "flags: %08x\n", flags);
return TRUE;
@@ -1431,6 +1510,7 @@ imapx_untagged_flags (CamelIMAPXServer *is,
static gboolean
imapx_untagged_fetch (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1440,7 +1520,7 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
/* cancellable may be NULL */
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- finfo = imapx_parse_fetch (is->stream, cancellable, error);
+ finfo = imapx_parse_fetch (stream, cancellable, error);
if (finfo == NULL) {
imapx_free_fetch (finfo);
return FALSE;
@@ -1668,6 +1748,7 @@ imapx_untagged_fetch (CamelIMAPXServer *is,
static gboolean
imapx_untagged_lsub (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1682,6 +1763,7 @@ imapx_untagged_lsub (CamelIMAPXServer *is,
static gboolean
imapx_untagged_list (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1693,7 +1775,7 @@ imapx_untagged_list (CamelIMAPXServer *is,
/* cancellable may be NULL */
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- linfo = imapx_parse_list (is->stream, cancellable, error);
+ linfo = imapx_parse_list (stream, cancellable, error);
if (!linfo)
return TRUE;
@@ -1724,6 +1806,7 @@ imapx_untagged_list (CamelIMAPXServer *is,
static gboolean
imapx_untagged_recent (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1739,6 +1822,7 @@ imapx_untagged_recent (CamelIMAPXServer *is,
static gboolean
imapx_untagged_status (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1748,7 +1832,7 @@ imapx_untagged_status (CamelIMAPXServer *is,
/* cancellable may be NULL */
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- sinfo = imapx_parse_status_info (is->stream, cancellable, error);
+ sinfo = imapx_parse_status_info (stream, cancellable, error);
if (sinfo) {
CamelIMAPXStoreSummary *s = ((CamelIMAPXStore *) is->store)->summary;
@@ -1789,6 +1873,7 @@ imapx_untagged_status (CamelIMAPXServer *is,
static gboolean
imapx_untagged_bye (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1798,7 +1883,7 @@ imapx_untagged_bye (CamelIMAPXServer *is,
/* cancellable may be NULL */
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- if (camel_imapx_stream_text (is->stream, &token, cancellable, NULL)) {
+ if (camel_imapx_stream_text (stream, &token, cancellable, NULL)) {
c (is->tagprefix, "BYE: %s\n", token);
g_set_error (error, CAMEL_IMAPX_ERROR, 1,
"IMAP server said BYE: %s", token);
@@ -1810,6 +1895,7 @@ imapx_untagged_bye (CamelIMAPXServer *is,
static gboolean
imapx_untagged_preauth (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1826,6 +1912,7 @@ imapx_untagged_preauth (CamelIMAPXServer *is,
static gboolean
imapx_untagged_ok_no_bad (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1835,11 +1922,13 @@ imapx_untagged_ok_no_bad (CamelIMAPXServer *is,
/* TODO: validate which ones of these can happen as unsolicited responses */
/* TODO: handle bye/preauth differently */
- camel_imapx_stream_ungettoken (is->stream,
- is->priv->context->tok,
- is->priv->context->token,
- is->priv->context->len);
- is->priv->context->sinfo = imapx_parse_status (is->stream, cancellable, error);
+ camel_imapx_stream_ungettoken (
+ stream,
+ is->priv->context->tok,
+ is->priv->context->token,
+ is->priv->context->len);
+ is->priv->context->sinfo =
+ imapx_parse_status (stream, cancellable, error);
if (is->priv->context->sinfo == NULL)
return FALSE;
switch (is->priv->context->sinfo->condition) {
@@ -1899,6 +1988,7 @@ imapx_untagged_ok_no_bad (CamelIMAPXServer *is,
/* handle any untagged responses */
static gboolean
imapx_untagged (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
GCancellable *cancellable,
GError **error)
{
@@ -1929,7 +2019,7 @@ imapx_untagged (CamelIMAPXServer *is,
e (is->tagprefix, "got untagged response\n");
is->priv->context->id = 0;
is->priv->context->tok = camel_imapx_stream_token (
- is->stream,
+ stream,
&(is->priv->context->token),
&(is->priv->context->len),
cancellable, error);
@@ -1940,11 +2030,10 @@ imapx_untagged (CamelIMAPXServer *is,
is->priv->context->id = strtoul (
(gchar *) is->priv->context->token, NULL, 10);
is->priv->context->tok = camel_imapx_stream_token (
- is->stream,
+ stream,
&(is->priv->context->token),
&(is->priv->context->len),
- cancellable,
- error);
+ cancellable, error);
if (is->priv->context->tok < 0)
goto exit;
}
@@ -1977,7 +2066,7 @@ imapx_untagged (CamelIMAPXServer *is,
}
/* call the handler function */
- ok = desc->handler (is, cancellable, error);
+ ok = desc->handler (is, stream, cancellable, error);
if (!ok)
goto exit;
@@ -2000,7 +2089,7 @@ imapx_untagged (CamelIMAPXServer *is,
goto exit;
}
- ok = (camel_imapx_stream_skip (is->stream, cancellable, error) == 0);
+ ok = (camel_imapx_stream_skip (stream, cancellable, error) == 0);
exit:
g_free (is->priv->context);
is->priv->context = NULL;
@@ -2012,6 +2101,7 @@ imapx_untagged (CamelIMAPXServer *is,
* either data continuations, or auth continuation */
static gboolean
imapx_continuation (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
gboolean litplus,
GCancellable *cancellable,
GError **error)
@@ -2025,7 +2115,7 @@ imapx_continuation (CamelIMAPXServer *is,
* ohter lock here. All other writes go through
* queue-lock */
if (imapx_idle_supported (is) && imapx_in_idle (is)) {
- camel_imapx_stream_skip (is->stream, cancellable, error);
+ camel_imapx_stream_skip (stream, cancellable, error);
c (is->tagprefix, "Got continuation response for IDLE \n");
IDLE_LOCK (is->idle);
@@ -2058,7 +2148,7 @@ imapx_continuation (CamelIMAPXServer *is,
ic = is->literal;
if (!litplus) {
if (ic == NULL) {
- camel_imapx_stream_skip (is->stream, cancellable, error);
+ camel_imapx_stream_skip (stream, cancellable, error);
c (is->tagprefix, "got continuation response with no outstanding continuation requests?\n");
return TRUE;
}
@@ -2074,17 +2164,17 @@ imapx_continuation (CamelIMAPXServer *is,
switch (cp->type & CAMEL_IMAPX_COMMAND_MASK) {
case CAMEL_IMAPX_COMMAND_DATAWRAPPER:
c (is->tagprefix, "writing data wrapper to literal\n");
- camel_data_wrapper_write_to_stream_sync ((CamelDataWrapper *) cp->ob, (CamelStream *) is->stream, cancellable, NULL);
+ camel_data_wrapper_write_to_stream_sync ((CamelDataWrapper *) cp->ob, (CamelStream *) stream, cancellable, NULL);
break;
case CAMEL_IMAPX_COMMAND_STREAM:
c (is->tagprefix, "writing stream to literal\n");
- camel_stream_write_to_stream ((CamelStream *) cp->ob, (CamelStream *) is->stream, cancellable, NULL);
+ camel_stream_write_to_stream ((CamelStream *) cp->ob, (CamelStream *) stream, cancellable, NULL);
break;
case CAMEL_IMAPX_COMMAND_AUTH: {
gchar *resp;
guchar *token;
- if (camel_imapx_stream_text (is->stream, &token, cancellable, error))
+ if (camel_imapx_stream_text (stream, &token, cancellable, error))
return FALSE;
resp = camel_sasl_challenge_base64_sync (
@@ -2095,7 +2185,7 @@ imapx_continuation (CamelIMAPXServer *is,
return FALSE;
c (is->tagprefix, "got auth continuation, feeding token '%s' back to auth mech\n", resp);
- camel_stream_write ((CamelStream *) is->stream, resp, strlen (resp), cancellable, NULL);
+ camel_stream_write ((CamelStream *) stream, resp, strlen (resp), cancellable, NULL);
g_free (resp);
/* we want to keep getting called until we get a status reponse from the server
* ignore what sasl tells us */
@@ -2110,14 +2200,14 @@ imapx_continuation (CamelIMAPXServer *is,
// FIXME: errors
if (cp->ob && (file = camel_stream_fs_new_with_name (cp->ob, O_RDONLY, 0, NULL))) {
- camel_stream_write_to_stream (file, (CamelStream *) is->stream, cancellable, NULL);
+ camel_stream_write_to_stream (file, (CamelStream *) stream, cancellable, NULL);
g_object_unref (file);
} else if (cp->ob_size > 0) {
// Server is expecting data ... ummm, send it zeros? abort?
}
break; }
case CAMEL_IMAPX_COMMAND_STRING:
- camel_stream_write ((CamelStream *) is->stream, cp->ob, cp->ob_size, cancellable, NULL);
+ camel_stream_write ((CamelStream *) stream, cp->ob, cp->ob_size, cancellable, NULL);
break;
default:
/* should we just ignore? */
@@ -2129,7 +2219,7 @@ imapx_continuation (CamelIMAPXServer *is,
}
if (!litplus)
- camel_imapx_stream_skip (is->stream, cancellable, error);
+ camel_imapx_stream_skip (stream, cancellable, error);
noskip:
link = g_list_next (link);
@@ -2138,8 +2228,8 @@ noskip:
cp = (CamelIMAPXCommandPart *) link->data;
c (is->tagprefix, "next part of command \"%c%05u: %s\"\n", is->tagprefix, ic->tag, cp->data);
- camel_stream_write_string ((CamelStream *) is->stream, cp->data, cancellable, NULL);
- camel_stream_write_string ((CamelStream *) is->stream, "\r\n", cancellable, NULL);
+ camel_stream_write_string ((CamelStream *) stream, cp->data, cancellable, NULL);
+ camel_stream_write_string ((CamelStream *) stream, "\r\n", cancellable, NULL);
if (cp->type & (CAMEL_IMAPX_COMMAND_CONTINUATION | CAMEL_IMAPX_COMMAND_LITERAL_PLUS)) {
newliteral = ic;
} else {
@@ -2147,7 +2237,7 @@ noskip:
}
} else {
c (is->tagprefix, "%p: queueing continuation\n", ic);
- camel_stream_write_string ((CamelStream *) is->stream, "\r\n", cancellable, NULL);
+ camel_stream_write_string ((CamelStream *) stream, "\r\n", cancellable, NULL);
}
QUEUE_LOCK (is);
@@ -2163,6 +2253,7 @@ noskip:
/* handle a completion line */
static gboolean
imapx_completion (CamelIMAPXServer *is,
+ CamelIMAPXStream *stream,
guchar *token,
gint len,
GCancellable *cancellable,
@@ -2224,7 +2315,7 @@ imapx_completion (CamelIMAPXServer *is,
QUEUE_UNLOCK (is);
- ic->status = imapx_parse_status (is->stream, cancellable, error);
+ ic->status = imapx_parse_status (stream, cancellable, error);
if (ic->status == NULL)
return FALSE;
@@ -2245,27 +2336,45 @@ imapx_step (CamelIMAPXServer *is,
GCancellable *cancellable,
GError **error)
{
+ CamelIMAPXStream *stream;
guint len;
guchar *token;
gint tok;
+ gboolean success = FALSE;
+
+ stream = camel_imapx_server_ref_stream (is);
// poll ? wait for other stuff? loop?
- tok = camel_imapx_stream_token (is->stream, &token, &len, cancellable, error);
- if (tok < 0)
- return FALSE;
+ tok = camel_imapx_stream_token (
+ stream, &token, &len, cancellable, error);
- if (tok == '*')
- return imapx_untagged (is, cancellable, error);
- else if (tok == IMAPX_TOK_TOKEN)
- return imapx_completion (is, token, len, cancellable, error);
- else if (tok == '+')
- return imapx_continuation (is, FALSE, cancellable, error);
+ switch (tok) {
+ case IMAPX_TOK_PROTOCOL:
+ case IMAPX_TOK_ERROR:
+ /* GError is already set. */
+ break;
+ case '*':
+ success = imapx_untagged (
+ is, stream, cancellable, error);
+ break;
+ case IMAPX_TOK_TOKEN:
+ success = imapx_completion (
+ is, stream, token, len, cancellable, error);
+ break;
+ case '+':
+ success = imapx_continuation (
+ is, stream, FALSE, cancellable, error);
+ break;
+ default:
+ g_set_error (
+ error, CAMEL_IMAPX_ERROR, 1,
+ "unexpected server response:");
+ break;
+ }
- g_set_error (
- error, CAMEL_IMAPX_ERROR, 1,
- "unexpected server response:");
+ g_object_unref (stream);
- return FALSE;
+ return success;
}
/* Used to run 1 command synchronously,
@@ -2421,7 +2530,19 @@ static gboolean
imapx_command_idle_stop (CamelIMAPXServer *is,
GError **error)
{
- if (!is->stream || camel_stream_write_string ((CamelStream *) is->stream, "DONE\r\n", NULL, NULL) == -1) {
+ CamelIMAPXStream *stream;
+ gboolean success = FALSE;
+
+ stream = camel_imapx_server_ref_stream (is);
+
+ if (stream != NULL) {
+ success = (camel_stream_write_string (
+ CAMEL_STREAM (stream),
+ "DONE\r\n", NULL, NULL) != -1);
+ g_object_unref (stream);
+ }
+
+ if (!success) {
g_set_error (
error, CAMEL_IMAPX_ERROR, 1,
"Unable to issue DONE");
@@ -2430,10 +2551,9 @@ imapx_command_idle_stop (CamelIMAPXServer *is,
is->parser_quit = TRUE;
if (is->cancellable)
g_cancellable_cancel (is->cancellable);
- return FALSE;
}
- return TRUE;
+ return success;
}
static gboolean
@@ -3042,6 +3162,7 @@ connect_to_server_process (CamelIMAPXServer *is,
CamelProvider *provider;
CamelSettings *settings;
CamelStream *cmd_stream;
+ CamelStream *imapx_stream;
CamelService *service;
CamelURL url;
gint ret, i = 0;
@@ -3154,9 +3275,18 @@ connect_to_server_process (CamelIMAPXServer *is,
g_free (full_cmd);
- is->stream = (CamelIMAPXStream *) camel_imapx_stream_new (cmd_stream);
+ imapx_stream = camel_imapx_stream_new (cmd_stream);
+
g_object_unref (cmd_stream);
+
+ /* Server takes ownership of the IMAPX stream. */
+ g_mutex_lock (&is->priv->stream_lock);
+ g_warn_if_fail (is->priv->stream == NULL);
+ is->priv->stream = CAMEL_IMAPX_STREAM (imapx_stream);
is->is_process_stream = TRUE;
+ g_mutex_unlock (&is->priv->stream_lock);
+
+ g_object_notify (G_OBJECT (is), "stream");
return TRUE;
}
@@ -3169,7 +3299,8 @@ imapx_connect_to_server (CamelIMAPXServer *is,
{
CamelNetworkSettings *network_settings;
CamelNetworkSecurityMethod method;
- CamelStream * tcp_stream = NULL;
+ CamelStream *tcp_stream = NULL;
+ CamelStream *imapx_stream = NULL;
CamelSockOptData sockopt;
CamelSettings *settings;
CamelService *service;
@@ -3229,21 +3360,34 @@ imapx_connect_to_server (CamelIMAPXServer *is,
goto exit;
}
- is->stream = (CamelIMAPXStream *) camel_imapx_stream_new (tcp_stream);
- g_object_unref (tcp_stream);
-
- /* Disable Nagle - we send a lot of small requests which nagle slows down */
+ /* Disable Nagle
+ * We send a lot of small requests which nagle slows down. */
sockopt.option = CAMEL_SOCKOPT_NODELAY;
sockopt.value.no_delay = TRUE;
- camel_tcp_stream_setsockopt ((CamelTcpStream *) tcp_stream, &sockopt);
+ camel_tcp_stream_setsockopt (CAMEL_TCP_STREAM (tcp_stream), &sockopt);
- /* Set keepalive - needed for some hosts/router configurations, we're idle a lot */
+ /* Set Keepalive
+ * Needed for some hosts/router configurations, we're idle a lot. */
sockopt.option = CAMEL_SOCKOPT_KEEPALIVE;
sockopt.value.keep_alive = TRUE;
- camel_tcp_stream_setsockopt ((CamelTcpStream *) tcp_stream, &sockopt);
+ camel_tcp_stream_setsockopt (CAMEL_TCP_STREAM (tcp_stream), &sockopt);
+
+ imapx_stream = camel_imapx_stream_new (tcp_stream);
+
+ /* CamelIMAPXServer takes ownership of the IMAPX stream.
+ * We need to set this right away for imapx_command_run()
+ * to work, but we delay emitting a "notify" signal until
+ * we're fully connected. */
+ g_mutex_lock (&is->priv->stream_lock);
+ g_warn_if_fail (is->priv->stream == NULL);
+ is->priv->stream = CAMEL_IMAPX_STREAM (imapx_stream);
+ g_mutex_unlock (&is->priv->stream_lock);
+
+ g_object_unref (tcp_stream);
connected:
- is->stream->tagprefix = is->tagprefix;
+ CAMEL_IMAPX_STREAM (imapx_stream)->tagprefix = is->tagprefix;
+
while (1) {
// poll ? wait for other stuff? loop?
if (camel_application_is_exiting || is->parser_quit) {
@@ -3255,21 +3399,28 @@ imapx_connect_to_server (CamelIMAPXServer *is,
goto exit;
}
- tok = camel_imapx_stream_token (is->stream, &token, &len, cancellable, error);
+ tok = camel_imapx_stream_token (
+ CAMEL_IMAPX_STREAM (imapx_stream),
+ &token, &len, cancellable, error);
if (tok < 0) {
success = FALSE;
goto exit;
}
if (tok == '*') {
- imapx_untagged (is, cancellable, error);
+ imapx_untagged (
+ is, CAMEL_IMAPX_STREAM (imapx_stream),
+ cancellable, error);
break;
}
- camel_imapx_stream_ungettoken (is->stream, tok, token, len);
- if (camel_imapx_stream_text (is->stream, &token, cancellable, error)) {
- success = FALSE;
+ camel_imapx_stream_ungettoken (
+ CAMEL_IMAPX_STREAM (imapx_stream), tok, token, len);
+
+ success = camel_imapx_stream_text (
+ CAMEL_IMAPX_STREAM (imapx_stream),
+ &token, cancellable, error);
+ if (!success)
goto exit;
- }
e (is->tagprefix, "Got unexpected line before greeting: '%s'\n", token);
g_free (token);
}
@@ -3362,16 +3513,20 @@ imapx_connect_to_server (CamelIMAPXServer *is,
}
exit:
- if (!success) {
- if (is->stream != NULL) {
- g_object_unref (is->stream);
- is->stream = NULL;
- }
+ if (success) {
+ g_object_notify (G_OBJECT (is), "stream");
+ } else {
+ g_mutex_lock (&is->priv->stream_lock);
+
+ g_object_unref (is->priv->stream);
+ is->priv->stream = NULL;
if (is->cinfo != NULL) {
imapx_free_capability (is->cinfo);
is->cinfo = NULL;
}
+
+ g_mutex_unlock (&is->priv->stream_lock);
}
g_free (host);
@@ -5763,9 +5918,16 @@ parse_contents (CamelIMAPXServer *is,
GCancellable *cancellable,
GError **error)
{
+ CamelIMAPXStream *stream;
+
+ stream = camel_imapx_server_ref_stream (is);
+ g_return_if_fail (stream != NULL);
+
while (imapx_step (is, cancellable, error))
- if (camel_imapx_stream_buffered (is->stream) == 0)
+ if (camel_imapx_stream_buffered (stream) == 0)
break;
+
+ g_object_unref (stream);
}
/*
@@ -5779,7 +5941,9 @@ static gpointer
imapx_parser_thread (gpointer d)
{
CamelIMAPXServer *is = d;
+ CamelIMAPXStream *stream;
GCancellable *cancellable;
+ gboolean have_stream;
GError *local_error = NULL;
QUEUE_LOCK (is);
@@ -5787,7 +5951,19 @@ imapx_parser_thread (gpointer d)
is->cancellable = g_object_ref (cancellable);
QUEUE_UNLOCK (is);
- while (local_error == NULL && is->stream) {
+ stream = camel_imapx_server_ref_stream (is);
+ if (stream != NULL) {
+ have_stream = TRUE;
+ g_object_unref (stream);
+ } else {
+ have_stream = FALSE;
+ }
+
+ /* FIXME This should really be a GMainLoop instead of a 'while' loop.
+ * Testing for a stream on each loop iteration is pretty hokey.
+ * Disconnecting the stream could just terminate the parser
+ * thread's main loop. */
+ while (local_error == NULL && have_stream) {
g_cancellable_reset (cancellable);
#ifndef G_OS_WIN32
@@ -5796,7 +5972,8 @@ imapx_parser_thread (gpointer d)
CamelStream *source;
gint res;
- source = camel_imapx_stream_ref_source (is->stream);
+ stream = camel_imapx_server_ref_stream (is);
+ source = camel_imapx_stream_ref_source (stream);
fds[0].fd = CAMEL_STREAM_PROCESS (source)->sockfd;
fds[0].events = G_IO_IN;
@@ -5812,6 +5989,7 @@ imapx_parser_thread (gpointer d)
g_cancellable_release_fd (cancellable);
g_object_unref (source);
+ g_object_unref (stream);
} else
#endif
{
@@ -5839,6 +6017,14 @@ imapx_parser_thread (gpointer d)
/* Jump out of the loop if an error occurred. */
if (local_error != NULL)
break;
+
+ stream = camel_imapx_server_ref_stream (is);
+ if (stream != NULL) {
+ have_stream = TRUE;
+ g_object_unref (stream);
+ } else {
+ have_stream = FALSE;
+ }
}
QUEUE_LOCK (is);
@@ -5871,6 +6057,24 @@ join_helper (gpointer thread)
}
static void
+imapx_server_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_STREAM:
+ g_value_take_object (
+ value,
+ camel_imapx_server_ref_stream (
+ CAMEL_IMAPX_SERVER (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
imapx_server_dispose (GObject *object)
{
CamelIMAPXServer *server = CAMEL_IMAPX_SERVER (object);
@@ -5914,6 +6118,8 @@ imapx_server_finalize (GObject *object)
{
CamelIMAPXServer *is = CAMEL_IMAPX_SERVER (object);
+ g_mutex_clear (&is->priv->stream_lock);
+
camel_imapx_command_queue_free (is->queue);
camel_imapx_command_queue_free (is->active);
camel_imapx_command_queue_free (is->done);
@@ -5959,13 +6165,25 @@ camel_imapx_server_class_init (CamelIMAPXServerClass *class)
g_type_class_add_private (class, sizeof (CamelIMAPXServerPrivate));
object_class = G_OBJECT_CLASS (class);
+ object_class->get_property = imapx_server_get_property;
object_class->finalize = imapx_server_finalize;
- object_class->constructed = imapx_server_constructed;
object_class->dispose = imapx_server_dispose;
+ object_class->constructed = imapx_server_constructed;
class->select_changed = NULL;
class->shutdown = NULL;
+ g_object_class_install_property (
+ object_class,
+ PROP_STREAM,
+ g_param_spec_object (
+ "stream",
+ "Stream",
+ "IMAP network stream",
+ CAMEL_TYPE_IMAPX_STREAM,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
/**
* CamelIMAPXServer::select_changed
* @server: the #CamelIMAPXServer which emitted the signal
@@ -6002,6 +6220,8 @@ camel_imapx_server_init (CamelIMAPXServer *is)
is->priv->untagged_handlers = create_initial_untagged_handler_table ();
+ g_mutex_init (&is->priv->stream_lock);
+
is->queue = camel_imapx_command_queue_new ();
is->active = camel_imapx_command_queue_new ();
is->done = camel_imapx_command_queue_new ();
@@ -6041,6 +6261,23 @@ camel_imapx_server_new (CamelStore *store)
return is;
}
+CamelIMAPXStream *
+camel_imapx_server_ref_stream (CamelIMAPXServer *server)
+{
+ CamelIMAPXStream *stream = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_IMAPX_SERVER (server), NULL);
+
+ g_mutex_lock (&server->priv->stream_lock);
+
+ if (server->priv->stream != NULL)
+ stream = g_object_ref (server->priv->stream);
+
+ g_mutex_unlock (&server->priv->stream_lock);
+
+ return stream;
+}
+
static gboolean
imapx_disconnect (CamelIMAPXServer *is)
{
@@ -6048,16 +6285,20 @@ imapx_disconnect (CamelIMAPXServer *is)
g_static_rec_mutex_lock (&is->ostream_lock);
- if (is->stream) {
- CamelStream *stream = CAMEL_STREAM (is->stream);
+ g_mutex_lock (&is->priv->stream_lock);
+
+ if (is->priv->stream != NULL) {
+ CamelStream *stream = CAMEL_STREAM (is->priv->stream);
if (camel_stream_close (stream, NULL, NULL) == -1)
ret = FALSE;
- g_object_unref (is->stream);
- is->stream = NULL;
+ g_object_unref (is->priv->stream);
+ is->priv->stream = NULL;
}
+ g_mutex_unlock (&is->priv->stream_lock);
+
/* TODO need a select lock */
if (is->select_folder) {
g_object_unref (is->select_folder);
@@ -6078,6 +6319,8 @@ imapx_disconnect (CamelIMAPXServer *is)
g_static_rec_mutex_unlock (&is->ostream_lock);
+ g_object_notify (G_OBJECT (is), "stream");
+
return ret;
}
diff --git a/camel/camel-imapx-server.h b/camel/camel-imapx-server.h
index 42d56a5..631374c 100644
--- a/camel/camel-imapx-server.h
+++ b/camel/camel-imapx-server.h
@@ -63,9 +63,12 @@ typedef struct _CamelIMAPXIdle CamelIMAPXIdle;
struct _IMAPXJobQueueInfo;
/* untagged response handling */
-typedef gboolean (*CamelIMAPXUntaggedRespHandler) (CamelIMAPXServer *server,
- GCancellable *cancellable,
- GError **error);
+typedef gboolean
+ (*CamelIMAPXUntaggedRespHandler)
+ (CamelIMAPXServer *server,
+ CamelIMAPXStream *stream,
+ GCancellable *cancellable,
+ GError **error);
/**
* CamelIMAPXUntaggedRespHandlerDesc:
@@ -105,7 +108,6 @@ struct _CamelIMAPXServer {
CamelSession *session;
/* Info about the current connection */
- CamelIMAPXStream *stream;
struct _capability_info *cinfo;
gboolean is_process_stream;
@@ -179,6 +181,8 @@ struct _CamelIMAPXServerClass {
GType camel_imapx_server_get_type (void);
CamelIMAPXServer *
camel_imapx_server_new (CamelStore *store);
+CamelIMAPXStream *
+ camel_imapx_server_ref_stream (CamelIMAPXServer *is);
gboolean camel_imapx_server_connect (CamelIMAPXServer *is,
GCancellable *cancellable,
GError **error);
diff --git a/camel/camel-imapx-store.c b/camel/camel-imapx-store.c
index 88b340a..93ba88a 100644
--- a/camel/camel-imapx-store.c
+++ b/camel/camel-imapx-store.c
@@ -265,8 +265,9 @@ imapx_query_auth_types_sync (CamelService *service,
CamelIMAPXStore *istore = CAMEL_IMAPX_STORE (service);
CamelServiceAuthType *authtype;
GList *sasl_types, *t, *next;
- gboolean connected;
CamelIMAPXServer *server;
+ CamelIMAPXStream *stream;
+ gboolean connected;
if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (istore))) {
g_set_error (
@@ -278,9 +279,15 @@ imapx_query_auth_types_sync (CamelService *service,
server = camel_imapx_server_new (CAMEL_STORE (istore));
- connected = server->stream != NULL;
- if (!connected)
- connected = imapx_connect_to_server (server, cancellable, error);
+ stream = camel_imapx_server_ref_stream (server);
+ if (stream != NULL) {
+ connected = TRUE;
+ g_object_unref (stream);
+ } else {
+ connected = imapx_connect_to_server (
+ server, cancellable, error);
+ }
+
if (!connected)
return NULL;
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index e18400a..098b94a 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -832,6 +832,7 @@ uidset_state
<TITLE>CamelIMAPXServer</TITLE>
CamelIMAPXServer
camel_imapx_server_new
+camel_imapx_server_ref_stream
camel_imapx_server_connect
camel_imapx_server_authenticate
camel_imapx_server_list
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]