diff --git a/src/net/sf/briar/api/plugins/duplex/DuplexPluginFactory.java b/src/net/sf/briar/api/plugins/duplex/DuplexPluginFactory.java index daf39c155023ea1c273748d0bcd98d1627a771f5..047e4584617ec0089ce6b968b4f9a03457f2c9ae 100644 --- a/src/net/sf/briar/api/plugins/duplex/DuplexPluginFactory.java +++ b/src/net/sf/briar/api/plugins/duplex/DuplexPluginFactory.java @@ -3,6 +3,7 @@ package net.sf.briar.api.plugins.duplex; import java.util.concurrent.Executor; import net.sf.briar.api.android.AndroidExecutor; +import net.sf.briar.api.lifecycle.ShutdownManager; import android.content.Context; @@ -10,5 +11,5 @@ public interface DuplexPluginFactory { DuplexPlugin createPlugin(Executor pluginExecutor, AndroidExecutor androidExecutor, Context appContext, - DuplexPluginCallback callback); + ShutdownManager shutdownManager, DuplexPluginCallback callback); } diff --git a/src/net/sf/briar/api/plugins/simplex/SimplexPluginFactory.java b/src/net/sf/briar/api/plugins/simplex/SimplexPluginFactory.java index 06e4df03c89e96b09891dcb16bd59d0e8d575140..6460d45a2161abcc05280c7ebbb88a34944b82a6 100644 --- a/src/net/sf/briar/api/plugins/simplex/SimplexPluginFactory.java +++ b/src/net/sf/briar/api/plugins/simplex/SimplexPluginFactory.java @@ -3,6 +3,7 @@ package net.sf.briar.api.plugins.simplex; import java.util.concurrent.Executor; import net.sf.briar.api.android.AndroidExecutor; +import net.sf.briar.api.lifecycle.ShutdownManager; import android.content.Context; @@ -10,5 +11,5 @@ public interface SimplexPluginFactory { SimplexPlugin createPlugin(Executor pluginExecutor, AndroidExecutor androidExecutor, Context appContext, - SimplexPluginCallback callback); + ShutdownManager shutdownManager, SimplexPluginCallback callback); } diff --git a/src/net/sf/briar/lifecycle/WindowsShutdownManagerImpl.java b/src/net/sf/briar/lifecycle/WindowsShutdownManagerImpl.java index 38f66ce61fbfc687a799c22647bec275fac5594a..d603975fe13d498319b2526ebbde139e381bfecd 100644 --- a/src/net/sf/briar/lifecycle/WindowsShutdownManagerImpl.java +++ b/src/net/sf/briar/lifecycle/WindowsShutdownManagerImpl.java @@ -1,5 +1,8 @@ package net.sf.briar.lifecycle; +import static com.sun.jna.Library.OPTION_FUNCTION_MAPPER; +import static com.sun.jna.Library.OPTION_TYPE_MAPPER; +import static com.sun.jna.win32.W32APIFunctionMapper.UNICODE; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; @@ -11,7 +14,6 @@ import java.util.logging.Logger; import net.sf.briar.util.OsUtils; -import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.platform.win32.WinDef.HINSTANCE; @@ -23,13 +25,11 @@ import com.sun.jna.platform.win32.WinDef.WPARAM; import com.sun.jna.platform.win32.WinUser.MSG; import com.sun.jna.win32.StdCallLibrary; import com.sun.jna.win32.StdCallLibrary.StdCallCallback; -import com.sun.jna.win32.W32APIFunctionMapper; -import com.sun.jna.win32.W32APITypeMapper; class WindowsShutdownManagerImpl extends ShutdownManagerImpl { private static final Logger LOG = - Logger.getLogger(WindowsShutdownManagerImpl.class.getName()); + Logger.getLogger(WindowsShutdownManagerImpl.class.getName()); private static final int WM_QUERYENDSESSION = 17; private static final int GWL_WNDPROC = -4; @@ -42,9 +42,8 @@ class WindowsShutdownManagerImpl extends ShutdownManagerImpl { WindowsShutdownManagerImpl() { // Use the Unicode versions of Win32 API calls Map<String, Object> m = new HashMap<String, Object>(); - m.put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE); - m.put(Library.OPTION_FUNCTION_MAPPER, - W32APIFunctionMapper.UNICODE); + m.put(OPTION_TYPE_MAPPER, UNICODE); + m.put(OPTION_FUNCTION_MAPPER, UNICODE); options = Collections.unmodifiableMap(m); } diff --git a/src/net/sf/briar/plugins/PluginManagerImpl.java b/src/net/sf/briar/plugins/PluginManagerImpl.java index a0e2e4111b455ebf967c625a633641afa7186d68..4fb27488951e60e72a435409965d079fb1c14896 100644 --- a/src/net/sf/briar/plugins/PluginManagerImpl.java +++ b/src/net/sf/briar/plugins/PluginManagerImpl.java @@ -20,6 +20,7 @@ import net.sf.briar.api.TransportProperties; import net.sf.briar.api.android.AndroidExecutor; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DbException; +import net.sf.briar.api.lifecycle.ShutdownManager; import net.sf.briar.api.plugins.Plugin; import net.sf.briar.api.plugins.PluginCallback; import net.sf.briar.api.plugins.PluginExecutor; @@ -67,6 +68,7 @@ class PluginManagerImpl implements PluginManager { private final ExecutorService pluginExecutor; private final AndroidExecutor androidExecutor; + private final ShutdownManager shutdownManager; private final DatabaseComponent db; private final Poller poller; private final ConnectionDispatcher dispatcher; @@ -76,11 +78,12 @@ class PluginManagerImpl implements PluginManager { @Inject PluginManagerImpl(@PluginExecutor ExecutorService pluginExecutor, - AndroidExecutor androidExecutor, DatabaseComponent db, - Poller poller, ConnectionDispatcher dispatcher, - UiCallback uiCallback) { + AndroidExecutor androidExecutor, ShutdownManager shutdownManager, + DatabaseComponent db, Poller poller, + ConnectionDispatcher dispatcher, UiCallback uiCallback) { this.pluginExecutor = pluginExecutor; this.androidExecutor = androidExecutor; + this.shutdownManager = shutdownManager; this.db = db; this.poller = poller; this.dispatcher = dispatcher; @@ -99,7 +102,7 @@ class PluginManagerImpl implements PluginManager { (SimplexPluginFactory) c.newInstance(); SimplexCallback callback = new SimplexCallback(); SimplexPlugin plugin = factory.createPlugin(pluginExecutor, - androidExecutor, appContext, callback); + androidExecutor, appContext, shutdownManager, callback); if(plugin == null) { if(LOG.isLoggable(INFO)) { LOG.info(factory.getClass().getSimpleName() @@ -132,7 +135,7 @@ class PluginManagerImpl implements PluginManager { (DuplexPluginFactory) c.newInstance(); DuplexCallback callback = new DuplexCallback(); DuplexPlugin plugin = factory.createPlugin(pluginExecutor, - androidExecutor, appContext, callback); + androidExecutor, appContext, shutdownManager, callback); if(plugin == null) { if(LOG.isLoggable(INFO)) { LOG.info(factory.getClass().getSimpleName() diff --git a/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java b/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java index f3edf599c29a9114b267f4e6fec6364813ec096a..2d9754fde9c1062d0987654924fdced5b30399ae 100644 --- a/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java +++ b/src/net/sf/briar/plugins/bluetooth/BluetoothPluginFactory.java @@ -4,6 +4,7 @@ import java.util.concurrent.Executor; import net.sf.briar.api.android.AndroidExecutor; import net.sf.briar.api.clock.SystemClock; +import net.sf.briar.api.lifecycle.ShutdownManager; import net.sf.briar.api.plugins.PluginExecutor; import net.sf.briar.api.plugins.duplex.DuplexPlugin; import net.sf.briar.api.plugins.duplex.DuplexPluginCallback; @@ -16,7 +17,7 @@ public class BluetoothPluginFactory implements DuplexPluginFactory { public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor, AndroidExecutor androidExecutor, Context appContext, - DuplexPluginCallback callback) { + ShutdownManager shutdownManager, DuplexPluginCallback callback) { return new BluetoothPlugin(pluginExecutor, new SystemClock(), callback, POLLING_INTERVAL); } diff --git a/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java b/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java index e1634e102a9bbfbceea3ba10c5a8e9d9a19bba3a..7e438c5483555d609a898e9276fa64b147dd79f9 100644 --- a/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java +++ b/src/net/sf/briar/plugins/droidtooth/DroidtoothPluginFactory.java @@ -3,6 +3,7 @@ package net.sf.briar.plugins.droidtooth; import java.util.concurrent.Executor; import net.sf.briar.api.android.AndroidExecutor; +import net.sf.briar.api.lifecycle.ShutdownManager; import net.sf.briar.api.plugins.PluginExecutor; import net.sf.briar.api.plugins.duplex.DuplexPlugin; import net.sf.briar.api.plugins.duplex.DuplexPluginCallback; @@ -15,7 +16,7 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory { public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor, AndroidExecutor androidExecutor, Context appContext, - DuplexPluginCallback callback) { + ShutdownManager shutdownManager, DuplexPluginCallback callback) { return new DroidtoothPlugin(pluginExecutor, androidExecutor, appContext, callback, POLLING_INTERVAL); } diff --git a/src/net/sf/briar/plugins/email/GmailPluginFactory.java b/src/net/sf/briar/plugins/email/GmailPluginFactory.java index 192e0d412e3f846b103bf0aac5a9ebf78cfe7ed7..1057b80c03399912c434d14afa671311aa3fdb7f 100644 --- a/src/net/sf/briar/plugins/email/GmailPluginFactory.java +++ b/src/net/sf/briar/plugins/email/GmailPluginFactory.java @@ -3,6 +3,7 @@ package net.sf.briar.plugins.email; import java.util.concurrent.Executor; import net.sf.briar.api.android.AndroidExecutor; +import net.sf.briar.api.lifecycle.ShutdownManager; import net.sf.briar.api.plugins.simplex.SimplexPlugin; import net.sf.briar.api.plugins.simplex.SimplexPluginCallback; import net.sf.briar.api.plugins.simplex.SimplexPluginFactory; @@ -12,7 +13,7 @@ public class GmailPluginFactory implements SimplexPluginFactory { public SimplexPlugin createPlugin(Executor pluginExecutor, AndroidExecutor androidExecutor, Context context, - SimplexPluginCallback callback) { + ShutdownManager shutdownManager, SimplexPluginCallback callback) { return new GmailPlugin(pluginExecutor, callback); } } diff --git a/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java b/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java index 0dfee33b7e1f12af3c29546d455b41d03037ad41..26ecec3675743b1c700ce819145b680a9ecf47d1 100644 --- a/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java +++ b/src/net/sf/briar/plugins/file/RemovableDrivePluginFactory.java @@ -3,6 +3,7 @@ package net.sf.briar.plugins.file; import java.util.concurrent.Executor; import net.sf.briar.api.android.AndroidExecutor; +import net.sf.briar.api.lifecycle.ShutdownManager; import net.sf.briar.api.plugins.PluginExecutor; import net.sf.briar.api.plugins.simplex.SimplexPlugin; import net.sf.briar.api.plugins.simplex.SimplexPluginCallback; @@ -16,7 +17,7 @@ public class RemovableDrivePluginFactory implements SimplexPluginFactory { public SimplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor, AndroidExecutor androidExecutor, Context appContext, - SimplexPluginCallback callback) { + ShutdownManager shutdownManager, SimplexPluginCallback callback) { RemovableDriveFinder finder; RemovableDriveMonitor monitor; if(OsUtils.isLinux()) { diff --git a/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java b/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java index fb5c8f560eaf2fa4b250a11dfc920236d576bc90..6abcba8997c9aa9ba808998577e562270d04f761 100644 --- a/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java +++ b/src/net/sf/briar/plugins/tcp/LanTcpPluginFactory.java @@ -3,6 +3,7 @@ package net.sf.briar.plugins.tcp; import java.util.concurrent.Executor; import net.sf.briar.api.android.AndroidExecutor; +import net.sf.briar.api.lifecycle.ShutdownManager; import net.sf.briar.api.plugins.PluginExecutor; import net.sf.briar.api.plugins.duplex.DuplexPlugin; import net.sf.briar.api.plugins.duplex.DuplexPluginCallback; @@ -15,7 +16,7 @@ public class LanTcpPluginFactory implements DuplexPluginFactory { public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor, AndroidExecutor androidExecutor, Context appContext, - DuplexPluginCallback callback) { + ShutdownManager shutdownManager, DuplexPluginCallback callback) { return new LanTcpPlugin(pluginExecutor, callback, POLLING_INTERVAL); } } diff --git a/src/net/sf/briar/plugins/tcp/PortMapper.java b/src/net/sf/briar/plugins/tcp/PortMapper.java index 5bd226329df1e9496bf87d35e97cfc2a9376a0a6..d7ad7d6fba874730cedf2b4fc149b660a77d51a1 100644 --- a/src/net/sf/briar/plugins/tcp/PortMapper.java +++ b/src/net/sf/briar/plugins/tcp/PortMapper.java @@ -2,9 +2,5 @@ package net.sf.briar.plugins.tcp; interface PortMapper { - void start(); - - void stop(); - MappingResult map(int port); } diff --git a/src/net/sf/briar/plugins/tcp/PortMapperImpl.java b/src/net/sf/briar/plugins/tcp/PortMapperImpl.java index d3da9eb63cfab8e60f4553cb9768e50665438202..bb7606e8aa58efc9fba4df0ad437cba0b6ca31b4 100644 --- a/src/net/sf/briar/plugins/tcp/PortMapperImpl.java +++ b/src/net/sf/briar/plugins/tcp/PortMapperImpl.java @@ -5,13 +5,13 @@ import static java.util.logging.Level.WARNING; import java.io.IOException; import java.net.InetAddress; -import java.util.Collection; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Logger; import javax.xml.parsers.ParserConfigurationException; +import net.sf.briar.api.lifecycle.ShutdownManager; + import org.wetorrent.upnp.GatewayDevice; import org.wetorrent.upnp.GatewayDiscover; import org.xml.sax.SAXException; @@ -21,71 +21,68 @@ class PortMapperImpl implements PortMapper { private static final Logger LOG = Logger.getLogger(PortMapperImpl.class.getName()); - private final CountDownLatch started = new CountDownLatch(1); - private final Collection<Integer> ports = - new CopyOnWriteArrayList<Integer>(); + private final ShutdownManager shutdownManager; + private final AtomicBoolean started = new AtomicBoolean(false); private volatile GatewayDevice gateway = null; - public void start() { - GatewayDiscover d = new GatewayDiscover(); + PortMapperImpl(ShutdownManager shutdownManager) { + this.shutdownManager = shutdownManager; + } + + public MappingResult map(final int port) { + if(!started.getAndSet(true)) start(); + if(gateway == null) return null; + InetAddress internal = gateway.getLocalAddress(); + if(internal == null) return null; + boolean succeeded = false; + InetAddress external = null; try { - d.discover(); + succeeded = gateway.addPortMapping(port, port, + internal.getHostAddress(), "TCP", "TCP"); + if(succeeded) { + shutdownManager.addShutdownHook(new Runnable() { + public void run() { + deleteMapping(port); + } + }); + } + String externalString = gateway.getExternalIPAddress(); + if(LOG.isLoggable(INFO)) + LOG.info("External address " + externalString); + if(externalString != null) + external = InetAddress.getByName(externalString); } catch(IOException e) { if(LOG.isLoggable(WARNING)) LOG.warning(e.toString()); } catch(SAXException e) { if(LOG.isLoggable(WARNING)) LOG.warning(e.toString()); - } catch(ParserConfigurationException e) { - if(LOG.isLoggable(WARNING)) LOG.warning(e.toString()); } - gateway = d.getValidGateway(); - started.countDown(); + return new MappingResult(internal, external, port, succeeded); } - public void stop() { - if(gateway == null) return; + private void start() { + GatewayDiscover d = new GatewayDiscover(); try { - for(Integer port: ports) { - gateway.deletePortMapping(port, "TCP"); - if(LOG.isLoggable(INFO)) - LOG.info("Deleted mapping for port " + port); - } + d.discover(); } catch(IOException e) { if(LOG.isLoggable(WARNING)) LOG.warning(e.toString()); } catch(SAXException e) { if(LOG.isLoggable(WARNING)) LOG.warning(e.toString()); + } catch(ParserConfigurationException e) { + if(LOG.isLoggable(WARNING)) LOG.warning(e.toString()); } + gateway = d.getValidGateway(); } - public MappingResult map(int port) { - try { - started.await(); - } catch(InterruptedException e) { - if(LOG.isLoggable(WARNING)) LOG.warning(e.toString()); - Thread.currentThread().interrupt(); - return null; - } - if(gateway == null) return null; - InetAddress internal = gateway.getLocalAddress(); - if(internal == null) return null; - boolean succeeded = false; - InetAddress external = null; + private void deleteMapping(int port) { try { - succeeded = gateway.addPortMapping(port, port, - internal.getHostAddress(), "TCP", "TCP"); - String externalString = gateway.getExternalIPAddress(); - if(externalString != null) - external = InetAddress.getByName(externalString); - if(LOG.isLoggable(INFO)) { - if(succeeded) LOG.info("External address " + externalString); - else LOG.info("Could not create port mapping"); - } + gateway.deletePortMapping(port, "TCP"); + if(LOG.isLoggable(INFO)) + LOG.info("Deleted mapping for port " + port); } catch(IOException e) { if(LOG.isLoggable(WARNING)) LOG.warning(e.toString()); } catch(SAXException e) { if(LOG.isLoggable(WARNING)) LOG.warning(e.toString()); } - if(succeeded) ports.add(port); - return new MappingResult(internal, external, port, succeeded); } } diff --git a/src/net/sf/briar/plugins/tcp/WanTcpPlugin.java b/src/net/sf/briar/plugins/tcp/WanTcpPlugin.java index c0849cf92749799f83e1a59ac8ba32a27e3c0ab2..471b03d29f04b2a8eb926cbe4700429c319c48c9 100644 --- a/src/net/sf/briar/plugins/tcp/WanTcpPlugin.java +++ b/src/net/sf/briar/plugins/tcp/WanTcpPlugin.java @@ -2,7 +2,6 @@ package net.sf.briar.plugins.tcp; import static java.util.logging.Level.WARNING; -import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.NetworkInterface; @@ -49,26 +48,6 @@ class WanTcpPlugin extends TcpPlugin { return ID; } - @Override - public void start() throws IOException { - super.start(); - pluginExecutor.execute(new Runnable() { - public void run() { - portMapper.start(); - } - }); - } - - @Override - public void stop() throws IOException { - super.stop(); - pluginExecutor.execute(new Runnable() { - public void run() { - portMapper.stop(); - } - }); - } - @Override protected List<SocketAddress> getLocalSocketAddresses() { List<SocketAddress> addrs = new ArrayList<SocketAddress>(); diff --git a/src/net/sf/briar/plugins/tcp/WanTcpPluginFactory.java b/src/net/sf/briar/plugins/tcp/WanTcpPluginFactory.java index f976e22cf531e5a00d370d3227f47d67a0b08857..d4f89475bcdb94ea02a079f8a9621b928d6ed5bc 100644 --- a/src/net/sf/briar/plugins/tcp/WanTcpPluginFactory.java +++ b/src/net/sf/briar/plugins/tcp/WanTcpPluginFactory.java @@ -3,6 +3,7 @@ package net.sf.briar.plugins.tcp; import java.util.concurrent.Executor; import net.sf.briar.api.android.AndroidExecutor; +import net.sf.briar.api.lifecycle.ShutdownManager; import net.sf.briar.api.plugins.PluginExecutor; import net.sf.briar.api.plugins.duplex.DuplexPlugin; import net.sf.briar.api.plugins.duplex.DuplexPluginCallback; @@ -15,8 +16,8 @@ public class WanTcpPluginFactory implements DuplexPluginFactory { public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor, AndroidExecutor androidExecutor, Context appContext, - DuplexPluginCallback callback) { + ShutdownManager shutdownManager, DuplexPluginCallback callback) { return new WanTcpPlugin(pluginExecutor, callback, POLLING_INTERVAL, - new PortMapperImpl()); + new PortMapperImpl(shutdownManager)); } } diff --git a/src/net/sf/briar/plugins/tor/TorPluginFactory.java b/src/net/sf/briar/plugins/tor/TorPluginFactory.java index bb43a6d3b4cb961f06899dbb650c640b1ba62ee9..2d213209cc05c4f4732e911d36c89b4382b3013c 100644 --- a/src/net/sf/briar/plugins/tor/TorPluginFactory.java +++ b/src/net/sf/briar/plugins/tor/TorPluginFactory.java @@ -3,6 +3,7 @@ package net.sf.briar.plugins.tor; import java.util.concurrent.Executor; import net.sf.briar.api.android.AndroidExecutor; +import net.sf.briar.api.lifecycle.ShutdownManager; import net.sf.briar.api.plugins.PluginExecutor; import net.sf.briar.api.plugins.duplex.DuplexPlugin; import net.sf.briar.api.plugins.duplex.DuplexPluginCallback; @@ -15,7 +16,7 @@ public class TorPluginFactory implements DuplexPluginFactory { public DuplexPlugin createPlugin(@PluginExecutor Executor pluginExecutor, AndroidExecutor androidExecutor, Context appContext, - DuplexPluginCallback callback) { + ShutdownManager shutdownManager, DuplexPluginCallback callback) { return new TorPlugin(pluginExecutor, callback, POLLING_INTERVAL); } }