Re: [Evolution-hackers] Let the porting begin



On Thu, 2007-10-25 at 22:25 -0400, Jeffrey Stedfast wrote:
> On Fri, 2007-10-26 at 03:25 +0200, Philip Van Hoof wrote:
> > On Wed, 2007-10-24 at 11:58 -0400, Jeffrey Stedfast wrote:
> > > I took a look at the IDLE implementation last night and felt it went
> > > about it the wrong way.
> > 
> > Yes, you are right. I think the right fix is to create a new API called
> > camel_tcp_stream_wait that works like this:
> > 
> > 
> > int bytes = camel_tcp_stream_wait (tcp_stream, stop_fd,
> > 	 store->idle_sleep, line_buffer, 1023);
> [snip]
> 
> I was thinking more along the lines of making the idle_loop use
> PRPoll()/poll() itself - it already has to figure out what type of fd to
> create for the cancel_idle_fd anyway.

I have it more or less working, with one more problem remaining (and I
already tried fixing it, check the "line_buffer" stuff in this patch)
being that the read returns me a block of bytes, not lines.

Yet I need to feed the rest of the current IDLE handling code exact
lines (untagged lines that start with '*').

So my plan is to use strrchr(buffer, '\n') and with the result calculate
where the last full line was. Then add that to what we stored last time.
And store the remainder in a buffer for the next loop.

Then with the two pieces together, strtok_r on \n and get the full lines
ouf of that.

I already started this, but I'm going to sleep now :)

Attached ... (it's again on Tinymail's trunk, not on Camel upstream)

> > Afaics It's not true that you don't need to change any API:
> > 
> > The camel_stream_read() will block until all n bytes are read.
> 
> no it doesn't. it returns as soon as any number of bytes are read or an
> error occurs.
> 
> >  This is
> > something you don't know during IDLE (how many bytes you can expect to
> > receive), and on top of that you want to continue immediately after
> > select returns, not keep retrying until you have n bytes (to simulate a
> > blocking read).
> 
> sure, but that's why you poll yourself. once the socket has data, /then/
> you call camel_stream_read() on it.
> 
> >  You also want a dedicated stop fildescriptor, not the
> > standard cancel_fd as then any cancel will interfere with this (while
> > you want strict control over this to let other threads start and stop
> > IDLE).
> 
> right, but if you add a CamelStream API, then you have to add 1 for unix
> fds and 1 for PRFileDesc
> 
> plus it keeps the code simpler (keeps all read() logic in the
> camel_stream_read() implementations rather than duplicating it).
> 
> 
> This actually brings me to another thought I've had for a few years now
> but haven't bothered pushing for it... but it might be best if all of
> the sockets used PRFileDesc rather than unix fd for raw sockets and
> PRFileDesc for SSL sockets. If this is done, I think it'd be possible to
> get rid of CamelTcpStreamRaw and move the implementation into
> CamelTcpStream and make CamelTcpStreamSSL a simple subclass of
> CamelTcpStream, replacing the CamelTcpStream's PRFileDesc with an
> SSL-wrapped fd as appropriate and calling parent_class->read/write/etc
> instead of implementing them all itself /again/.
> 
> 
> Jeff
> 
> 
-- 
Philip Van Hoof, software developer
home: me at pvanhoof dot be 
gnome: pvanhoof at gnome dot org 
http://www.pvanhoof.be/blog



Index: libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c
===================================================================
--- libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c	(revision 2884)
+++ libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c	(working copy)
@@ -197,46 +197,31 @@
 static void 
 let_idle_die (CamelImapStore *store, gboolean connect_buz)
 {
-
-	idle_debug ("let_idle_die starts\n");
-
-	g_static_rec_mutex_lock (store->idle_prefix_lock);
 	g_static_rec_mutex_lock (store->idle_lock);
 
-	store->idle_kill = TRUE;
-	store->idle_cont = FALSE;
-
-	if (store->idle_prefix)
+	idle_debug ("let_idle_die starts\n");
+	if (store->in_idle && store->idle_thread) 
 	{
-		gchar *resp = NULL;
-		int nwritten = 0;
-		CamelException ex = CAMEL_EXCEPTION_INITIALISER;
+		IdleResponse *idle_resp;
+		store->idle_cont = FALSE;
+		if (store->current_idle)
+			camel_operation_cancel (store->current_idle);
+		idle_resp = g_thread_join (store->idle_thread);
+		if (store->current_idle)
+			camel_operation_uncancel (store->current_idle);
 
-		idle_debug ("Sending DONE in let_idle_die\n");
-		CAMEL_SERVICE_REC_LOCK (store, connect_lock);
-		nwritten = camel_stream_printf (store->ostream, "DONE\r\n");
 		store->in_idle = FALSE;
-		if (nwritten != -1) {
-			resp = NULL;
-			while ((camel_imap_command_response_idle (store, &resp, &ex)) == CAMEL_IMAP_RESPONSE_UNTAGGED) {
-				idle_debug ("(.., ..) <- %s | in let_idle_die\n", resp); 
-				g_free (resp); resp=NULL; 
-			}
-			if (resp) {
-				idle_debug ("(.., ..) <- %s\n", resp);
-				g_free (resp);
-			}
-		}
-		CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
-		g_free (store->idle_prefix); 
-		store->idle_prefix=NULL;
+		store->idle_thread = NULL;
+		if (store->idle_prefix)
+			g_free (store->idle_prefix);
+		store->idle_prefix = NULL;
+		if (idle_resp)
+			idle_response_free (idle_resp);
 	}
+	idle_debug ("let_idle_die finished\n");
 
 	g_static_rec_mutex_unlock (store->idle_lock);
-	g_static_rec_mutex_unlock (store->idle_prefix_lock);
 
-	idle_debug ("let_idle_die finished\n");
-
 	return;
 }
 
@@ -245,41 +230,8 @@
 {
 	if (store->current_folder && CAMEL_IS_IMAP_FOLDER (store->current_folder))
 		camel_imap_folder_stop_idle (store->current_folder);
-	else {
-		g_static_rec_mutex_lock (store->idle_prefix_lock);
-		g_static_rec_mutex_lock (store->idle_lock);
-
-		store->idle_kill = TRUE;
-		store->idle_cont = FALSE;
-
-		if (store->idle_prefix) {
-			gchar *resp = NULL;
-			int nwritten = 0;
-			CamelException ex = CAMEL_EXCEPTION_INITIALISER;
-
-			idle_debug ("Sending DONE in camel_imap_store_stop_idle\n");
-			CAMEL_SERVICE_REC_LOCK (store, connect_lock);
-			nwritten = camel_stream_printf (store->ostream, "DONE\r\n");
-			store->in_idle = FALSE;
-			if (nwritten != -1) {
-				resp = NULL;
-				while ((camel_imap_command_response_idle (store, &resp, &ex)) == CAMEL_IMAP_RESPONSE_UNTAGGED) {
-					idle_debug ("(.., ..) <- %s | in idle_deal_with_stuff (no current folder?)\n", resp); 
-					g_free (resp); resp=NULL; 
-				}
-				if (resp) {
-					idle_debug ("(.., ..) <- %s\n", resp);
-					g_free (resp);
-				}
-			}
-			CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
-			g_free (store->idle_prefix);
-			store->idle_prefix = NULL;
-		}
-
-		g_static_rec_mutex_unlock (store->idle_lock);
-		g_static_rec_mutex_unlock (store->idle_prefix_lock);
-	}
+	else
+		let_idle_die (store, FALSE);
 }
 
 
@@ -403,10 +355,6 @@
 		disco->diary = NULL;
 	}
 
-	/* g_static_rec_mutex_free (imap_store->idle_prefix_lock); */
-	g_free (imap_store->idle_prefix_lock);
-	imap_store->idle_prefix_lock = NULL;
-
 	/* g_static_rec_mutex_free (imap_store->idle_lock); */
 	g_free (imap_store->idle_lock);
 	imap_store->idle_lock = NULL;
@@ -415,6 +363,9 @@
 	g_free (imap_store->sum_lock);
 	imap_store->sum_lock = NULL;
 
+	if (imap_store->current_idle)
+		camel_operation_unref (imap_store->current_idle);
+
 }
 
 static void
@@ -422,11 +373,10 @@
 {
 	CamelImapStore *imap_store = CAMEL_IMAP_STORE (object);
 
+	imap_store->current_idle = NULL;
 	imap_store->got_online = FALSE;
 	imap_store->going_online = FALSE;
 	imap_store->courier_crap = FALSE;
-	imap_store->idle_prefix_lock = g_new0 (GStaticRecMutex, 1);
-	g_static_rec_mutex_init (imap_store->idle_prefix_lock);
 
 	imap_store->idle_lock = g_new0 (GStaticRecMutex, 1);
 	g_static_rec_mutex_init (imap_store->idle_lock);
@@ -4078,191 +4028,3 @@
 	return nread;
 }
 
-
-
-/* FIXME: please god, when will the hurting stop? Thus function is so
-   fucking broken it's not even funny. */
-ssize_t
-camel_imap_store_readline_idle (CamelImapStore *store, char **dest, CamelException *ex)
-{
-	CamelStreamBuffer *stream;
-	char linebuf[1024] = {0};
-	GByteArray *ba;
-	ssize_t nread;
-	
-	g_return_val_if_fail (CAMEL_IS_IMAP_STORE (store), -1);
-	g_return_val_if_fail (dest, -1);
-	
-	*dest = NULL;
-	
-	/* Check for connectedness. Failed (or cancelled) operations will
-	 * close the connection. We can't expect a read to have any
-	 * meaning if we reconnect, so always set an exception.
-	 */
-
-	if (!camel_disco_store_check_online((CamelDiscoStore *)store, ex))
-		return -1;
-
-	camel_imap_store_restore_stream_buffer (store);
-	stream = CAMEL_STREAM_BUFFER (store->istream);
-
-	ba = g_byte_array_new ();
-	while ((nread = camel_stream_buffer_gets_idle (stream, linebuf, sizeof (linebuf))) > 0) {
-		g_byte_array_append (ba, (const guchar*) linebuf, nread);
-		if (linebuf[nread - 1] == '\n')
-			break;
-	}
-
-	if (nread <= 0) {
-		if (errno == EINTR)
-		{
-			CamelException mex = CAMEL_EXCEPTION_INITIALISER;
-			camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
-			camel_imap_recon (store, &mex);
-			imap_debug ("Recon in idle: %s\n", camel_exception_get_description (&mex));
-		} else {
-			camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
-					      _("Server unexpectedly disconnected: %s"),
-					      g_strerror (errno));
-			camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
-		}
-
-		g_byte_array_free (ba, TRUE);
-		return -1;
-	}
-	
-	if (camel_verbose_debug) {
-		fprintf (stderr, "received: ");
-		fwrite (ba->data, 1, ba->len, stderr);
-	}
-	
-	/* camel-imap-command.c:imap_read_untagged expects the CRLFs
-           to be stripped off and be nul-terminated *sigh* */
-	nread = ba->len - 1;
-	ba->data[nread] = '\0';
-	if (ba->data[nread - 1] == '\r') {
-		ba->data[nread - 1] = '\0';
-		nread--;
-	}
-	
-	*dest = (char *) ba->data;
-	g_byte_array_free (ba, FALSE);
-	
-	return nread;
-}
-
-ssize_t
-camel_imap_store_readline_nl (CamelImapStore *store, char **dest, CamelException *ex)
-{
-	CamelStreamBuffer *stream;
-	char linebuf[1024] = {0};
-	GByteArray *ba;
-	ssize_t nread;
-	
-	g_return_val_if_fail (CAMEL_IS_IMAP_STORE (store), -1);
-	g_return_val_if_fail (dest, -1);
-	
-	*dest = NULL;
-	
-	/* Check for connectedness. Failed (or cancelled) operations will
-	 * close the connection. We can't expect a read to have any
-	 * meaning if we reconnect, so always set an exception.
-	 */
-
-	if (!camel_disco_store_check_online((CamelDiscoStore *)store, ex))
-		return -1;
-
-	camel_imap_store_restore_stream_buffer (store);
-
-	if (!store->istream)
-		return -1;
-
-	stream = CAMEL_STREAM_BUFFER (store->istream);
-
-	ba = g_byte_array_new ();
-	while ((nread = camel_stream_buffer_gets (stream, linebuf, sizeof (linebuf))) > 0) {
-		g_byte_array_append (ba, (const guchar*) linebuf, nread);
-		if (linebuf[nread - 1] == '\n')
-			break;
-	}
-
-	if (nread <= 0) {
-		if (errno == EINTR)
-		{
-			CamelException mex = CAMEL_EXCEPTION_INITIALISER;
-			camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled"));
-			camel_imap_recon (store, &mex);
-			imap_debug ("Recon in nl: %s\n", camel_exception_get_description (&mex));
-		} else {
-			camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
-					      _("Server unexpectedly disconnected: %s"),
-					      g_strerror (errno));
-			camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
-		}
-
-		g_byte_array_free (ba, TRUE);
-		return -1;
-	}
-	
-	if (camel_verbose_debug) {
-		fprintf (stderr, "received: ");
-		fwrite (ba->data, 1, ba->len, stderr);
-	}
-	
-	/* camel-imap-command.c:imap_read_untagged expects the CRLFs
-           to be stripped off and be nul-terminated *sigh* */
-	nread = ba->len - 1;
-	ba->data[nread] = '\0';
-	if (ba->data[nread - 1] == '\r') {
-		ba->data[nread - 1] = '\0';
-		nread--;
-	}
-	
-	*dest = (char *) ba->data;
-	g_byte_array_free (ba, FALSE);
-	
-	return nread;
-}
-
-ssize_t
-camel_imap_store_readline_nb (CamelImapStore *store, char **dest, CamelException *ex)
-{
-	CamelStreamBuffer *stream;
-	char linebuf[1024] = {0};
-	GByteArray *ba;
-	ssize_t nread;
-	
-	g_return_val_if_fail (CAMEL_IS_IMAP_STORE (store), -1);
-	g_return_val_if_fail (dest, -1);
-
-	*dest = NULL;
-
-	if (store->istream == NULL || ((CamelObject *)store->istream)->ref_count <= 0)
-		return -1;
-
-	stream = CAMEL_STREAM_BUFFER (store->istream);
-	ba = g_byte_array_new ();
-	while ((nread = camel_tcp_stream_buffer_gets_nb (stream, linebuf, sizeof (linebuf))) > 0) 
-	{
-		g_byte_array_append (ba, (const guchar*) linebuf, nread);
-		if (linebuf[nread - 1] == '\n')
-			break;
-	}
-
-	if (nread <= 0) {
-		g_byte_array_free (ba, TRUE);
-		return -1;
-	}
-
-	nread = ba->len - 1;
-	ba->data[nread] = '\0';
-	if (ba->data[nread - 1] == '\r') {
-		ba->data[nread - 1] = '\0';
-		nread--;
-	}
-	
-	*dest = (char *) ba->data;
-	g_byte_array_free (ba, FALSE);
-	
-	return nread;
-}
Index: libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.h
===================================================================
--- libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.h	(revision 2882)
+++ libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.h	(working copy)
@@ -52,6 +52,18 @@
 
 G_BEGIN_DECLS
 
