commit ac3b5186b0046a18db21f54b00c974c4bd73d731
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Thu Jun 9 13:27:50 2022 +0200

    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 b887400c..e92c53f1 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 802f69d0..a0565f40 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 9f11933a..f0784342 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 );


_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to