Browse Source

*** close IMAP socket ourselves instead of waiting for the server

*** this violates the RFC

some ms exchange versions and misconfigured tunnels just hang.

REFMAIL: <87czqj9xrw.fsf@vonfry.name>
REFMAIL: <CAC089cxhrYc+PyW-FGevaevQZ2GF98DBP25WVzUS7oEsMa73kg@mail.gmail.com>
wip/imap-client-close
Oswald Buddenhagen 3 years ago
parent
commit
9a701053e7
  1. 23
      src/drv_imap.c
  2. 9
      src/socket.c
  3. 1
      src/socket.h

23
src/drv_imap.c

@ -168,9 +168,8 @@ union imap_store {
uint buffer_mem; // Memory currently occupied by buffers in the queue uint buffer_mem; // Memory currently occupied by buffers in the queue
// Used during sequential operations like connect // Used during sequential operations like connect
enum { GreetingPending = 0, GreetingBad, GreetingOk, GreetingPreauth } greeting; enum { GreetingPending = 0, GreetingOk, GreetingPreauth } greeting;
int expectBYE; // LOGOUT is in progress int expectBYE; // LOGOUT is in progress
int expectEOF; // received LOGOUT's OK or unsolicited BYE
int canceling; // imap_cancel_cmds() is in progress int canceling; // imap_cancel_cmds() is in progress
union { union {
void (*imap_open)( int sts, void *aux ); void (*imap_open)( int sts, void *aux );
@ -1759,8 +1758,7 @@ imap_socket_read( void *aux )
return; return;
} }
if (cmd == (void *)~0) { if (cmd == (void *)~0) {
if (!ctx->expectEOF) error( "IMAP error: unexpected EOF from %s\n", ctx->conn.name );
error( "IMAP error: unexpected EOF from %s\n", ctx->conn.name );
/* A clean shutdown sequence ends with bad_callback as well (see imap_cleanup()). */ /* A clean shutdown sequence ends with bad_callback as well (see imap_cleanup()). */
break; break;
} }
@ -1796,14 +1794,10 @@ imap_socket_read( void *aux )
} }
} else if (equals( arg, argl, "BYE", 3 )) { } else if (equals( arg, argl, "BYE", 3 )) {
if (!ctx->expectBYE) { if (!ctx->expectBYE) {
ctx->greeting = GreetingBad;
error( "IMAP error: unexpected BYE response: %s\n", cmd ); error( "IMAP error: unexpected BYE response: %s\n", cmd );
/* We just wait for the server to close the connection now. */ break;
ctx->expectEOF = 1;
socket_expect_eof( &ctx->conn );
} else {
/* We still need to wait for the LOGOUT's tagged OK. */
} }
// We still need to wait for the LOGOUT's tagged OK.
} else if (ctx->greeting == GreetingPending) { } else if (ctx->greeting == GreetingPending) {
error( "IMAP error: bogus greeting response %s\n", arg ); error( "IMAP error: bogus greeting response %s\n", arg );
break; break;
@ -2085,14 +2079,9 @@ imap_cleanup( void )
static void static void
imap_cleanup_p2( imap_store_t *ctx, imap_cleanup_p2( imap_store_t *ctx,
imap_cmd_t *cmd ATTR_UNUSED, int response ) imap_cmd_t *cmd ATTR_UNUSED, int response ATTR_UNUSED )
{ {
if (response == RESP_NO) { imap_cancel_store( &ctx->gen );
imap_cancel_store( &ctx->gen );
} else if (response == RESP_OK) {
ctx->expectEOF = 1;
socket_expect_eof( &ctx->conn );
}
} }
/******************* imap_open_store *******************/ /******************* imap_open_store *******************/

9
src/socket.c

@ -822,15 +822,6 @@ socket_expect_activity( conn_t *conn, int expect )
conf_wakeup( &conn->fd_timeout, expect ? conn->conf->timeout : -1 ); conf_wakeup( &conn->fd_timeout, expect ? conn->conf->timeout : -1 );
} }
void
socket_expect_eof( conn_t *sock )
{
#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF // implies HAVE_LIBSSL
if (sock->ssl)
SSL_set_options( sock->ssl, SSL_OP_IGNORE_UNEXPECTED_EOF );
#endif
}
void void
socket_expect_bytes( conn_t *conn, uint len ) socket_expect_bytes( conn_t *conn, uint len )
{ {

1
src/socket.h

@ -134,7 +134,6 @@ void socket_start_tls(conn_t *conn, void (*cb)( int ok, void *aux ) );
void socket_start_deflate( conn_t *conn ); void socket_start_deflate( conn_t *conn );
void socket_close( conn_t *sock ); void socket_close( conn_t *sock );
void socket_expect_activity( conn_t *sock, int expect ); void socket_expect_activity( conn_t *sock, int expect );
void socket_expect_eof( conn_t *sock );
void socket_expect_bytes( conn_t *sock, uint len ); void socket_expect_bytes( conn_t *sock, uint len );
// Don't free return values. These functions never wait. // Don't free return values. These functions never wait.
char *socket_read( conn_t *conn, uint min_len, uint max_len, uint *out_len ); char *socket_read( conn_t *conn, uint min_len, uint max_len, uint *out_len );

Loading…
Cancel
Save