+typedef struct {
+	guint32 exists;
+	guint32 recent;
+	GArray *expunged;
+	GList *vanished;
+	GPtrArray *fetch;
+	gboolean exists_happened;
+	CamelFolder *folder;
+} IdleResponse;
+
+void idle_response_free (IdleResponse *idle_resp);
+
 typedef struct _CamelImapMsg CamelImapMsg;
 
 struct _CamelImapMsg {
@@ -151,7 +163,8 @@
 	char tag_prefix;
 	guint32 command;
 	CamelFolder *current_folder, *last_folder, *old_folder;
-	
+	CamelOperation *current_idle;
+
 	/* Information about the server */
 	CamelImapServerLevel server_level;
 	guint32 capabilities, parameters;
@@ -163,9 +176,9 @@
 	gchar *idle_prefix;
 	gboolean dontdistridlehack, has_login;
 
-	GStaticRecMutex *idle_prefix_lock, *idle_lock, *sum_lock;
+	GStaticRecMutex *idle_lock, *sum_lock;
 	GThread *idle_thread;
-	gboolean idle_cont, in_idle, idle_kill;
+	gboolean idle_cont, in_idle;
 	guint idle_sleep, getsrv_sleep;
 	gboolean courier_crap;
 	gboolean going_online, got_online, clean_exit;
@@ -185,10 +198,7 @@
 
 gboolean camel_imap_store_connected (CamelImapStore *store, CamelException *ex);
 
-ssize_t camel_imap_store_readline_nl (CamelImapStore *store, char **dest, CamelException *ex);
-ssize_t camel_imap_store_readline_nb (CamelImapStore *store, char **dest, CamelException *ex);
 ssize_t camel_imap_store_readline (CamelImapStore *store, char **dest, CamelException *ex);
-ssize_t camel_imap_store_readline_idle (CamelImapStore *store, char **dest, CamelException *ex);
 
 gboolean camel_imap_store_restore_stream_buffer (CamelImapStore *store);
 
Index: libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c
===================================================================
--- libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c	(revision 2884)
+++ libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c	(working copy)
@@ -3456,15 +3456,6 @@
 	guint32 flags;
 } FetchIdleResponse;
 
-typedef struct {
-	guint32 exists;
-	guint32 recent;
-	GArray *expunged;
-	GList *vanished;
-	GPtrArray *fetch;
-	gboolean exists_happened;
-	CamelFolder *folder;
-} IdleResponse;
 
 static void 
 process_idle_response (IdleResponse *idle_resp)
@@ -3600,7 +3591,7 @@
 	return idle_resp;
 }
 
