status_t IMAPMailbox::StartWatchingMailbox(sem_id startedSem) { atomic_set(&fWatching, 1); bool firstIDLE = true; // refresh every 29 min bigtime_t timeout = 1000 * 1000 * 60 * 29; // 29 min status_t status; while (true) { int32 commandID = NextCommandID(); TRACE("IDLE ...\n"); status = SendCommand("IDLE", commandID); if (firstIDLE) { release_sem(startedSem); firstIDLE = false; } if (status != B_OK) break; status = HandleResponse(commandID, timeout, false); ProcessAfterQuacks(kIMAP4ClientTimeout); if (atomic_get(&fWatching) == 0) break; if (status == B_TIMED_OUT) { TRACE("Renew IDLE connection.\n"); status = SendRawCommand("DONE"); if (status != B_OK) break; // handle IDLE response and more status = ProcessCommand("NOOP"); if (status != B_OK) break; else continue; } if (status != B_OK) break; } atomic_set(&fWatching, 0); return status; }
status_t Protocol::ProcessCommand(Command& command, bigtime_t timeout) { BString commandString = command.CommandString(); if (commandString.IsEmpty()) return B_BAD_VALUE; Handler* handler = dynamic_cast<Handler*>(&command); if (handler != NULL && !AddHandler(*handler)) return B_NO_MEMORY; int32 commandID = NextCommandID(); status_t status = SendCommand(commandID, commandString.String()); if (status == B_OK) { fOngoingCommands[commandID] = &command; status = HandleResponse(&command, timeout); } if (handler != NULL) RemoveHandler(*handler); return status; }