Author: toad
Date: 2007-10-23 23:09:49 +0000 (Tue, 23 Oct 2007)
New Revision: 15514
Added:
trunk/plugins/Freemail/src/freemail/support/
trunk/plugins/Freemail/src/freemail/support/io/
trunk/plugins/Freemail/src/freemail/support/io/LineReader.java
trunk/plugins/Freemail/src/freemail/support/io/LineReadingInputStream.java
trunk/plugins/Freemail/src/freemail/support/io/TooLongException.java
Modified:
trunk/plugins/Freemail/build.xml
trunk/plugins/Freemail/src/freemail/AckProcrastinator.java
trunk/plugins/Freemail/src/freemail/Freemail.java
trunk/plugins/Freemail/src/freemail/MailHeaderFilter.java
trunk/plugins/Freemail/src/freemail/MessageSender.java
trunk/plugins/Freemail/src/freemail/RTSFetcher.java
trunk/plugins/Freemail/src/freemail/SingleAccountWatcher.java
trunk/plugins/Freemail/src/freemail/fcp/FCPConnection.java
trunk/plugins/Freemail/src/freemail/fcp/FCPMessage.java
trunk/plugins/Freemail/src/freemail/imap/IMAPListener.java
trunk/plugins/Freemail/src/freemail/smtp/SMTPListener.java
Log:
Apply patch from ET on Frost to make Freemail a plugin.
Modified: trunk/plugins/Freemail/build.xml
===================================================================
--- trunk/plugins/Freemail/build.xml 2007-10-23 23:03:14 UTC (rev 15513)
+++ trunk/plugins/Freemail/build.xml 2007-10-23 23:09:49 UTC (rev 15514)
@@ -37,7 +37,11 @@
<!-- Bundle the whole lot together, unless anyone whinges.
It makes it much easier to run -->
- <javac srcdir="${src}" destdir="${build}" debug="on"
optimize="on" source="1.4" />
+ <javac srcdir="${src}" destdir="${build}" debug="on"
optimize="on" source="1.4">
+ <classpath>
+ <pathelement
location="${lib}/freenet-cvs-snapshot.jar"/>
+ </classpath>
+ </javac>
<copy todir="${build}/freemailgui/text">
<fileset dir="${src}/freemailgui/text" />
</copy>
@@ -52,6 +56,7 @@
<jar jarfile="${lib}/Freemail.jar" basedir="${build}">
<manifest>
<attribute name="Main-Class"
value="freemail.Freemail"/>
+ <attribute name="Plugin-Main-Class"
value="freemail.Freemail"/>
<attribute name="Built-By"
value="${user.name}"/>
<section name="common">
<attribute name="Implementation-Title"
value="Freemail"/>
Modified: trunk/plugins/Freemail/src/freemail/AckProcrastinator.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/AckProcrastinator.java 2007-10-23
23:03:14 UTC (rev 15513)
+++ trunk/plugins/Freemail/src/freemail/AckProcrastinator.java 2007-10-23
23:09:49 UTC (rev 15514)
@@ -39,6 +39,20 @@
* Freemail is run more or less permanantly.
*/
public class AckProcrastinator implements Runnable {
+ /**
+ * Object that is used for syncing purposes.
+ */
+ protected final Object syncObject = new Object();
+
+ /**
+ * Whether the thread this service runs in should stop.
+ */
+ protected volatile boolean stopping = false;
+
+ /**
+ * The currently running threads.
+ */
+ private Thread thread;
private static final long MAX_DELAY = 12 * 60 * 60 * 1000;
private static final int RANDOM_ACK_SIZE = 512;
@@ -65,7 +79,8 @@
}
public void run() {
- while (true) {
+ thread = Thread.currentThread();
+ while (!stopping) {
File[] acks = getAckDir().listFiles();
int i;
@@ -116,8 +131,30 @@
} catch (InterruptedException ie) {
}
}
+ synchronized (syncObject) {
+ thread = null;
+ syncObject.notify();
+ }
+
}
+ /**
+ * This method will block until the
+ * thread has exited.
+ */
+ public void kill() {
+ synchronized (syncObject) {
+ stopping = true;
+ while (thread != null) {
+ syncObject.notify();
+ try {
+ syncObject.wait(1000);
+ } catch (InterruptedException ie1) {
+ }
+ }
+ }
+ }
+
/** As put(String key, String data), but insert random data
*/
public static synchronized void put(String key) {
Modified: trunk/plugins/Freemail/src/freemail/Freemail.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/Freemail.java 2007-10-23 23:03:14 UTC
(rev 15513)
+++ trunk/plugins/Freemail/src/freemail/Freemail.java 2007-10-23 23:09:49 UTC
(rev 15514)
@@ -23,6 +23,8 @@
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
import freemail.fcp.FCPContext;
import freemail.fcp.FCPConnection;
@@ -30,8 +32,16 @@
import freemail.smtp.SMTPListener;
import freemail.config.Configurator;
import freemail.config.ConfigClient;
+import freenet.pluginmanager.FredPlugin;
+import freenet.pluginmanager.FredPluginHTTP;
+import freenet.pluginmanager.FredPluginHTTPAdvanced;
+import freenet.pluginmanager.FredPluginThreadless;
+import freenet.pluginmanager.PluginHTTPException;
+import freenet.pluginmanager.PluginRespirator;
+import freenet.support.HTMLNode;
+import freenet.support.api.HTTPRequest;
-public class Freemail implements ConfigClient {
+public class Freemail implements ConfigClient, FredPlugin, FredPluginHTTP,
FredPluginHTTPAdvanced, FredPluginThreadless {
// version info
public static final int VER_MAJOR = 0;
public static final int VER_MINOR = 1;
@@ -48,6 +58,15 @@
private static File tempdir;
private static FCPConnection fcpconn;
+
+ //Plugin
+ private static PluginRespirator pr;
+ private ArrayList singleAccountWatcherList = new ArrayList();
+ private MessageSender sender;
+ private SMTPListener smtpl;
+ private AckProcrastinator ackinserter;
+ private IMAPListener imapl;
+
public static File getTempDir() {
return Freemail.tempdir;
}
@@ -222,4 +241,156 @@
Freemail.globaldatadir = new File(val);
}
}
+
+ // Plugin
+ public void runPlugin(PluginRespirator pr) {
+ Freemail.pr = pr;
+ String cfgfile = CFGFILE;
+ Configurator cfg = new Configurator(new File(cfgfile));
+ FCPContext fcpctx = new FCPContext();
+
+ cfg.register("fcp_host", fcpctx, "localhost");
+ cfg.register("fcp_port", fcpctx, "9481");
+
+ Freemail.fcpconn = new FCPConnection(fcpctx);
+ Thread fcpthread = new Thread(fcpconn, "Freemail FCP
Connection");
+ fcpthread.setDaemon(true);
+ fcpthread.start();
+ cfg.register("globaldatadir", new Freemail(), GLOBALDATADIR);
+ if (!globaldatadir.exists()) {
+ if(!globaldatadir.mkdir()) {
+ System.out.println("Freemail plugin: Couldn't
create global data directory. Please ensure that the user you are running
Freemail as has write access to its working directory");
+ return;
+ }
+ }
+ cfg.register("datadir", new Freemail(), Freemail.DATADIR);
+ if (!Freemail.datadir.exists()) {
+ if (!Freemail.datadir.mkdir()) {
+ System.out.println("Freemail plugin: Couldn't
create data directory. Please ensure that the user you are running Freemail as
has write access to its working directory");
+ return;
+ }
+ }
+ cfg.register("tempdir", new Freemail(), Freemail.TEMPDIRNAME);
+ if (!Freemail.tempdir.exists()) {
+ if (!Freemail.tempdir.mkdir()) {
+ System.out.println("Freemail plugin: Couldn't
create temporary directory. Please ensure that the user you are running
Freemail as has write access to its working directory");
+ return;
+ }
+ }
+ File[] files = Freemail.datadir.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].getName().equals(".") ||
files[i].getName().equals(".."))
+ continue;
+ if (!files[i].isDirectory()) continue;
+
+ SingleAccountWatcher saw = new
SingleAccountWatcher(files[i]);
+ singleAccountWatcherList.add(saw);
+ Thread t = new Thread(saw, "Freemail Account Watcher
for "+files[i].getName());
+ t.setDaemon(true);
+ t.start();
+ }
+
+ // and a sender thread
+ sender = new MessageSender(Freemail.datadir);
+ Thread senderthread = new Thread(sender, "Freemail Message
sender");
+ senderthread.setDaemon(true);
+ senderthread.start();
+
+ // start the SMTP Listener
+ smtpl = new SMTPListener(sender, cfg);
+ Thread smtpthread = new Thread(smtpl, "Freemail SMTP Listener");
+ smtpthread.setDaemon(true);
+ smtpthread.start();
+
+ // start the delayed ACK inserter
+ File ackdir = new File(globaldatadir, ACKDIR);
+ AckProcrastinator.setAckDir(ackdir);
+ ackinserter = new AckProcrastinator();
+ Thread ackinsthread = new Thread(ackinserter, "Freemail Delayed
ACK Inserter");
+ ackinsthread.setDaemon(true);
+ ackinsthread.start();
+
+ // start the IMAP listener
+ imapl = new IMAPListener(cfg);
+ Thread imaplthread = new Thread(imapl, "Freemail IMAP
Listener");
+ imaplthread.setDaemon(true);
+ imaplthread.start();
+ }
+
+ public void terminate() {
+ Iterator it = singleAccountWatcherList.iterator();
+ while(it.hasNext()) {
+ ((SingleAccountWatcher)it.next()).kill();
+ it.remove();
+ }
+ sender.kill();
+ ackinserter.kill();
+ smtpl.kill();
+ imapl.kill();
+ fcpconn.kill();
+ return;
+ }
+
+ public String handleHTTPGet(HTTPRequest request) throws
PluginHTTPException {
+ HTMLNode pageNode = pr.getPageMaker().getPageNode("Freemail
plugin", false, null);
+ HTMLNode contentNode =
pr.getPageMaker().getContentNode(pageNode);
+
+ if(request.getParam("add").equals("Add account")) {
+ if(!(request.getParam("name").equals("") ||
request.getParam("password").equals(""))) {
+ try {
+
AccountManager.Create(request.getParam("name"));
+
AccountManager.ChangePassword(request.getParam("name"),
request.getParam("password"));
+
if(!request.getParam("domain").equals("")) {
+
AccountManager.addShortAddress(request.getParam("name"),
request.getParam("domain"));
+ }
+ Thread t = new Thread(new
SingleAccountWatcher(new File(DATADIR, request.getParam("name"))), "Account
Watcher for "+request.getParam("name"));
+ t.setDaemon(true);
+ t.start();
+ HTMLNode addedBox =
contentNode.addChild("div", "class", "infobox");
+ addedBox.addChild("div", "class",
"infobox-header", "Added account");
+ addedBox.addChild("div", "class",
"infobox-content", "Account for " + request.getParam("name") + " is created");
+
+ } catch (IOException ioe) {
+ HTMLNode errorBox =
contentNode.addChild("div", "class", "infobox-error");
+ errorBox.addChild("div", "class",
"infobox-header", "IO Error");
+ errorBox.addChild("div", "class",
"infobox-content", "Couldn't create account. Please check write access to
Freemail's working directory. If you want to overwrite your account, delete the
appropriate directory manually in 'data' first. Freemail will intentionally not
overwrite it. Error: "+ioe.getMessage());
+ } catch (Exception e) {
+ HTMLNode errorBox =
contentNode.addChild("div", "class", "infobox-error");
+ errorBox.addChild("div", "class",
"infobox-header", "Error");
+ errorBox.addChild("div", "class",
"infobox-content", "Couldn't change password for "+request.getParam("name")+".
"+e.getMessage());
+ }
+ } else {
+ HTMLNode errorBox = contentNode.addChild("div",
"class", "infobox-error");
+ errorBox.addChild("div", "class",
"infobox-header", "Error");
+ errorBox.addChild("div", "class",
"infobox-content", "Couldn't create account, name or password is missing");
+ }
+ }
+
+ HTMLNode addBox = contentNode.addChild("div", "class",
"infobox");
+ addBox.addChild("div", "class", "infobox-header", "Add
account");
+ HTMLNode table = addBox.addChild("div", "class",
"infobox-content").addChild("form").addChild("table", "class", "plugintable");
+ HTMLNode tableRowName = table.addChild("tr");
+ tableRowName.addChild("td", "Name");
+ tableRowName.addChild("td").addChild("input", new String[] {
"type", "name", "value", "size" }, new String[] { "text", "name", "", "30" });
+ HTMLNode tableRowPassword = table.addChild("tr");
+ tableRowPassword.addChild("td", "Password");
+ tableRowPassword.addChild("td").addChild("input", new String[]
{ "type", "name", "value", "size" }, new String[] { "password", "password", "",
"30" });
+ HTMLNode tableRowDomain = table.addChild("tr");
+ tableRowDomain.addChild("td", "Domain");
+ tableRowDomain.addChild("td").addChild("input", new String[] {
"type", "name", "value", "size" }, new String[] { "text", "domain", "", "30" });
+ HTMLNode tableRowSubmit = table.addChild("tr");
+ tableRowSubmit.addChild("td");
+ tableRowSubmit.addChild("td").addChild("input", new String[] {
"type", "name", "value" }, new String[] { "submit", "add", "Add account"});
+
+ return pageNode.generate();
+ }
+
+ public String handleHTTPPost(HTTPRequest request) throws
PluginHTTPException {
+ return null;
+ }
+
+ public String handleHTTPPut(HTTPRequest request) throws
PluginHTTPException {
+ return null;
+ }
+
}
Modified: trunk/plugins/Freemail/src/freemail/MailHeaderFilter.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/MailHeaderFilter.java 2007-10-23
23:03:14 UTC (rev 15513)
+++ trunk/plugins/Freemail/src/freemail/MailHeaderFilter.java 2007-10-23
23:09:49 UTC (rev 15514)
@@ -29,7 +29,6 @@
import java.io.BufferedReader;
import java.io.IOException;
import java.lang.StringBuffer;
-import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
Modified: trunk/plugins/Freemail/src/freemail/MessageSender.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/MessageSender.java 2007-10-23
23:03:14 UTC (rev 15513)
+++ trunk/plugins/Freemail/src/freemail/MessageSender.java 2007-10-23
23:09:49 UTC (rev 15514)
@@ -33,6 +33,20 @@
import freemail.utils.DateStringFactory;
public class MessageSender implements Runnable {
+ /**
+ * Object that is used for syncing purposes.
+ */
+ protected final Object syncObject = new Object();
+
+ /**
+ * Whether the thread this service runs in should stop.
+ */
+ protected volatile boolean stopping = false;
+
+ /**
+ * The currently running threads.
+ */
+ private Thread thread;
public static final String OUTBOX_DIR = "outbox";
private static final int MIN_RUN_TIME = 60000;
public static final String NIM_KEY_PREFIX = "KSK at freemail-nim-";
@@ -92,12 +106,16 @@
public void run() {
this.senderthread = Thread.currentThread();
- while (true) {
+ thread = Thread.currentThread();
+ while (!stopping) {
long start = System.currentTimeMillis();
// iterate through users
File[] files = this.datadir.listFiles();
for (int i = 0; i < files.length; i++) {
+ if(stopping) {
+ break;
+ }
if (files[i].getName().startsWith("."))
continue;
File outbox = new File(files[i], OUTBOX_DIR);
@@ -108,6 +126,10 @@
}
// don't spin around the loop if nothing's
// going on
+ if(stopping) {
+ break;
+ }
+
long runtime = System.currentTimeMillis() - start;
if (MIN_RUN_TIME - runtime > 0) {
@@ -117,7 +139,28 @@
}
}
}
+ synchronized (syncObject) {
+ thread = null;
+ syncObject.notify();
+ }
}
+
+ /**
+ * This method will block until the
+ * thread has exited.
+ */
+ public void kill() {
+ synchronized (syncObject) {
+ stopping = true;
+ while (thread != null) {
+ syncObject.notify();
+ try {
+ syncObject.wait(1000);
+ } catch (InterruptedException ie1) {
+ }
+ }
+ }
+ }
private void sendDir(File accdir, File dir) {
File[] files = dir.listFiles();
Modified: trunk/plugins/Freemail/src/freemail/RTSFetcher.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/RTSFetcher.java 2007-10-23 23:03:14 UTC
(rev 15513)
+++ trunk/plugins/Freemail/src/freemail/RTSFetcher.java 2007-10-23 23:09:49 UTC
(rev 15514)
@@ -22,6 +22,8 @@
package freemail;
import freemail.fcp.HighLevelFCPClient;
+import freemail.support.io.LineReadingInputStream;
+import freemail.support.io.TooLongException;
import freemail.utils.DateStringFactory;
import freemail.utils.PropsFile;
@@ -50,8 +52,6 @@
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.DataLengthException;
-import freenet.support.io.LineReadingInputStream;
-import freenet.support.io.TooLongException;
import org.archive.util.Base32;
Modified: trunk/plugins/Freemail/src/freemail/SingleAccountWatcher.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/SingleAccountWatcher.java
2007-10-23 23:03:14 UTC (rev 15513)
+++ trunk/plugins/Freemail/src/freemail/SingleAccountWatcher.java
2007-10-23 23:09:49 UTC (rev 15514)
@@ -28,6 +28,20 @@
import freemail.utils.EmailAddress;
public class SingleAccountWatcher implements Runnable {
+ /**
+ * Object that is used for syncing purposes.
+ */
+ protected final Object syncObject = new Object();
+
+ /**
+ * Whether the thread this service runs in should stop.
+ */
+ protected volatile boolean stopping = false;
+
+ /**
+ * The currently running threads.
+ */
+ private Thread thread;
public static final String CONTACTS_DIR = "contacts";
public static final String INBOUND_DIR = "inbound";
public static final String OUTBOUND_DIR = "outbound";
@@ -85,7 +99,8 @@
}
public void run() {
- while (true) {
+ thread = Thread.currentThread();
+ while (!stopping) {
long start = System.currentTimeMillis();
// is it time we inserted the mailsite?
@@ -95,7 +110,9 @@
this.mailsite_last_upload =
System.currentTimeMillis();
}
}
-
+ if(stopping) {
+ break;
+ }
// send any messages queued in contact outboxes
File[] obcontacts = this.obctdir.listFiles();
if (obcontacts != null) {
@@ -106,12 +123,13 @@
obct.doComm();
}
}
-
if (this.nf != null) {
nf.fetch();
}
-
this.rtsf.poll();
+ if(stopping) {
+ break;
+ }
// poll for incoming message from all inbound contacts
File[] ibcontacts = this.ibctdir.listFiles();
@@ -125,7 +143,10 @@
ibct.fetch(this.mb);
}
}
-
+ if(stopping) {
+ break;
+ }
+
long runtime = System.currentTimeMillis() - start;
if (MIN_POLL_DURATION - runtime > 0) {
@@ -135,5 +156,27 @@
}
}
}
+ synchronized (syncObject) {
+ thread = null;
+ syncObject.notify();
+ }
+
}
+
+ /**
+ * This method will block until the
+ * thread has exited.
+ */
+ public void kill() {
+ synchronized (syncObject) {
+ stopping = true;
+ while (thread != null) {
+ syncObject.notify();
+ try {
+ syncObject.wait(1000);
+ } catch (InterruptedException ie1) {
+ }
+ }
+ }
+ }
}
Modified: trunk/plugins/Freemail/src/freemail/fcp/FCPConnection.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/fcp/FCPConnection.java 2007-10-23
23:03:14 UTC (rev 15513)
+++ trunk/plugins/Freemail/src/freemail/fcp/FCPConnection.java 2007-10-23
23:09:49 UTC (rev 15514)
@@ -29,6 +29,21 @@
import java.util.Iterator;
public class FCPConnection implements Runnable {
+ /**
+ * Object that is used for syncing purposes.
+ */
+ protected final Object syncObject = new Object();
+
+ /**
+ * Whether the thread this service runs in should stop.
+ */
+ protected volatile boolean stopping = false;
+
+ /**
+ * The currently running threads.
+ */
+ private Thread thread;
+
private final FCPContext fcpctx;
private OutputStream os;
private InputStream is;
@@ -76,10 +91,11 @@
}
public void run() {
- while (true) {
+ thread = Thread.currentThread();
+ while (!stopping) {
try {
this.tryConnect();
- if (this.conn == null) throw new IOException();
+ if (this.conn == null || stopping) throw new
IOException();
FCPMessage msg = this.getMessage();
if (msg.getType() == null) throw new
IOException("Connection closed");
@@ -102,8 +118,33 @@
}
}
}
+ synchronized (syncObject) {
+ thread = null;
+ syncObject.notify();
+ }
}
+ /**
+ * This method will block until the
+ * thread has exited.
+ */
+ public void kill() {
+ synchronized (syncObject) {
+ stopping = true;
+ try {
+ finalize();
+ } catch (Throwable t) {
+ }
+ while (thread != null) {
+ syncObject.notify();
+ try {
+ syncObject.wait(1000);
+ } catch (InterruptedException ie1) {
+ }
+ }
+ }
+ }
+
protected void finalize() throws Throwable {
try {
this.conn.close();
Modified: trunk/plugins/Freemail/src/freemail/fcp/FCPMessage.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/fcp/FCPMessage.java 2007-10-23
23:03:14 UTC (rev 15513)
+++ trunk/plugins/Freemail/src/freemail/fcp/FCPMessage.java 2007-10-23
23:09:49 UTC (rev 15514)
@@ -31,9 +31,9 @@
import java.util.Collections;
import freemail.Freemail;
+import freemail.support.io.LineReader;
+import freemail.support.io.LineReadingInputStream;
-import freenet.support.io.LineReader;
-import freenet.support.io.LineReadingInputStream;
public class FCPMessage {
private String messagetype;
Modified: trunk/plugins/Freemail/src/freemail/imap/IMAPListener.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/imap/IMAPListener.java 2007-10-23
23:03:14 UTC (rev 15513)
+++ trunk/plugins/Freemail/src/freemail/imap/IMAPListener.java 2007-10-23
23:09:49 UTC (rev 15514)
@@ -23,12 +23,28 @@
import java.net.ServerSocket;
import java.net.InetAddress;
+import java.net.SocketTimeoutException;
import java.io.IOException;
import freemail.config.Configurator;
import freemail.config.ConfigClient;
public class IMAPListener implements Runnable,ConfigClient {
+ /**
+ * Object that is used for syncing purposes.
+ */
+ protected final Object syncObject = new Object();
+
+ /**
+ * Whether the thread this service runs in should stop.
+ */
+ protected volatile boolean stopping = false;
+
+ /**
+ * The currently running threads.
+ */
+ private Thread thread;
+ private ServerSocket sock;
private static final int LISTENPORT = 3143;
private String bindaddress;
private int bindport;
@@ -47,22 +63,49 @@
}
public void run() {
+ thread = Thread.currentThread();
try {
this.realrun();
} catch (IOException ioe) {
System.out.println("Error in IMAP server -
"+ioe.getMessage());
}
+ synchronized (syncObject) {
+ thread = null;
+ syncObject.notify();
+ }
}
+ /**
+ * This method will block until the
+ * thread has exited.
+ */
+ public void kill() {
+ synchronized (syncObject) {
+ stopping = true;
+ try {
+ sock.close();
+ } catch (IOException ioe) { }
+ while (thread != null) {
+ syncObject.notify();
+ try {
+ syncObject.wait(1000);
+ } catch (InterruptedException ie1) {
+ }
+ }
+ }
+ }
+
public void realrun() throws IOException {
- ServerSocket sock = new ServerSocket(this.bindport, 10,
InetAddress.getByName(this.bindaddress));
-
- while (!sock.isClosed()) {
+ sock = new ServerSocket(this.bindport, 10,
InetAddress.getByName(this.bindaddress));
+ sock.setSoTimeout(60000);
+ while (!sock.isClosed() && !stopping) {
try {
IMAPHandler newcli = new
IMAPHandler(sock.accept());
Thread newthread = new Thread(newcli);
newthread.setDaemon(true);
newthread.start();
+ } catch (SocketTimeoutException ste) {
+
} catch (IOException ioe) {
}
Modified: trunk/plugins/Freemail/src/freemail/smtp/SMTPListener.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/smtp/SMTPListener.java 2007-10-23
23:03:14 UTC (rev 15513)
+++ trunk/plugins/Freemail/src/freemail/smtp/SMTPListener.java 2007-10-23
23:09:49 UTC (rev 15514)
@@ -30,6 +30,21 @@
import freemail.config.Configurator;
public class SMTPListener implements Runnable,ConfigClient {
+ /**
+ * Object that is used for syncing purposes.
+ */
+ protected final Object syncObject = new Object();
+
+ /**
+ * Whether the thread this service runs in should stop.
+ */
+ protected volatile boolean stopping = false;
+
+ /**
+ * The currently running threads.
+ */
+ private Thread thread;
+ private ServerSocket sock;
private static final int LISTENPORT = 3025;
private final MessageSender msgsender;
private String bindaddress;
@@ -42,12 +57,37 @@
}
public void run() {
+ thread = Thread.currentThread();
try {
this.realrun();
} catch (IOException ioe) {
System.out.println("Error in SMTP server -
"+ioe.getMessage());
}
+ synchronized (syncObject) {
+ thread = null;
+ syncObject.notify();
+ }
}
+
+ /**
+ * This method will block until the
+ * thread has exited.
+ */
+ public void kill() {
+ synchronized (syncObject) {
+ stopping = true;
+ try {
+ sock.close();
+ } catch (IOException ioe) { }
+ while (thread != null) {
+ syncObject.notify();
+ try {
+ syncObject.wait(1000);
+ } catch (InterruptedException ie1) {
+ }
+ }
+ }
+ }
public void setConfigProp(String key, String val) {
if (key.equalsIgnoreCase("smtp_bind_address")) {
@@ -58,9 +98,8 @@
}
public void realrun() throws IOException {
- ServerSocket sock = new ServerSocket(this.bindport, 10,
InetAddress.getByName(this.bindaddress));
-
- while (!sock.isClosed()) {
+ sock = new ServerSocket(this.bindport, 10,
InetAddress.getByName(this.bindaddress));
+ while (!sock.isClosed() && !stopping) {
try {
SMTPHandler newcli = new
SMTPHandler(sock.accept(), this.msgsender);
Thread newthread = new Thread(newcli);
Added: trunk/plugins/Freemail/src/freemail/support/io/LineReader.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/support/io/LineReader.java
(rev 0)
+++ trunk/plugins/Freemail/src/freemail/support/io/LineReader.java
2007-10-23 23:09:49 UTC (rev 15514)
@@ -0,0 +1,9 @@
+package freemail.support.io;
+
+import java.io.IOException;
+
+public interface LineReader {
+
+ public String readLine(int maxLength, int bufferSize) throws
IOException;
+
+}
Added:
trunk/plugins/Freemail/src/freemail/support/io/LineReadingInputStream.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/support/io/LineReadingInputStream.java
(rev 0)
+++ trunk/plugins/Freemail/src/freemail/support/io/LineReadingInputStream.java
2007-10-23 23:09:49 UTC (rev 15514)
@@ -0,0 +1,47 @@
+package freemail.support.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A FilterInputStream which provides readLine().
+ */
+public class LineReadingInputStream extends FilterInputStream implements
LineReader {
+ private int lastBytesRead;
+
+ public LineReadingInputStream(InputStream in) {
+ super(in);
+ }
+
+ /**
+ * Read a line of US-ASCII. Used for e.g. HTTP. @return Null if end of
file.
+ */
+ public String readLine(int maxLength, int bufferSize) throws
IOException {
+ StringBuffer sb = new StringBuffer(bufferSize);
+ this.lastBytesRead = 0;
+ while(true) {
+ int x = read();
+ this.lastBytesRead++;
+ if(x == -1) {
+ if(sb.length() == 0) return null;
+ return sb.toString();
+ }
+ char c = (char) x;
+ if(c == '\n') {
+ if(sb.length() > 0) {
+ if(sb.charAt(sb.length()-1) == '\r')
+ sb.setLength(sb.length()-1);
+ }
+ return sb.toString();
+ }
+ sb.append(c);
+ if(sb.length() >= maxLength)
+ throw new TooLongException();
+ }
+ }
+
+ public int getLastBytesRead() {
+ return this.lastBytesRead;
+ }
+}
Added: trunk/plugins/Freemail/src/freemail/support/io/TooLongException.java
===================================================================
--- trunk/plugins/Freemail/src/freemail/support/io/TooLongException.java
(rev 0)
+++ trunk/plugins/Freemail/src/freemail/support/io/TooLongException.java
2007-10-23 23:09:49 UTC (rev 15514)
@@ -0,0 +1,8 @@
+package freemail.support.io;
+
+import java.io.IOException;
+
+/** Exception thrown by a LineReadingInputStream when a line is too long. */
+public class TooLongException extends IOException {
+ static final long serialVersionUID = -1;
+}