-static void
+void
 idle_response_free (IdleResponse *idle_resp)
 {
 	idle_debug ("idle_response_free\n");
@@ -3624,41 +3615,29 @@
 
 
 static void
-idle_real_start (CamelImapStore *store)
+idle_start (CamelImapStore *store)
 {
 	char *resp;
 	CamelException ex = CAMEL_EXCEPTION_INITIALISER;
-	gboolean l = CAMEL_SERVICE_REC_TRYLOCK (store, connect_lock);
-	if (store->ostream && store->istream && CAMEL_IS_STREAM (store->ostream))
-	{
-		int nwritten = 0;
-		if (store->idle_prefix)
-			g_free (store->idle_prefix);
-		store->idle_prefix = g_strdup_printf ("%c%.5u", 
-			store->tag_prefix, store->command++);
-		nwritten = camel_stream_printf (store->ostream, "%s IDLE\r\n",
+	int nwritten = 0;
+
+	if (store->idle_prefix)
+		g_free (store->idle_prefix);
+
+	store->idle_prefix = g_strdup_printf ("%c%.5u", store->tag_prefix, 
+			store->command++);
+
+	nwritten = camel_stream_printf (store->ostream, "%s IDLE\r\n",
 			store->idle_prefix);
-		idle_debug ("(%d, %d) -> %s IDLE\n", strlen (store->idle_prefix)+5, 
-			nwritten, store->idle_prefix);
-	} else {
-		idle_debug ("idle_real_start connection lost\n");
-		goto errh;
-	}
 
-	/* The IDLE command is sent from the client to the server when the
-	 *  client is ready to accept unsolicited mailbox update messages.  The
-	 *  server requests a response to the IDLE command using the continuation
-	 * ("+") response.  The IDLE command remains active until the client
-	 * responds to the continuation, and as long as an IDLE command is
-	 * active, the server is now free to send untagged EXISTS, EXPUNGE, and
-	 *  other messages at any time. */
+	idle_debug ("(%d, %d) -> %s IDLE\n", strlen (store->idle_prefix)+5, 
+		nwritten, store->idle_prefix);
 
-	/* So according to the RFC, we will wait for the server for its + 
-	 * continuation. If the server doesn't do this, it's an incorrect 
-	 * IDLE implementation at the server. Right? */
+	/* According to the RFC, we will wait for the server for its + 
+	 * continuation. */
 
 	resp = NULL;
-	while (camel_imap_store_readline_nl (store, &resp, &ex) > 0)
+	while (camel_imap_store_readline (store, &resp, &ex) > 0)
 	{
 		gboolean tbreak = FALSE;
 		if (!strncmp (resp, "+ ", 2))
@@ -3667,16 +3646,15 @@
 			tbreak = TRUE;
 		if (camel_strstrcase (resp, "BAD") != NULL)
 			tbreak = TRUE;
-		idle_debug ("(.., ..) <- %s | in idle_real_start\n", resp);
-		g_free (resp); resp=NULL;
+		idle_debug ("(.., ..) <- %s\n", resp);
+		g_free (resp); 
+		resp=NULL;
 		if (tbreak)
 			break;
 	}
 	if (resp)
 		g_free (resp);
-errh:
-	if (l)
-		CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
+
 	return;
 }
 
@@ -3692,11 +3670,55 @@
 			idle_resp = idle_response_new (folder);
 		read_idle_response (folder, resp, idle_resp);
 	}
-	idle_debug ("(%d, ..) <- %s\n", 
+	idle_debug ("(%d, ..) <- [%s]\n", 
 		strlen (resp), resp);
 	return;
 }
 
+
+static void
+idle_done (CamelImapStore *store, CamelFolder *folder, IdleResponse *idle_resp)
+{
+	char *resp;
+	CamelException ex = CAMEL_EXCEPTION_INITIALISER;
+	int nwritten = 0;
+
+	nwritten = camel_stream_printf (store->ostream, "DONE\r\n",
+		store->idle_prefix);
+	idle_debug ("(%d, %d) -> DONE\n", nwritten, nwritten);
+
+	resp = NULL;
+	while (camel_imap_store_readline (store, &resp, &ex) > 0)
+	{
+		gboolean tbreak = FALSE;
+		int l = my_replace (resp, '\n', '\0');
+		if (resp && l > 1 && resp[0] == '*') {
+			if (!idle_resp)
+				idle_resp = idle_response_new (folder);
+			consume_idle_line (store, folder, resp, idle_resp);
+		}
+
+		if (camel_strstrcase (resp, "OK") != NULL)
+			tbreak = TRUE;
+		if (camel_strstrcase (resp, "NO") != NULL)
+			tbreak = TRUE;
+		if (camel_strstrcase (resp, "BAD") != NULL)
+			tbreak = TRUE;
+
+		idle_debug ("(.., ..) <- %s\n", resp);
+		g_free (resp); 
+		resp=NULL;
+
+		if (tbreak)
+			break;
+	}
+	if (resp)
+		g_free (resp);
+
+
+	return;
+}
+
 typedef struct {
 	CamelFolder *folder;
 	GCond *condition;
@@ -3715,6 +3737,12 @@
 	int cnt = 0;
 	int nwritten=0;
 	gpointer retval = NULL;
+	gchar line_buffer [1024];
+	CamelTcpStream *tcp_stream;
+	IdleResponse *idle_resp = NULL;
+	gboolean stopped = FALSE, ever_landed = FALSE;
+	int lines = 0, nextlineoff = 0;
+	int stop_fd;
 
 	idle_debug ("idle_thread starts\n");
 
@@ -3776,199 +3804,83 @@
 		idle_debug ("idle_thread starting but immediately stopping\n");
 	}
 
+	idle_start (store);
+
+	if (!info->had_cond && info->condition) {
+		g_mutex_lock (info->mutex);
+		g_cond_broadcast (info->condition);
+		info->had_cond = TRUE;
+		had_cond = TRUE;
+		g_mutex_unlock (info->mutex);
+	}
+
 	/* While nothing has stopped us yet ... 
 	 * TNY TODO: it would be nicer to use select() here, rather than usleep() */
 
-	while (my_cont && !store->idle_kill) 
+	tcp_stream = (CamelTcpStream *) store->ostream;
+	stop_fd = camel_operation_cancel_fd (store->current_idle);
+
+	while (store->idle_cont) 
 	{
-		CamelException ex = CAMEL_EXCEPTION_INITIALISER;
-		char *resp = NULL;
-		IdleResponse *idle_resp = NULL;
-		gboolean senddone = FALSE;
+		char *lasts = NULL;
+		int bytes = 0;
+		char *ptr;
 
-		/* A) The first time we will start the IDLE by sending IDLE to
-		 * the server and reading away the + continuation (check out the
-		 * idle_real_start function). We don't call this in the other
-		 * loop cycles of this while. */
+		ever_landed = TRUE;
 
-		if (store->idle_cont && first) {
-			gboolean l = g_static_rec_mutex_trylock (store->idle_lock);
-			if (!store->idle_kill)
-				idle_real_start (store);
-			if (l)
-				g_static_rec_mutex_unlock (store->idle_lock);
-			first = FALSE;
-		}
+		bytes = camel_tcp_stream_wait (tcp_stream, stop_fd, store->idle_sleep, line_buffer+nextlineoff, 1023-nextlineoff);
 
-		/* And we also send the broadcast to the caller of this thread:
-		 * We're started, and we're fine. It can continue. We don't call
-		 * this in the other loop cycles of this while. */
+		if (bytes <= 0)
+			continue;
 
-		if (tfirst) {
-			if (info->condition) {
-				g_mutex_lock (info->mutex);
-				g_cond_broadcast (info->condition);
-				info->had_cond = TRUE; had_cond = TRUE;
-				g_mutex_unlock (info->mutex);
-			}
-			tfirst = FALSE;
-		}
+		line_buffer[bytes+1] = '\0';
+		ptr = strrchr (line_buffer, '\n');
+		if (ptr) {
+			char my_data [1024];
+			char *resp;
+			int pos = line_buffer-ptr;
+			int len = bytes + nextlineoff;
 
-		if (g_static_rec_mutex_trylock (store->idle_lock)) 
-		{
-			/* B) This happens during the IDLE's body (after IDLE is
-			 * started and before DONE is sent). We read away the
-			 * lines in a non-blocking way. As soon as we have a
-			 * full line, that starts with '*', we consume it. */
+			nextlineoff = ptr-line_buffer;
+			memcpy (my_data, line_buffer, nextlineoff);
+			memmove (line_buffer, line_buffer+pos, len - nextlineoff);
 
-			if (!store->idle_kill) {
-				while (camel_imap_store_readline_nb (store, &resp, &ex) > 0)
-				{
-					if (resp && strlen (resp) > 1 && resp[0] == '*') {
-						if (!idle_resp)
-							idle_resp = idle_response_new (folder);
-						consume_idle_line (store, folder, resp, idle_resp);
-					}
-
-					if (resp)
-						g_free (resp);
-					resp = NULL;
+			for (resp = strtok_r (my_data, "\r\n", &lasts); resp; resp = strtok_r (NULL, "\r\n", &lasts))
+			{
+				if (resp && strlen (resp) > 1 && resp[0] == '*') {
+					if (!idle_resp)
+						idle_resp = idle_response_new (folder);
+					consume_idle_line (store, folder, resp, idle_resp);
+					lines++;
 				}
 			}
-			g_static_rec_mutex_unlock (store->idle_lock);
+
 		}
 
-		if (resp)
-			g_free (resp);
+		if (!store->idle_cont || (idle_resp && idle_resp->exists_happened)) {
+			idle_done (store, folder, idle_resp);
+			stopped = TRUE;
+			if (!store->idle_cont)
+				retval = idle_resp;
+		} 
 
-		if (store->idle_cont) 
-		{
-			if (idle_resp && !idle_resp->exists_happened) {
-				/* We can process it already: nothing is at this moment
-				 * joining us, nothing is at this moment locking the
-				 * folder_changed handler of TnyCamelFolder */
+		if (store->idle_cont) {
+			if (idle_resp) {
 				process_idle_response (idle_resp);
 				idle_response_free (idle_resp);
 				idle_resp = NULL;
-			} else if (idle_resp && idle_resp->exists_happened) {
-
-				/* We can't deal with new EXISTS responses 
-				 * without first stopping IDLE (we'll need to
-				 * fetch the new headers) */
-
-				senddone = TRUE;
-				retval = idle_resp;
+				lines = 0;
 			}
-		} else {
-			/* If store->idle_cont was FALSE, we're going to handle
-			 * idle_resp differently (look below). */
-			senddone = TRUE;
-			retval = idle_resp; 
+			if (stopped)
+				idle_start (store);
 		}
+	}
 
-		/* C) So either we timed out (store->idle_sleep as been reached), 
-		 * which means that we 'are' going to restart this entire while,
-		 * including resending the IDLE-start, after we're done with 
-		 * this if-block of course.
-		 *
-		 * Or another thread called us to stop IDLE, and then we're 
-		 * going to exit this while, of course. If it was an idle_kill,
-		 * we're not even going to try doing that in a nice way. In that
-		 * case we'll just exit ASAP (it's let_idle_die in CamelImapStore
-		 * trying to disconnect from the IMAP server). */
-
-		if ((cnt > store->idle_sleep) || senddone) 
-		{
-			if (store->idle_prefix) 
-			{
-				CamelImapResponseType type;
-				gboolean l = g_static_rec_mutex_trylock (store->idle_lock);
-
-				if (!store->idle_kill) 
-				{
-					/* We read-away everything that we still
-					 * have. To find where idle_resp is handled,
-					 * read below at the g_thread_join for
-					 * this thread (we are returning it). */
-
-					resp = NULL;
-					while (camel_imap_store_readline_nb (store, &resp, &ex) > 0)
-					{
-						if (resp && strlen (resp) > 1 && resp[0] == '*') {
-							if (!idle_resp) {
-								idle_resp = idle_response_new (folder);
-								/* We will free this after the join */
-								if (!store->idle_cont)
-									retval = idle_resp; 
-							}
-							consume_idle_line (store, folder, resp, idle_resp);
-						}
-
-						if (resp)
-							g_free (resp);
-						resp = NULL;
-					}
-					if (resp)
-						g_free (resp);
-					resp = NULL;
-
-					/* We send the DONE to the server */
-
-					nwritten = camel_stream_printf (store->ostream, "DONE\r\n");
-					idle_debug ("(%d, 8) -> DONE\n", nwritten);
-
-					/* We read away everything the server sends 
-					 * until the we see the untagged OK response */
-
-					while ((type = camel_imap_command_response_idle (store, &resp, &ex)) == CAMEL_IMAP_RESPONSE_UNTAGGED) 
-					{
-						if (resp && strlen (resp) > 1 && resp[0] == '*') {
-							if (!idle_resp) {
-								idle_resp = idle_response_new (folder);
-								/* We will free this after the join */
-								if (!store->idle_cont)
-									retval = idle_resp; 
-							}
-							consume_idle_line (store, folder, resp, idle_resp);
-						}
-
-						if (resp)
-							g_free (resp);
-						resp = NULL;
-					}
-				}
-
-				if (l)
-					g_static_rec_mutex_unlock (store->idle_lock);
-
-				if (resp)
-					g_free (resp);
-				resp = NULL;
-
-				/* If we are continuing the loop, handle idle_resp
-				 * now (this can invoke fetching new headers). */
-
-				if (store->idle_cont && idle_resp) {
-					process_idle_response (idle_resp);
-					idle_response_free (idle_resp);
-					idle_resp = NULL;
-				}
-			}
-
-			if (store->idle_cont)
-				first = TRUE; 
-			else
-				my_cont = FALSE;
-
-			cnt = 0;
-		}
-
-		/* TNY TODO: try to use the select() of the non-blocking read 
-		 * for this usleep() and cnt stuff. */
-
-		if (my_cont)
-			usleep (500000);
-		cnt++;
+	if (!ever_landed) {
+		if (!idle_resp)
+			idle_resp = idle_response_new (folder);
+		idle_done (store, folder, idle_resp);
+		retval = idle_resp;
 	}
 
 	/* We have an extra bool for this, because it's possible that info
@@ -3989,7 +3901,40 @@
 	return retval;
 }
 
+static void 
+do_store_stop_idle_now (CamelImapStore *store)
+{
+	IdleResponse *idle_resp = NULL;
 
+	store->idle_cont = FALSE;
+	if (store->current_idle)
+		camel_operation_cancel (store->current_idle);
+
+	printf ("Joining %s\n", store->idle_thread?"yes":"no");
+	idle_resp = g_thread_join (store->idle_thread);
+	printf ("Joining finished %s\n", idle_resp?"have results":"none");
+
+	if (store->current_idle)
+		camel_operation_uncancel (store->current_idle);
+
+	if (store->idle_prefix)
+		g_free (store->idle_prefix);
+	store->idle_prefix = NULL;
+
+	/* We are doing this here because here we wont hit the
+	 * priv->folder's lock of TnyCamelFolder during its
+	 * folder_changed handler. */
+
+	if (idle_resp) {
+		process_idle_response (idle_resp);
+		idle_response_free (idle_resp);
+	}
+
+	store->in_idle = FALSE;
+	store->idle_thread = NULL;
+
+}
+
 void
 camel_imap_folder_stop_idle (CamelFolder *folder)
 {
@@ -4000,39 +3945,23 @@
 
 	store = CAMEL_IMAP_STORE (folder->parent_store);
 
-	store->idle_cont = FALSE;
-
 	if (!camel_disco_store_check_online ((CamelDiscoStore*)store, &ex))
 		return;
 
-	if ((store->capabilities & IMAP_CAPABILITY_IDLE))
-	{
-		if (store->in_idle && store->idle_thread) {
-			IdleResponse *idle_resp = NULL;
-			store->idle_cont = FALSE;
-			idle_resp = g_thread_join (store->idle_thread);
-			g_static_rec_mutex_lock (store->idle_prefix_lock);
-			g_static_rec_mutex_lock (store->idle_lock);
-			store->in_idle = FALSE;
-			store->idle_thread = NULL;
-			if (store->idle_prefix)
-				g_free (store->idle_prefix);
-			g_static_rec_mutex_unlock (store->idle_lock);
-			g_static_rec_mutex_unlock (store->idle_prefix_lock);
+	g_static_rec_mutex_lock (store->idle_lock);
 
-			/* We are doing this here because here we wont hit the
-			 * priv->folder's lock of TnyCamelFolder during its
-			 * folder_changed handler. */
+	if ((store->capabilities & IMAP_CAPABILITY_IDLE)) {
+		if (store->in_idle && store->idle_thread)
+			do_store_stop_idle_now (store);
+		else 
 
-			if (idle_resp) {
-				process_idle_response (idle_resp);
-				idle_response_free (idle_resp);
-			}
+		printf ("NOT IN IDLE %s, %s\n",  
+			store->in_idle ? "in idle":"not in idle" , store->idle_thread ? "h thread" : "no thread") ;
 
-		}
-		store->idle_prefix = NULL;
 	}
 
+	g_static_rec_mutex_unlock (store->idle_lock);
+
 	return;
 }
 
@@ -4058,43 +3987,29 @@
 
 	if (store->capabilities & IMAP_CAPABILITY_IDLE)
 	{
-		g_static_rec_mutex_lock (store->idle_prefix_lock);
-		if (store->current_folder && !store->idle_prefix)
+		if (store->current_folder)
 		{
 			folder->folder_flags |= CAMEL_FOLDER_HAS_PUSHEMAIL_CAPABILITY;
 
-			if (!store->in_idle && store->idle_thread) {
-				IdleResponse *idle_resp = NULL;
+			if (store->in_idle && store->idle_thread)
+				do_store_stop_idle_now (store);
 
-				store->idle_cont = FALSE;
-				idle_resp = g_thread_join (store->idle_thread);
-				store->idle_thread = NULL;
-
-				/* We are doing this here because here we wont hit the
-				 * priv->folder's lock of TnyCamelFolder during its
-				 * folder_changed handler. */
-
-				if (idle_resp) {
-					process_idle_response (idle_resp);
-					idle_response_free (idle_resp);
-				}
-
-			}
-
 			if (!store->in_idle) {
 				IdleThreadInfo *info = g_slice_new0 (IdleThreadInfo);
-				store->idle_kill = FALSE;
-				store->in_idle = TRUE;
-				store->idle_cont = TRUE;
-
 				info->mutex = g_mutex_new ();
 				info->condition = g_cond_new ();
 				info->had_cond = FALSE;
 				info->folder = folder;
 				camel_object_ref (info->folder);
 
+				if (!store->current_idle)
+					store->current_idle = camel_operation_new (NULL, NULL);
+
+				store->idle_cont = TRUE;
+				store->in_idle = TRUE;
 				store->idle_thread = g_thread_create (idle_thread, 
-					info, TRUE, NULL);
+						info, TRUE, NULL);
+
 				g_mutex_lock (info->mutex);
 				if (!info->had_cond)
 					g_cond_wait (info->condition, info->mutex);
@@ -4104,11 +4019,9 @@
 				g_mutex_free (info->mutex);
 				g_cond_free (info->condition);
 				g_slice_free (IdleThreadInfo, info);
-
 			}
 
 		}
-		g_static_rec_mutex_unlock (store->idle_prefix_lock);
 	}
 
 	g_static_rec_mutex_unlock (store->idle_lock);
Index: libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c
===================================================================
--- libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c	(revision 2883)
+++ libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c	(working copy)
@@ -355,19 +355,6 @@
 		fprintf (stderr, "sending : %c%.5u %s\r\n", store->tag_prefix, store->command, mask);
 	}
 
-	/* Read away whatever we got */
-	while (camel_imap_store_readline_nb (store, &resp, &myex) > 0)
-	{
-		imap_debug ("unsolitcited: ");
-		imap_debug (resp);
-		imap_debug ("\n");
-
-		g_free (resp);
-		resp=NULL;
-	}
-	if (resp)
-		g_free (resp);
-
 	full_cmd = g_strdup_printf ("%c%.5u %s\r\n", store->tag_prefix, 
 		store->command++, cmd);
 	len = strlen (full_cmd);
@@ -531,72 +518,6 @@
 }
 
 
-CamelImapResponseType
-camel_imap_command_response_idle (CamelImapStore *store, char **response,
-			     CamelException *ex)
-{
-	CamelImapResponseType type;
-	char *respbuf;
-
-	if (camel_imap_store_readline_nl (store, &respbuf, ex) < 0)
-		return CAMEL_IMAP_RESPONSE_ERROR;
-
-	imap_debug ("(.., ..) <- %s (IDLE response)\n", respbuf);
-
-	switch (*respbuf) {
-	case '*':
-		if (!g_ascii_strncasecmp (respbuf, "* BYE", 5)) {
-			/* Connection was lost, no more data to fetch */
-			camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL);
-			camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
-					      _("Server unexpectedly disconnected: %s"),
-					      _("Unknown error")); /* g_strerror (104));  FIXME after 1.0 is released */
-			store->connected = FALSE;
-			g_free (respbuf);
-			respbuf = NULL;
-			type = CAMEL_IMAP_RESPONSE_ERROR;
-			break;
-		}
-		
-		/* Read the rest of the response. */
-		type = CAMEL_IMAP_RESPONSE_UNTAGGED;
-		respbuf = imap_read_untagged (store, respbuf, ex);
-		if (!respbuf)
-			type = CAMEL_IMAP_RESPONSE_ERROR;
-		else if (!g_ascii_strncasecmp (respbuf, "* OK [ALERT]", 12)
-			 || !g_ascii_strncasecmp (respbuf, "* NO [ALERT]", 12)
-			 || !g_ascii_strncasecmp (respbuf, "* BAD [ALERT]", 13)) {
-			char *msg;
-
-			/* for imap ALERT codes, account user host */
-			/* we might get a ']' from a BAD response since we +12, but who cares? */
-			msg = g_strdup_printf(_("Alert from IMAP server %s %s:\n%s"),
-					      ((CamelService *)store)->url->user, ((CamelService *)store)->url->host, respbuf+12);
-			camel_session_alert_user_generic(((CamelService *)store)->session, 
-				CAMEL_SESSION_ALERT_WARNING, msg, FALSE, ((CamelService *)store));
-			g_free(msg);
-		} else if (!g_ascii_strncasecmp (respbuf, "* BAD Invalid tag",17))
-			type = CAMEL_IMAP_RESPONSE_ERROR;
-		break;
-	case '+':
-		type = CAMEL_IMAP_RESPONSE_CONTINUATION;
-		break;
-	default:
-		if (camel_strstrcase (respbuf, "OK") != NULL || 
-			camel_strstrcase (respbuf, "NO") != NULL ||
-			camel_strstrcase (respbuf, "BAD") != NULL) {
-
-			type = CAMEL_IMAP_RESPONSE_TAGGED;
-
-		} else 
-			type = CAMEL_IMAP_RESPONSE_UNTAGGED;
-		break;
-	}
-	*response = respbuf;
-	
-	return type;
-}
-
 CamelImapResponse *
 imap_read_response (CamelImapStore *store, CamelException *ex)
 {
Index: libtinymail-camel/camel-lite/camel/camel-tcp-stream-openssl.c
===================================================================
--- libtinymail-camel/camel-lite/camel/camel-tcp-stream-openssl.c	(revision 2882)
+++ libtinymail-camel/camel-lite/camel/camel-tcp-stream-openssl.c	(working copy)
@@ -61,7 +61,7 @@
 /* Returns the class for a CamelTcpStreamSSL */
 #define CTSR_CLASS(so) CAMEL_TCP_STREAM_SSL_CLASS (CAMEL_OBJECT_GET_CLASS (so))
 
-static ssize_t stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n);
+static ssize_t stream_wait (CamelTcpStream *stream, int stop_fd, int timeout, char *buffer, size_t n);
 static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n);
 static ssize_t stream_write (CamelStream *stream, const char *buffer, size_t n);
 static int stream_flush  (CamelStream *stream);
@@ -84,6 +84,9 @@
 	gboolean ssl_mode;
 	guint32 flags;
 	CamelService *service;
+
+	gchar *wait_buffer;
+	size_t wait_buffer_size;
 };
 
 
@@ -105,7 +108,7 @@
 	camel_stream_class->flush = stream_flush;
 	camel_stream_class->close = stream_close;
 	
-	camel_tcp_stream_class->read_nb = stream_read_nb;
+	camel_tcp_stream_class->wait = stream_wait;
 	camel_tcp_stream_class->connect = stream_connect;
 	camel_tcp_stream_class->getsockopt = stream_getsockopt;
 	camel_tcp_stream_class->setsockopt = stream_setsockopt;
@@ -124,6 +127,8 @@
 	
 	stream->priv = g_new0 (struct _CamelTcpStreamSSLPrivate, 1);
 	stream->priv->sockfd = -1;
+	stream->priv->wait_buffer = g_malloc (1024);
+	stream->priv->wait_buffer_size = -1;
 }
 
 static void
@@ -143,9 +148,10 @@
 	
 	if (stream->priv->sockfd != -1)
 		close (stream->priv->sockfd);
-	
+
 	g_free (stream->priv->expected_host);
-	
+	g_free (stream->priv->wait_buffer);
+
 	g_free (stream->priv);
 }
 
