summaryrefslogtreecommitdiffstats
path: root/libmail/imapidle.C
diff options
context:
space:
mode:
authorSam Varshavchik2013-08-19 16:39:41 -0400
committerSam Varshavchik2013-08-25 14:43:51 -0400
commit9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch)
tree7a81a04cb51efb078ee350859a64be2ebc6b8813 /libmail/imapidle.C
parenta9520698b770168d1f33d6301463bb70a19655ec (diff)
downloadcourier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2
Initial checkin
Imported from subversion report, converted to git. Updated all paths in scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'libmail/imapidle.C')
-rw-r--r--libmail/imapidle.C197
1 files changed, 197 insertions, 0 deletions
diff --git a/libmail/imapidle.C b/libmail/imapidle.C
new file mode 100644
index 0000000..2409754
--- /dev/null
+++ b/libmail/imapidle.C
@@ -0,0 +1,197 @@
+/*
+** Copyright 2003, Double Precision Inc.
+**
+** See COPYING for distribution information.
+*/
+#include "libmail_config.h"
+#include "imap.H"
+#include "imaphandler.H"
+#include "imapidle.H"
+
+using namespace std;
+
+mail::imapIdleHandler::imapIdleHandler(bool idleOnOffArg,
+ mail::callback *callbackArg)
+ : idleOnOff(idleOnOffArg), idling(false),
+ shouldTerminate(false), terminating(false),
+ callback(callbackArg)
+{
+}
+
+const char *mail::imapIdleHandler::getName()
+{
+ return "IDLE";
+}
+
+bool mail::imapIdleHandler::getTimeout(imap &imapAccount,
+ int &ioTimeout)
+{
+ if (waiting)
+ {
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ if (tv.tv_sec > waitingUntil.tv_sec ||
+ (tv.tv_sec == waitingUntil.tv_sec &&
+ tv.tv_usec >= waitingUntil.tv_usec))
+ {
+ waiting=false;
+
+ imapAccount.imapcmd("IDLE", "IDLE\r\n");
+ ioTimeout=0;
+ return false;
+ }
+ else
+ {
+ struct timeval t=waitingUntil;
+
+ t.tv_usec -= tv.tv_usec;
+
+ if (t.tv_usec < 0)
+ {
+ t.tv_usec += 1000000;
+ --t.tv_sec;
+ }
+ t.tv_sec -= tv.tv_sec;
+
+ ioTimeout=t.tv_sec * 1000 + t.tv_usec / 1000;
+
+ if (ioTimeout == 0)
+ ioTimeout=100;
+ return false;
+ }
+ }
+
+ ioTimeout = 15 * 60 * 1000;
+ return false;
+}
+
+void mail::imapIdleHandler::timedOut(const char *errmsg)
+{
+ mail::callback *c=callback;
+
+ callback=NULL;
+
+ if (c)
+ callbackTimedOut(*c, errmsg);
+}
+
+mail::imapIdleHandler::~imapIdleHandler()
+{
+ mail::callback *c=callback;
+
+ callback=NULL;
+
+ if (c)
+ c->success("OK");
+}
+
+bool mail::imapIdleHandler::untaggedMessage(imap &imapAccount,
+ std::string name)
+{
+ return false;
+}
+
+void mail::imapIdleHandler::installed(imap &imapAccount)
+{
+ if (!idleOnOff || !imapAccount.wantIdleMode
+ || shouldTerminate || !imapAccount.task_queue.empty())
+ {
+ imapAccount.uninstallHandler(this);
+ return;
+ }
+
+ waiting=true;
+
+ // Wait 1/10th of a second before issuing an IDLE. When we're in
+ // IDLE mode, and a new task is started, we terminate and a requeue
+ // ourselves after the pending command. We don't want to immediately
+ // reenter the IDLE mode because if the first task queues up a second
+ // task we would have to immediately get out of IDLE mode right away,
+ // so wait 1/10th of a second to see if anything is up.
+
+ gettimeofday(&waitingUntil, NULL);
+ if ((waitingUntil.tv_usec += 100000) > 1000000)
+ {
+ waitingUntil.tv_usec %= 1000000;
+ ++waitingUntil.tv_sec;
+ }
+}
+
+
+bool mail::imapIdleHandler::taggedMessage(imap &imapAccount, std::string name,
+ std::string message,
+ bool okfail, std::string errmsg)
+{
+ mail::callback *c=callback;
+
+ callback=NULL;
+
+ imapAccount.uninstallHandler(this);
+
+ if (imapAccount.wantIdleMode)
+ {
+ // Reinstall, when we're done
+
+ imapAccount.installForegroundTask(new imapIdleHandler(true,
+ NULL));
+ c=NULL;
+ }
+
+ if (c)
+ {
+ if (okfail)
+ c->success(errmsg);
+ else
+ c->fail(errmsg);
+ }
+ return true;
+}
+
+bool mail::imapIdleHandler::continuationRequest(imap &imapAccount,
+ std::string request)
+{
+ idling=true;
+ if (shouldTerminate)
+ terminateIdle(imapAccount);
+
+ mail::callback *c=callback;
+
+ callback=NULL;
+
+ if (c)
+ c->success("Monitoring folder for changes...");
+
+ return true;
+}
+
+void mail::imapIdleHandler::anotherHandlerInstalled(imap &imapAccount)
+{
+ if (waiting)
+ {
+ imapAccount.uninstallHandler(this);
+ return;
+ }
+
+ shouldTerminate=true;
+ if (idling)
+ terminateIdle(imapAccount);
+}
+
+void mail::imapIdleHandler::terminateIdle(imap &imapAccount)
+{
+ if (terminating)
+ return;
+ terminating=true;
+
+ mail::callback *c=callback;
+
+ callback=NULL;
+
+ if (c)
+ c->success("OK");
+
+ imapAccount.imapcmd("", "DONE\r\n");
+}
+