fetchmail-friends
[Top] [All Lists]

Re: [fetchmail] Regression: broken-up SIZE fetch FATAL for POP3 uidl keep

2003-10-16 15:17:03
Matthias Andree <ma(_at_)dt(_dot_)e-technik(_dot_)uni-dortmund(_dot_)de> writes:

* Sunil Shetye's patches to break up fetching of sizes and UIDLs.

This is harmful for POP3:

I suggest the enclosed patch to pop3.c.

NOTE that the current code need optimization, if I have unseen articles
3 and 47, fetchmail will happily request LIST for articles 3...47 rather
than just 3 and 47. In cases where the message numbers are far apart,
this involves considerable overhead - which could be alleviated by
pipelining the list commands, which needs either asynchronous reading
while sending the commands, or knowing the send buffer, to avoid
deadlocks. Unfortunately, I don't have the time to delve deeper into the
code and look around.

Note that such a pipelining function would be of universal use, so it
should not be in pop3.c or something. I'd think the best approach is to
call a "sender" function with the command and a callback, and the sender
will call the receiver when the send buffer is full and call the
callback function for each reply received.

See the ESMTP PIPELINING RFC for details on the deadlock avoidance
requirements.

--- fetchmail-6.2.5/pop3.c      2003-10-15 21:22:31.000000000 +0200
+++ fetchmail-6.2.5-ma1/pop3.c  2003-10-17 00:07:18.000000000 +0200
@@ -911,25 +911,24 @@
 static int pop3_getpartialsizes(int sock, int first, int last, int *sizes)
 /* capture the size of message #first */
 {
-    int        ok;
+    int        ok, i;
     char buf [POPBUFSIZE+1];
     unsigned int num, size;
 
-    /* for POP3, we can get the size of one mail only! */
-    if (first != last)
-    {
-       report(stderr, "cannot get a range of message sizes (%d-%d).\n", first, 
last);
-       return(PS_PROTOCOL);
-    }
-    gen_send(sock, "LIST %d", first);
-    if ((ok = pop3_ok(sock, buf)) != 0)
-       return(ok);
-    if (sscanf(buf, "%u %u", &num, &size) == 2) {
-       if (num == first)
-           sizes[0] = size;
-       else
-           /* warn about possible attempt to induce buffer overrun */
-           report(stderr, "Warning: ignoring bogus data for message sizes 
returned by server.\n");
+    for (i = first; i <= last; i++) {
+       gen_send(sock, "LIST %d", i);
+       if ((ok = pop3_ok(sock, buf)) != 0)
+           return(ok);
+       if (sscanf(buf, "%u %u", &num, &size) == 2) {
+           if (num == i)
+               sizes[i - first] = size;
+           else
+               /* warn about possible attempt to induce buffer overrun
+                *
+                * we expect server reply message number and requested
+                * message number to match */
+               report(stderr, "Warning: ignoring bogus data for message sizes 
returned by server.\n");
+       }
     }
     return(ok);
 }

-- 
Matthias Andree

Encrypt your mail: my GnuPG key ID is 0x052E7D95