@@ -288,53 +294,42 @@
 
 
 static ssize_t
-stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n)
+stream_wait (CamelTcpStream *stream, int stop_fd, int timeout, char *buffer, size_t max_len)
 {
 	CamelTcpStreamSSL *openssl = CAMEL_TCP_STREAM_SSL (stream);
 	SSL *ssl = openssl->priv->ssl;
 	ssize_t nread;
-
 	int error, flags, fdmax;
-	struct timeval timeout;
+	struct timeval tv;
 	fd_set rdset;
 	int res;
 
 	flags = fcntl (openssl->priv->sockfd, F_GETFL);
 	fcntl (openssl->priv->sockfd, F_SETFL, flags | O_NONBLOCK);
-	
-	fdmax = openssl->priv->sockfd + 1;
-	
-	do {
-		FD_ZERO (&rdset);
-		FD_SET (openssl->priv->sockfd, &rdset);
+
+	fdmax = MAX (openssl->priv->sockfd, stop_fd) + 1;
+	FD_ZERO (&rdset);
+	FD_SET (openssl->priv->sockfd, &rdset);
+	FD_SET (stop_fd, &rdset);
+
+	nread = -1;
+	tv.tv_sec = timeout;
+	tv.tv_usec = 0;
+
+	res = select (fdmax, &rdset, 0, 0, &tv);
+
+	if (res > 0 && !FD_ISSET (stop_fd, &rdset)) {
+		if (ssl)
+			nread = SSL_read (ssl, buffer, max_len);
+		else
+			nread = read (openssl->priv->sockfd, buffer, max_len);
+	} else
 		nread = -1;
-		timeout.tv_sec = NONBLOCKING_READ_TIMEOUT;
-		timeout.tv_usec = 0;
-		res = select (fdmax, &rdset, 0, 0, &timeout);
-		
-		if (res == -1)
-			;
-		else if (res == 0)
-			errno = ETIMEDOUT;
-		else {
 
-		  do {
-			if (ssl) {
-				nread = SSL_read (ssl, buffer, n);
-				if (nread < 0)
-					errno = ssl_errno (ssl, nread);
-			} else {
-				nread = read (openssl->priv->sockfd, buffer, n);
-			}
-		  } while (0 && (nread < 0 && errno == EINTR));
-		}
-	} while (0 && (nread < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)));
-	
 	error = errno;
 	fcntl (openssl->priv->sockfd, F_SETFL, flags);
 	errno = error;
 
