commit 9e15ab4a5a2938318816f3972708176462cb9d5f
Author: Oswald Buddenhagen <[email protected]>
Date: Sun Feb 15 12:15:46 2015 +0100
refactor socket EOF handling
handling EOF already at the socket level isn't a very good idea - it
breaks the abstraction, and makes implementing sane semantics hard.
src/drv_imap.c | 32 ++++++++++++++++++++++++++------
src/socket.c | 29 +++++++++++++++++++++--------
src/socket.h | 9 ---------
3 files changed, 47 insertions(+), 23 deletions(-)
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 447bc6e..7146d26 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -114,6 +114,8 @@ typedef struct imap_store {
/* Used during sequential operations like connect */
enum { GreetingPending = 0, GreetingBad, GreetingOk, GreetingPreauth }
greeting;
+ int expectBYE; /* LOGOUT is in progress */
+ int expectEOF; /* received LOGOUT's OK or unsolicited BYE */
int canceling; /* imap_cancel() is in progress */
union {
void (*imap_open)( store_t *srv, void *aux );
@@ -674,7 +676,7 @@ parse_imap_list( imap_store_t *ctx, char **sp,
parse_list_state_t *sts )
{
list_t *cur, **curp;
char *s = *sp, *d, *p;
- int bytes;
+ int n, bytes;
char c;
assert( sts );
@@ -724,7 +726,13 @@ parse_imap_list( imap_store_t *ctx, char **sp,
parse_list_state_t *sts )
s[cur->len] = 0;
getbytes:
- bytes -= socket_read( &ctx->conn, s, bytes );
+ n = socket_read( &ctx->conn, s, bytes );
+ if (n < 0) {
+ badeof:
+ error( "IMAP error: unexpected EOF from %s\n",
ctx->conn.name );
+ goto bail;
+ }
+ bytes -= n;
if (bytes > 0)
goto postpone;
@@ -738,6 +746,8 @@ parse_imap_list( imap_store_t *ctx, char **sp,
parse_list_state_t *sts )
getline:
if (!(s = socket_read_line( &ctx->conn )))
goto postpone;
+ if (s == (void *)~0)
+ goto badeof;
if (DFlags & VERBOSE) {
printf( "%s%s\n", ctx->label, s );
fflush( stdout );
@@ -1218,6 +1228,12 @@ imap_socket_read( void *aux )
}
if (!(cmd = socket_read_line( &ctx->conn )))
return;
+ if (cmd == (void *)~0) {
+ if (!ctx->expectEOF)
+ error( "IMAP error: unexpected EOF from %s\n",
ctx->conn.name );
+ /* A clean shutdown sequence ends with bad_callback as
well (see imap_cleanup()). */
+ break;
+ }
if (DFlags & VERBOSE) {
printf( "%s%s\n", ctx->label, cmd );
fflush( stdout );
@@ -1250,12 +1266,14 @@ imap_socket_read( void *aux )
goto dogreet;
}
} else if (!strcmp( "BYE", arg )) {
- if (ctx->conn.state != SCK_CLOSING) {
- ctx->conn.state = SCK_CLOSING;
+ if (!ctx->expectBYE) {
ctx->greeting = GreetingBad;
error( "IMAP error: unexpected BYE
response: %s\n", cmd );
+ /* We just wait for the server to close
the connection now. */
+ ctx->expectEOF = 1;
+ } else {
+ /* We still need to wait for the
LOGOUT's tagged OK. */
}
- /* We just wait for the server to close the
connection now. */
} else if (ctx->greeting == GreetingPending) {
error( "IMAP error: bogus greeting response
%s\n", arg );
break;
@@ -1470,7 +1488,7 @@ imap_cleanup( void )
for (ctx = unowned; ctx; ctx = nctx) {
nctx = ctx->next;
set_bad_callback( ctx, (void (*)(void *))imap_cancel_store, ctx
);
- ((imap_store_t *)ctx)->conn.state = SCK_CLOSING;
+ ((imap_store_t *)ctx)->expectBYE = 1;
imap_exec( (imap_store_t *)ctx, 0, imap_cleanup_p2, "LOGOUT" );
}
}
@@ -1481,6 +1499,8 @@ imap_cleanup_p2( imap_store_t *ctx,
{
if (response == RESP_NO)
imap_cancel_store( &ctx->gen );
+ else if (response == RESP_OK)
+ ctx->expectEOF = 1;
}
/******************* imap_open_store *******************/
diff --git a/src/socket.c b/src/socket.c
index d70488a..9452cd0 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -43,6 +43,15 @@
# include <openssl/x509v3.h>
#endif
+enum {
+ SCK_CONNECTING,
+#ifdef HAVE_LIBSSL
+ SCK_STARTTLS,
+#endif
+ SCK_READY,
+ SCK_EOF
+};
+
static void
socket_fail( conn_t *conn )
{
@@ -67,11 +76,12 @@ ssl_return( const char *func, conn_t *conn, int ret )
case SSL_ERROR_SSL:
if (!(err = ERR_get_error())) {
if (ret == 0) {
- if (conn->state != SCK_CLOSING)
- error( "Socket error: secure %s %s:
unexpected EOF\n", func, conn->name );
- } else {
- sys_error( "Socket error: secure %s %s", func,
conn->name );
+ /* Callers take the short path out, so signal
higher layers from here. */
+ conn->state = SCK_EOF;
+ conn->read_callback( conn->callback_aux );
+ return 0;
}
+ sys_error( "Socket error: secure %s %s", func,
conn->name );
} else {
error( "Socket error: secure %s %s: %s\n", func,
conn->name, ERR_error_string( err, 0 ) );
}
@@ -582,10 +592,9 @@ do_read( conn_t *sock, char *buf, int len )
sys_error( "Socket error: read from %s", sock->name );
socket_fail( sock );
} else if (!n) {
- if (sock->state != SCK_CLOSING)
- error( "Socket error: read from %s: unexpected
EOF\n", sock->name );
- socket_fail( sock );
- return -1;
+ /* EOF. Callers take the short path out, so signal
higher layers from here. */
+ sock->state = SCK_EOF;
+ sock->read_callback( sock->callback_aux );
}
}
@@ -656,6 +665,8 @@ int
socket_read( conn_t *conn, char *buf, int len )
{
int n = conn->bytes;
+ if (!n && conn->state == SCK_EOF)
+ return -1;
if (n > len)
n = len;
memcpy( buf, conn->buf + conn->offset, n );
@@ -680,6 +691,8 @@ socket_read_line( conn_t *b )
memmove( b->buf, b->buf + b->offset, b->bytes );
b->offset = 0;
}
+ if (b->state == SCK_EOF)
+ return (void *)~0;
return 0;
}
n = p + 1 - s;
diff --git a/src/socket.h b/src/socket.h
index 20c3033..a420e49 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -29,15 +29,6 @@
#include <zlib.h>
#endif
-enum {
- SCK_CONNECTING,
-#ifdef HAVE_LIBSSL
- SCK_STARTTLS,
-#endif
- SCK_READY,
- SCK_CLOSING
-};
-
#ifdef HAVE_LIBSSL
typedef struct ssl_st SSL;
typedef struct ssl_ctx_st SSL_CTX;
------------------------------------------------------------------------------
Dive into the World of Parallel Programming. The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net/
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel