From ac3b5186b0046a18db21f54b00c974c4bd73d731 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 9 Jun 2022 13:27:50 +0200 Subject: [PATCH] don't notify about socket reads that fall short of expectations this will prospectively make the debug output less messy. --- src/drv_imap.c | 8 +++++-- src/socket.c | 59 ++++++++++++++++++++++++++++++++++++++------------ src/socket.h | 3 +++ 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/drv_imap.c b/src/drv_imap.c index b887400..e92c53f 100644 --- a/src/drv_imap.c +++ b/src/drv_imap.c @@ -1605,14 +1605,18 @@ imap_socket_read( void *aux ) if (ctx->parse_list_sts.level) { resp = parse_list_continue( ctx ); listret: - if (resp == LIST_PARTIAL) + if (resp == LIST_PARTIAL) { + socket_expect_bytes( &ctx->conn, ctx->parse_list_sts.need_bytes ); return; + } if (resp == LIST_BAD) break; continue; } - if (!(cmd = socket_read_line( &ctx->conn ))) + if (!(cmd = socket_read_line( &ctx->conn ))) { + socket_expect_bytes( &ctx->conn, 0 ); return; + } if (cmd == (void *)~0) { if (!ctx->expectEOF) error( "IMAP error: unexpected EOF from %s\n", ctx->conn.name ); diff --git a/src/socket.c b/src/socket.c index 802f69d..a0565f4 100644 --- a/src/socket.c +++ b/src/socket.c @@ -719,6 +719,33 @@ do_read( conn_t *sock, char *buf, uint len ) return n; } +static void +socket_filled( conn_t *conn, uint len ) +{ + uint off = conn->offset; + uint cnt = conn->bytes + len; + conn->bytes = cnt; + if (conn->wanted) { + // Fulfill as much of the request as still fits into the buffer + if (cnt < conn->wanted && off + cnt < sizeof(conn->buf)) + return; + } else { + // Need a full line + char *s = conn->buf + off; + char *p = memchr( s + conn->scanoff, '\n', cnt - conn->scanoff ); + if (!p) { + conn->scanoff = cnt; + if (off + cnt == sizeof(conn->buf)) { + memmove( conn->buf, conn->buf + off, cnt ); + conn->offset = 0; + } + return; + } + conn->scanoff = (uint)(p - s); + } + conn->read_callback( conn->callback_aux ); +} + #ifdef HAVE_LIBZ static void socket_fill_z( conn_t *sock ) @@ -745,10 +772,8 @@ socket_fill_z( conn_t *sock ) if (!sock->in_z->avail_out) conf_wakeup( &sock->z_fake, 0 ); - if ((len = (uint)((char *)sock->in_z->next_out - buf))) { - sock->bytes += len; - sock->read_callback( sock->callback_aux ); - } + if ((len = (uint)((char *)sock->in_z->next_out - buf))) + socket_filled( sock, len ); } #endif @@ -778,8 +803,7 @@ socket_fill( conn_t *sock ) if ((n = do_read( sock, buf, len )) <= 0) return; - sock->bytes += (uint)n; - sock->read_callback( sock->callback_aux ); + socket_filled( sock, (uint)n ); } } @@ -799,6 +823,21 @@ socket_expect_eof( conn_t *sock ) #endif } +void +socket_expect_bytes( conn_t *conn, uint len ) +{ + conn->wanted = len; + uint off = conn->offset; + if (off) { + uint cnt = conn->bytes; + if (off + len > sizeof(conn->buf) || + off + cnt == sizeof(conn->buf)) { + memmove( conn->buf, conn->buf + off, cnt ); + conn->offset = 0; + } + } +} + char * socket_read( conn_t *conn, uint min_len, uint max_len, uint *out_len ) { @@ -811,10 +850,6 @@ socket_read( conn_t *conn, uint min_len, uint max_len, uint *out_len ) if (cnt < min_len) { if (conn->state == SCK_EOF) return (void *)~0; - if (off + min_len > sizeof(conn->buf)) { - memmove( conn->buf, conn->buf + off, cnt ); - conn->offset = 0; - } return NULL; } uint n = (cnt < max_len) ? cnt : max_len; @@ -836,10 +871,6 @@ socket_read_line( conn_t *conn ) if (conn->state == SCK_EOF) return (void *)~0; conn->scanoff = cnt; - if (off + cnt == sizeof(conn->buf)) { - memmove( conn->buf, conn->buf + off, cnt ); - conn->offset = 0; - } return NULL; } uint n = (uint)(p + 1 - s); diff --git a/src/socket.h b/src/socket.h index 9f11933..f078434 100644 --- a/src/socket.h +++ b/src/socket.h @@ -99,6 +99,7 @@ typedef struct { uint offset; /* start of filled bytes in buffer */ uint bytes; /* number of filled bytes in buffer */ uint scanoff; /* offset to continue scanning for newline at, relative to 'offset' */ + uint wanted; // try to accumulate that many bytes before calling back; 0 => full line char buf[100000]; #ifdef HAVE_LIBZ char z_buf[100000]; @@ -121,6 +122,7 @@ static INLINE void socket_init( conn_t *conn, conn->fd = -1; conn->name = NULL; conn->write_buf_append = &conn->write_buf; + conn->wanted = 1; } void socket_connect( conn_t *conn, void (*cb)( int ok, void *aux ) ); void socket_start_tls(conn_t *conn, void (*cb)( int ok, void *aux ) ); @@ -128,6 +130,7 @@ void socket_start_deflate( conn_t *conn ); void socket_close( conn_t *sock ); 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 ); // 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_line( conn_t *conn );