-
 	return nread;
 }
 
@@ -346,7 +341,7 @@
 	SSL *ssl = openssl->priv->ssl;
 	ssize_t nread;
 	int cancel_fd;
-	
+
 	if (camel_operation_cancel_check (NULL)) {
 		errno = EINTR;
 		return -1;
Index: libtinymail-camel/camel-lite/camel/camel-tcp-stream.c
===================================================================
--- libtinymail-camel/camel-lite/camel/camel-tcp-stream.c	(revision 2882)
+++ libtinymail-camel/camel-lite/camel/camel-tcp-stream.c	(working copy)
@@ -40,7 +40,7 @@
 static int tcp_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
 static struct sockaddr *tcp_get_local_address (CamelTcpStream *stream, socklen_t *len);
 static struct sockaddr *tcp_get_remote_address (CamelTcpStream *stream, socklen_t *len);
-static ssize_t tcp_read_nb (CamelTcpStream *stream, char *buffer, size_t n);
+static ssize_t tcp_wait (CamelTcpStream *stream, int stop_fd, int timeout, char *buffer, size_t max_len);
 
 static void
 camel_tcp_stream_class_init (CamelTcpStreamClass *camel_tcp_stream_class)
@@ -50,12 +50,12 @@
 	parent_class = CAMEL_STREAM_CLASS (camel_type_get_global_classfuncs (CAMEL_STREAM_TYPE));
 	
 	/* tcp stream methods */
-	camel_tcp_stream_class->read_nb            = tcp_read_nb;
 	camel_tcp_stream_class->connect            = tcp_connect;
 	camel_tcp_stream_class->getsockopt         = tcp_getsockopt;
 	camel_tcp_stream_class->setsockopt         = tcp_setsockopt;
 	camel_tcp_stream_class->get_local_address  = tcp_get_local_address;
 	camel_tcp_stream_class->get_remote_address = tcp_get_remote_address;
+	camel_tcp_stream_class->wait               = tcp_wait;
 }
 
 static void
@@ -84,9 +84,9 @@
 }
 
 static ssize_t
-tcp_read_nb (CamelTcpStream *stream, char *buffer, size_t n)
+tcp_wait (CamelTcpStream *stream, int stop_fd, int timeout, char *buffer, size_t max_len)
 {
-	w(g_warning ("CamelTcpStream::read_nb called on default implementation"));
+	w(g_warning ("CamelTcpStream::wait called on default implementation"));
 	return -1;
 }
 
@@ -191,10 +191,10 @@
 	return CTS_CLASS (stream)->get_local_address (stream, len);
 }
 
-int 
-camel_tcp_stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n)
+ssize_t 
+camel_tcp_stream_wait (CamelTcpStream *stream, int stop_fd, int timeout, char *buffer, size_t max_len)
 {
-	return CTS_CLASS (stream)->read_nb (stream, buffer, n);
+	return CTS_CLASS (stream)->wait (stream, stop_fd, timeout, buffer, max_len);
 }
 
 
Index: libtinymail-camel/camel-lite/camel/camel-tcp-stream.h
===================================================================
--- libtinymail-camel/camel-lite/camel/camel-tcp-stream.h	(revision 2882)
+++ libtinymail-camel/camel-lite/camel/camel-tcp-stream.h	(working copy)
@@ -106,7 +106,9 @@
 	
 	struct sockaddr * (*get_local_address)  (CamelTcpStream *stream, socklen_t *len);
 	struct sockaddr * (*get_remote_address) (CamelTcpStream *stream, socklen_t *len);
-	ssize_t (*read_nb)   (CamelTcpStream *stream, char *buffer, size_t n);
+
+	ssize_t (*wait) (CamelTcpStream *stream, int stop_fd, int timeout, char *buffer, size_t max_len);
+
 } CamelTcpStreamClass;
 
 /* Standard Camel function */
@@ -116,11 +118,11 @@
 int         camel_tcp_stream_connect    (CamelTcpStream *stream, struct addrinfo *host);
 int         camel_tcp_stream_getsockopt (CamelTcpStream *stream, CamelSockOptData *data);
 int         camel_tcp_stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
+ssize_t     camel_tcp_stream_wait       (CamelTcpStream *stream, int stop_fd, int timeout, char *buffer, size_t max_len);
 
 struct sockaddr *camel_tcp_stream_get_local_address  (CamelTcpStream *stream, socklen_t *len);
 struct sockaddr *camel_tcp_stream_get_remote_address (CamelTcpStream *stream, socklen_t *len);
 
-int         camel_tcp_stream_read_nb    (CamelTcpStream *stream, char *buffer, size_t n);
 
 G_END_DECLS
 
Index: libtinymail-camel/camel-lite/camel/camel-file-utils.c
===================================================================
--- libtinymail-camel/camel-lite/camel/camel-file-utils.c	(revision 2882)
+++ libtinymail-camel/camel-lite/camel/camel-file-utils.c	(working copy)
@@ -798,89 +798,8 @@
 }
 
 
