diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3DatagramServer.java b/apps/sam/java/src/net/i2p/sam/SAMv3DatagramServer.java index 39a9f9034de8518bbfa0194945b1844f3f121a1b..f5d76c96d43aa88b723c736fb84602ba3df7b5dd 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3DatagramServer.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3DatagramServer.java @@ -32,18 +32,21 @@ import net.i2p.util.Log; * * @since 0.9.22 moved from SAMv3Handler */ -class SAMv3DatagramServer { +class SAMv3DatagramServer implements Handler { private static SAMv3DatagramServer _instance; private static DatagramChannel server; + private final Thread _listener; + private final SAMBridge _parent; /** * Returns the singleton. * If this is the first call, will be instantiated and will listen * on the default host:port 127.0.0.1:7655. + * Don't make this the first call. */ public static SAMv3DatagramServer getInstance() throws IOException { - return getInstance(new Properties()); + return getInstance(null, new Properties()); } /** @@ -54,15 +57,24 @@ class SAMv3DatagramServer { * * @param props ignored unless this is the first call */ - public static SAMv3DatagramServer getInstance(Properties props) throws IOException { + public static SAMv3DatagramServer getInstance(SAMBridge parent, Properties props) throws IOException { synchronized(SAMv3DatagramServer.class) { - if (_instance==null) - _instance = new SAMv3DatagramServer(props); - return _instance ; + if (_instance==null) { + _instance = new SAMv3DatagramServer(parent, props); + _instance.start(); + } } + return _instance; } - private SAMv3DatagramServer(Properties props) throws IOException { + /** + * Does not start listener. + * Caller must call start(). + * + * @param parent may be null + */ + private SAMv3DatagramServer(SAMBridge parent, Properties props) throws IOException { + _parent = parent; synchronized(SAMv3DatagramServer.class) { if (server==null) server = DatagramChannel.open(); @@ -78,13 +90,41 @@ class SAMv3DatagramServer { } server.socket().bind(new InetSocketAddress(host, port)); - new I2PAppThread(new Listener(server), "DatagramListener").start(); + _listener = new I2PAppThread(new Listener(server), "SAM DatagramListener " + port); + } + + /** + * Only call once. + * @since 0.9.22 + */ + public void start() { + _listener.start(); + if (_parent != null) + _parent.register(this); + } + + /** + * Cannot be restarted. + * @since 0.9.22 + */ + public void stopHandling() { + synchronized(SAMv3DatagramServer.class) { + if (server != null) { + try { + server.close(); + } catch (IOException ioe) {} + server = null; + } + } + _listener.interrupt(); + if (_parent != null) + _parent.unregister(this); } public void send(SocketAddress addr, ByteBuffer msg) throws IOException { server.send(msg, addr); } - + private static class Listener implements Runnable { private final DatagramChannel server; diff --git a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java index 1666ece03b321e39408f2d9103ebc17626d20732..5505eb28636f2ff9b8dc2f47600d5bc31b54d3aa 100644 --- a/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java +++ b/apps/sam/java/src/net/i2p/sam/SAMv3Handler.java @@ -520,12 +520,12 @@ class SAMv3Handler extends SAMv1Handler // Create the session if (style.equals("RAW")) { - SAMv3DatagramServer.getInstance(i2cpProps); + SAMv3DatagramServer.getInstance(bridge, i2cpProps); SAMv3RawSession v3 = newSAMRawSession(nick); rawSession = v3; this.session = v3; } else if (style.equals("DATAGRAM")) { - SAMv3DatagramServer.getInstance(i2cpProps); + SAMv3DatagramServer.getInstance(bridge, i2cpProps); SAMv3DatagramSession v3 = newSAMDatagramSession(nick); datagramSession = v3; this.session = v3;