package i2p.susi.webmail.pop3; import i2p.susi.debug.Debug; import i2p.susi.webmail.WebMail; import i2p.susi.util.Config; import net.i2p.I2PAppContext; import net.i2p.util.I2PAppThread; import net.i2p.util.SimpleTimer2; /** * Close the POP3 connection after a certain idle time * * @since 0.9.13 */ class IdleCloser { private final POP3MailBox mailbox; private final SimpleTimer2.TimedEvent timer; private volatile boolean isClosing; private volatile boolean isDead; private static final long CHECK_TIME = 30*1000; // POP3 RFC 1939 server minimum idle timeout is 10 minutes // pop3.postman.i2p timeout is 5 minutes // We want to be less than that. private static final int DEFAULT_IDLE_SECONDS = 4*60; private static final int MIN_IDLE_CONFIG = 60; public IdleCloser(POP3MailBox mailbox) { this.mailbox = mailbox; timer = new Checker(); } public void cancel() { isDead = true; timer.cancel(); } private static long getMaxIdle() { int seconds = DEFAULT_IDLE_SECONDS; String con = Config.getProperty(WebMail.CONFIG_IDLE_SECONDS); if (con != null) { try { int secs = Integer.parseInt(con); if (secs < MIN_IDLE_CONFIG) secs = MIN_IDLE_CONFIG; seconds = secs; } catch (NumberFormatException nfe) {} } return seconds * 1000L; } private class Checker extends SimpleTimer2.TimedEvent { public Checker() { super(I2PAppContext.getGlobalContext().simpleTimer2(), getMaxIdle() + 5*1000); } public void timeReached() { if (isDead) return; // unsynchronized here, synch in thread only if (!mailbox.isConnected()) return; if (!isClosing) { long config = getMaxIdle(); long idle = System.currentTimeMillis() - mailbox.getLastActivity(); long remaining = config - idle; if (remaining <= 0) { Debug.debug(Debug.DEBUG, "Threading close after " + idle + " ms idle"); Thread t = new Closer(); isClosing = true; t.start(); } else { Debug.debug(Debug.DEBUG, "Not closing after " + idle + " ms idle"); schedule(remaining + 5000); } } } } private class Closer extends I2PAppThread { public Closer() { super("Susimail-Closer"); } public void run() { try { synchronized (mailbox.getLock()) { if (!mailbox.isConnected()) return; long config = getMaxIdle(); long idle = System.currentTimeMillis() - mailbox.getLastActivity(); long remaining = config - idle; if (remaining <= 0) { // If we have items to delete, wait for the response code, // otherwise the DelayedDeleter thread will have to run later. // Since we are threaded we can do that here. boolean shouldWait = mailbox.hasQueuedDeletions(); mailbox.close(shouldWait); isDead = true; } else { timer.schedule(remaining + 5000); } } } finally { isClosing = false; } } } }