From ed08b22decaf1f7748dc69b859271f5213065955 Mon Sep 17 00:00:00 2001 From: Kuroneko Date: Fri, 12 Oct 2018 08:30:24 +1100 Subject: [PATCH] add-ons/mail_daemon: IMAP: limit UIDs in UID FETCH Some IMAP servers (such as dovecot) have hard line length limits for commands. The way UID FETCH was being scheduled was creating FETCHes longer than the maximum length. Limit these to a reasonable number of UIDs per fetch, such that we have a hope of success when facing monsterous mailboxes. Change-Id: I8a2184eec1b8fcab6f7914a9b14ad008700b96d1 Signed-off-by: Augustin Cavalier Reviewed-on: https://review.haiku-os.org/c/haiku/+/626 Style fixes by me, and also replaced emplace_back with push_back for GCC2 compatibility. --- .../imap/IMAPConnectionWorker.cpp | 46 +++++++++++++++---- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp index ba0c2c2f82..58f978cfc9 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp @@ -21,6 +21,7 @@ using IMAP::MessageUIDList; static const uint32 kMaxFetchEntries = 500; static const uint32 kMaxDirectDownloadSize = 4096; +static const uint32 kMaxUIDsPerFetch = 32; class WorkerPrivate { @@ -236,7 +237,7 @@ private: class FetchHeadersCommand : public SyncCommand, public IMAP::FetchListener { public: FetchHeadersCommand(IMAPFolder& folder, IMAPMailbox& mailbox, - MessageUIDList& uids, int32 bodyFetchLimit) + const MessageUIDList& uids, int32 bodyFetchLimit) : fFolder(folder), fMailbox(mailbox), @@ -402,16 +403,28 @@ public: if (from == 1) { fFolder->MessageEntriesFetched(); - if (fUIDsToFetch.size() > 0) { - // Add pending command to fetch the message headers - WorkerCommand* command = new FetchHeadersCommand(*fFolder, - *fMailbox, fUIDsToFetch, - WorkerPrivate(worker).BodyFetchLimit()); - if (!fFetchCommands.AddItem(command)) - delete command; + IMAP::MessageUIDList uidsForSubFetch; - fUIDsToFetch.clear(); + IMAP::MessageUIDList::iterator messageIterator + = fUIDsToFetch.begin(); + while (messageIterator != fUIDsToFetch.end()) { + uidsForSubFetch.push_back(*messageIterator); + messageIterator++; + + size_t uidsQueued = uidsForSubFetch.size(); + if (uidsQueued >= kMaxUIDsPerFetch + || (messageIterator == fUIDsToFetch.end() + && uidsQueued > 0)) { + status_t fetchResult = QueueFetch(worker, + uidsForSubFetch); + if (fetchResult != B_OK) { + printf("IMAP: Error occured queueing UID FETCH\n"); + return fetchResult; + } + uidsForSubFetch.clear(); + } } + fUIDsToFetch.clear(); fState = SELECT; } } @@ -424,6 +437,21 @@ public: return fState == DONE; } +private: + status_t QueueFetch(IMAPConnectionWorker& worker, + const IMAP::MessageUIDList& uids) + { + // Add pending command to fetch the message headers + WorkerCommand* command = new FetchHeadersCommand(*fFolder, + *fMailbox, uids, + WorkerPrivate(worker).BodyFetchLimit()); + if (!fFetchCommands.AddItem(command)) { + delete command; + return B_ERROR; + } + return B_OK; + } + private: enum State { INIT,