commit 0dd0cf34e373503f9b9c61edbcc8c23826db7c62
Author: Oswald Buddenhagen <[email protected]>
Date:   Sun Mar 27 16:50:32 2011 +0200

    make socket read/write error reporting callback-based
    
    the functions still have synchronous return codes as well -
    this enables early error returns without having to make the
    socket object refcounted like the imap context is.

 src/drv_imap.c |   25 ++++++++++++++++---------
 src/isync.h    |   12 ++++++++++++
 src/socket.c   |   15 ++++++++++-----
 3 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 3bbee11..3cab01a 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -232,7 +232,7 @@ v_submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd,
 
        while (ctx->literal_pending)
                if (get_cmd_result( ctx, 0 ) == RESP_CANCEL)
-                       goto bail2;
+                       goto bail;
 
        cmd->tag = ++ctx->nexttag;
        if (fmt)
@@ -275,8 +275,6 @@ v_submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd,
        return cmd;
 
   bail:
-       ctx->gen.bad_callback( ctx->gen.bad_callback_aux );
-  bail2:
        done_imap_cmd( ctx, cmd, RESP_CANCEL );
        return NULL;
 }
@@ -808,7 +806,7 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
        for (;;) {
                if (!(cmd = socket_read_line( &ctx->conn ))) {
                        if (socket_fill( &ctx->conn ) < 0)
-                               break;
+                               return RESP_CANCEL;
                        continue;
                }
 
@@ -851,7 +849,7 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
                                                break; /* stream is likely to 
be useless now */
                                        if (resp == LIST_PARTIAL) {
                                                if (socket_fill( &ctx->conn ) < 
0)
-                                                       break;
+                                                       return RESP_CANCEL;
                                                goto do_fetch;
                                        }
                                        if (parse_fetch( ctx, 
ctx->parse_list_sts.head ) < 0)
@@ -876,16 +874,16 @@ get_cmd_result( imap_store_t *ctx, struct imap_cmd *tcmd )
                                p = cmdp->param.data;
                                cmdp->param.data = 0;
                                if (socket_write( &ctx->conn, p, 
cmdp->param.data_len, GiveOwn ) < 0)
-                                       break;
+                                       return RESP_CANCEL;
                        } else if (cmdp->param.cont) {
                                if (cmdp->param.cont( ctx, cmdp, cmd ) < 0)
-                                       break;
+                                       return RESP_CANCEL;
                        } else {
                                error( "IMAP error: unexpected command 
continuation request\n" );
                                break;
                        }
                        if (socket_write( &ctx->conn, "\r\n", 2, KeepOwn ) < 0)
-                               break;
+                               return RESP_CANCEL;
                        if (!cmdp->param.cont)
                                ctx->literal_pending = 0;
                        if (!tcmd)
@@ -959,6 +957,14 @@ get_cmd_result_p2( imap_store_t *ctx, struct imap_cmd 
*cmd, int response )
        }
 }
 
+static void
+imap_socket_fail( void *aux )
+{
+       imap_store_t *ctx = (imap_store_t *)aux;
+
+       ctx->gen.bad_callback( ctx->gen.bad_callback_aux );
+}
+
 /******************* imap_cancel_store *******************/
 
 static void
@@ -1091,12 +1097,13 @@ imap_open_store( store_conf_t *conf,
 
        ctx = nfcalloc( sizeof(*ctx) );
        ctx->gen.conf = conf;
-       ctx->conn.fd = -1;
        ctx->callbacks.imap_open = cb;
        ctx->callback_aux = aux;
        set_bad_callback( &ctx->gen, (void (*)(void *))imap_open_store_bail, 
ctx );
        ctx->in_progress_append = &ctx->in_progress;
 
+       socket_init( &ctx->conn, imap_socket_fail, ctx );
+
        if (!socket_connect( &srvc->sconf, &ctx->conn ))
                goto bail;
 
diff --git a/src/isync.h b/src/isync.h
index b605fff..91f0d12 100644
--- a/src/isync.h
+++ b/src/isync.h
@@ -79,6 +79,9 @@ typedef struct {
        SSL *ssl;
 #endif
 
+       void (*bad_callback)( void *aux ); /* async fail while sending or 
listening */
+       void *callback_aux;
+
        int offset; /* start of filled bytes in buffer */
        int bytes; /* number of filled bytes in buffer */
        int scanoff; /* offset to continue scanning for newline at, relative to 
'offset' */
@@ -333,6 +336,15 @@ extern const char *Home;
 
 /* socket.c */
 
+/* call this before doing anything with the socket */
+static INLINE void socket_init( conn_t *conn,
+                                void (*bad_callback)( void *aux ),
+                                void *aux )
+{
+       conn->bad_callback = bad_callback;
+       conn->callback_aux = aux;
+       conn->fd = -1;
+}
 int socket_connect( const server_conf_t *conf, conn_t *sock );
 int socket_start_tls( const server_conf_t *conf, conn_t *sock );
 void socket_close( conn_t *sock );
diff --git a/src/socket.c b/src/socket.c
index 6941226..ad00c9f 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -49,6 +49,12 @@
 #include <netdb.h>
 
 static void
+socket_fail( conn_t *conn )
+{
+       conn->bad_callback( conn->callback_aux );
+}
+
+static void
 socket_perror( const char *func, conn_t *sock, int ret )
 {
 #ifdef HAVE_LIBSSL
@@ -65,20 +71,18 @@ socket_perror( const char *func, conn_t *sock, int ret )
                                        error( "SSL_%s: %s\n", func, 
strerror(errno) );
                        } else
                                error( "SSL_%s: %s\n", func, ERR_error_string( 
err, 0 ) );
-                       return;
+                       break;
                default:
                        error( "SSL_%s: unhandled SSL error %d\n", func, err );
                        break;
                }
-               return;
-       }
-#else
-       (void)sock;
+       } else
 #endif
        if (ret < 0)
                perror( func );
        else
                error( "%s: unexpected EOF\n", func );
+       socket_fail( sock );
 }
 
 #ifdef HAVE_LIBSSL
@@ -361,6 +365,7 @@ socket_fill( conn_t *sock )
        int len = sizeof(sock->buf) - n;
        if (!len) {
                error( "Socket error: receive buffer full. Probably protocol 
error.\n" );
+               socket_fail( sock );
                return -1;
        }
        assert( sock->fd >= 0 );

------------------------------------------------------------------------------
Xperia(TM) PLAY
It's a major breakthrough. An authentic gaming
smartphone on the nation's most reliable network.
And it wants your games.
http://p.sf.net/sfu/verizon-sfdev
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to