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 resort to refcounting.
This commit is contained in:
parent
f1df2f40d1
commit
802c99edcf
|
@ -236,7 +236,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)
|
||||
|
@ -279,8 +279,6 @@ v_submit_imap_cmd( imap_store_t *ctx, struct imap_cmd *cmd,
|
|||
return cmd;
|
||||
|
||||
bail:
|
||||
imap_invoke_bad_callback( ctx );
|
||||
bail2:
|
||||
done_imap_cmd( ctx, cmd, RESP_CANCEL );
|
||||
return NULL;
|
||||
}
|
||||
|
@ -811,7 +809,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;
|
||||
}
|
||||
|
||||
|
@ -854,7 +852,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)
|
||||
|
@ -882,16 +880,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 ))
|
||||
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)
|
||||
|
@ -1128,13 +1126,14 @@ imap_open_store( store_conf_t *conf,
|
|||
|
||||
ctx = nfcalloc( sizeof(*ctx) );
|
||||
ctx->gen.conf = conf;
|
||||
ctx->conn.fd = -1;
|
||||
ctx->ref_count = 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, (void (*)( void * ))imap_invoke_bad_callback, ctx );
|
||||
|
||||
if (!socket_connect( &srvc->sconf, &ctx->conn ))
|
||||
goto bail;
|
||||
|
||||
|
|
12
src/isync.h
12
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' */
|
||||
|
@ -330,6 +333,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 );
|
||||
|
|
15
src/socket.c
15
src/socket.c
|
@ -48,6 +48,12 @@
|
|||
#include <arpa/inet.h>
|
||||
#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 )
|
||||
{
|
||||
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue
Block a user