-ssize_t
-camel_read_socket_nb (int fd, char *buf, size_t n)
-{
-#ifndef G_OS_WIN32
-	return camel_read_nb (fd, buf, n);
-#else
-	ssize_t nread;
-	int cancel_fd;
-	
-	if (camel_operation_cancel_check (NULL)) {
-		errno = EINTR;
-		return -1;
-	}
-	cancel_fd = camel_operation_cancel_fd (NULL);
 
-	if (cancel_fd == -1) {
 
-		int fdmax;
-		fd_set rdset;
-		u_long yes = 1;
-
-		ioctlsocket (fd, FIONBIO, &yes);
-		fdmax = fd + 1;
-		do {
-			struct timeval tv;
-			int res;
-
-			FD_ZERO (&rdset);
-			FD_SET (fd, &rdset);
-			tv.tv_sec = NONBLOCKING_READ_TIMEOUT;
-			tv.tv_usec = 0;
-			nread = -1;
-
-			res = select(fdmax, &rdset, 0, 0, &tv);
-			if (res == -1)
-				;
-			else if (res == 0)
-				errno = ETIMEDOUT;
-			} else {				
-				nread = recv (fd, buf, n, 0);
-			}
-		} while (0&&(nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK));
-
-	} else {
-		int fdmax;
-		fd_set rdset;
-		u_long yes = 1;
-
-		ioctlsocket (fd, FIONBIO, &yes);
-		fdmax = MAX (fd, cancel_fd) + 1;
-		do {
-			struct timeval tv;
-			int res;
-
-			FD_ZERO (&rdset);
-			FD_SET (fd, &rdset);
-			FD_SET (cancel_fd, &rdset);
-			tv.tv_sec = NONBLOCKING_READ_TIMEOUT;
-			tv.tv_usec = 0;
-			nread = -1;
-
-			res = select(fdmax, &rdset, 0, 0, &tv);
-			if (res == -1)
-				;
-			else if (res == 0)
-				errno = ETIMEDOUT;
-			else if (FD_ISSET (cancel_fd, &rdset)) {
-				errno = EINTR;
-				goto failed;
-			} else {				
-				nread = recv (fd, buf, n, 0);
-			}
-		} while (0&&(nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK));
-	failed:
-		;
-	}
-	
-	return nread;
-#endif
-}
-
-
-
 /**
  * camel_write_socket:
  * @fd: file descriptor
Index: libtinymail-camel/camel-lite/camel/camel-tcp-stream-raw.c
===================================================================
--- libtinymail-camel/camel-lite/camel/camel-tcp-stream-raw.c	(revision 2882)
+++ libtinymail-camel/camel-lite/camel/camel-tcp-stream-raw.c	(working copy)
@@ -32,7 +32,12 @@
 #include <unistd.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <sys/types.h>
 
+#include <glib.h>
+
 #include "camel-file-utils.h"
 #include "camel-operation.h"
 #include "camel-tcp-stream-raw.h"
@@ -64,7 +69,7 @@
 static int stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data);
 static struct sockaddr *stream_get_local_address (CamelTcpStream *stream, socklen_t *len);
 static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len);
-static ssize_t stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n);
+static ssize_t stream_wait (CamelTcpStream *stream, int stop_fd, int timeout, char *buffer, size_t n);
 
 
 static void
@@ -83,7 +88,7 @@
 	camel_stream_class->flush = stream_flush;
 	camel_stream_class->close = stream_close;
 
-	camel_tcp_stream_class->read_nb = stream_read_nb;
+	camel_tcp_stream_class->wait = stream_wait;
 	camel_tcp_stream_class->connect = stream_connect;
 	camel_tcp_stream_class->getsockopt = stream_getsockopt;
 	camel_tcp_stream_class->setsockopt  = stream_setsockopt;
@@ -95,7 +100,6 @@
 camel_tcp_stream_raw_init (gpointer object, gpointer klass)
 {
 	CamelTcpStreamRaw *stream = CAMEL_TCP_STREAM_RAW (object);
-	
 	stream->sockfd = -1;
 }
 
@@ -103,7 +107,6 @@
 camel_tcp_stream_raw_finalize (CamelObject *object)
 {
 	CamelTcpStreamRaw *stream = CAMEL_TCP_STREAM_RAW (object);
-	
 	if (stream->sockfd != -1)
 		SOCKET_CLOSE (stream->sockfd);
 }
@@ -252,16 +255,40 @@
 stream_read (CamelStream *stream, char *buffer, size_t n)
 {
 	CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
-	
+
 	return camel_read_socket (raw->sockfd, buffer, n);
 }
 
 static ssize_t
-stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n)
+stream_wait (CamelTcpStream *stream, int stop_fd, int timeout, char *buffer, size_t max_len)
 {
 	CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream);
-	
-	return camel_read_socket_nb (raw->sockfd, buffer, n);
+	int fd = raw->sockfd;
+	ssize_t nread;
+	int fdmax;
+	fd_set rdset;
+	u_long yes = 1;
+	struct timeval tv;
+	int res;
+
+	//ioctlsocket (fd, FIONBIO, &yes);
+	fdmax = MAX (fd, stop_fd) + 1;
+
+	FD_ZERO (&rdset);
+	FD_SET (fd, &rdset);
+	FD_SET (stop_fd, &rdset);
+
+	tv.tv_sec = timeout;
+	tv.tv_usec = 0;
+	nread = -1;
+
+	res = select (fdmax, &rdset, 0, 0, &tv);
+	if (res > 0 && !FD_ISSET (stop_fd, &rdset))
+		nread = recv (fd, buffer, max_len, 0);
+	else
+		nread = -1;
+
+	return nread;
 }
 
 static ssize_t
Index: libtinymail-camel/camel-lite/camel/camel-stream-buffer.c
===================================================================
--- libtinymail-camel/camel-lite/camel/camel-stream-buffer.c	(revision 2882)
+++ libtinymail-camel/camel-lite/camel/camel-stream-buffer.c	(working copy)
@@ -429,49 +429,7 @@
 }
 
 
-int
-camel_tcp_stream_buffer_gets_nb (CamelStreamBuffer *sbf, char *buf, unsigned int max)
-{
-	register char *outptr, *inptr, *inend, c, *outend;
-	int bytes_read;
 
-	outptr = buf;
-	inptr = (char*)sbf->ptr;
-	inend = (char*)sbf->end;
-	outend = buf+max-1;	/* room for NUL */
-
-	do {
-		while (inptr<inend && outptr<outend) {
-			c = *inptr++;
-			*outptr++ = c;
-			if (c == '\n') {
-				*outptr = 0;
-				sbf->ptr = (unsigned char*) inptr;
-				return outptr-buf;
-			}
-		}
-		if (outptr == outend)
-			break;
-
-		bytes_read = camel_tcp_stream_read_nb ((CamelTcpStream *)sbf->stream, (char*)sbf->buf, sbf->size);
-		if (bytes_read == -1) {
-			if (buf == outptr)
-				return -1;
-			else
-				bytes_read = 0;
-		}
-		sbf->ptr = sbf->buf;
-		sbf->end = sbf->buf + bytes_read;
-		inptr = (char*)sbf->ptr;
-		inend = (char*)sbf->end;
-	} while (bytes_read>0);
-
-	sbf->ptr = (unsigned char*)inptr;
-	*outptr = 0;
-
-	return (int)(outptr - buf);
-}
-
 /**
  * camel_stream_buffer_read_line: read a complete line from the stream
  * @sbf: a #CamelStreamBuffer object
Index: libtinymail-camel/camel-lite/camel/camel-stream-buffer.h
===================================================================
--- libtinymail-camel/camel-lite/camel/camel-stream-buffer.h	(revision 2882)
+++ libtinymail-camel/camel-lite/camel/camel-stream-buffer.h	(working copy)
@@ -94,7 +94,6 @@
 int camel_stream_buffer_gets (CamelStreamBuffer *sbf, char *buf, unsigned int max);
 
 char *camel_stream_buffer_read_line (CamelStreamBuffer *sbf);
-int camel_tcp_stream_buffer_gets_nb (CamelStreamBuffer *sbf, char *buf, unsigned int max);
 
 
 G_END_DECLS


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