diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml
index 2f5e0d87b..70d79d2fa 100644
--- a/briar-android/AndroidManifest.xml
+++ b/briar-android/AndroidManifest.xml
@@ -9,6 +9,7 @@
+
diff --git a/briar-android/src/net/sf/briar/android/AndroidModule.java b/briar-android/src/net/sf/briar/android/AndroidModule.java
index 06dbc4bcf..afac6d63c 100644
--- a/briar-android/src/net/sf/briar/android/AndroidModule.java
+++ b/briar-android/src/net/sf/briar/android/AndroidModule.java
@@ -23,7 +23,7 @@ import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
import net.sf.briar.api.plugins.simplex.SimplexPluginConfig;
import net.sf.briar.api.plugins.simplex.SimplexPluginFactory;
import net.sf.briar.plugins.droidtooth.DroidtoothPluginFactory;
-import net.sf.briar.plugins.tcp.LanTcpPluginFactory;
+import net.sf.briar.plugins.tcp.DroidLanTcpPluginFactory;
import net.sf.briar.plugins.tcp.WanTcpPluginFactory;
import net.sf.briar.plugins.tor.TorPluginFactory;
import android.content.Context;
@@ -71,7 +71,8 @@ public class AndroidModule extends AbstractModule {
crypto.getSecureRandom());
DuplexPluginFactory tor = new TorPluginFactory(pluginExecutor,
appContext, shutdownManager);
- DuplexPluginFactory lan = new LanTcpPluginFactory(pluginExecutor);
+ DuplexPluginFactory lan = new DroidLanTcpPluginFactory(pluginExecutor,
+ appContext);
DuplexPluginFactory wan = new WanTcpPluginFactory(pluginExecutor,
shutdownManager);
final Collection factories =
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPlugin.java b/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPlugin.java
new file mode 100644
index 000000000..818472cbd
--- /dev/null
+++ b/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPlugin.java
@@ -0,0 +1,55 @@
+package net.sf.briar.plugins.tcp;
+
+import static android.content.Context.WIFI_SERVICE;
+
+import java.util.concurrent.Executor;
+
+import net.sf.briar.api.clock.Clock;
+import net.sf.briar.api.crypto.PseudoRandom;
+import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
+import net.sf.briar.api.plugins.duplex.DuplexTransportConnection;
+import android.content.Context;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.MulticastLock;
+
+class DroidLanTcpPlugin extends LanTcpPlugin {
+
+ private final Context appContext;
+
+ DroidLanTcpPlugin(Executor pluginExecutor, Context appContext, Clock clock,
+ DuplexPluginCallback callback, long maxLatency,
+ long pollingInterval) {
+ super(pluginExecutor, clock, callback, maxLatency, pollingInterval);
+ this.appContext = appContext;
+ }
+
+ @Override
+ public DuplexTransportConnection sendInvitation(PseudoRandom r,
+ long timeout) {
+ WifiManager wifi =
+ (WifiManager) appContext.getSystemService(WIFI_SERVICE);
+ if(wifi == null || !wifi.isWifiEnabled()) return null;
+ MulticastLock lock = wifi.createMulticastLock("invitation");
+ lock.acquire();
+ try {
+ return super.sendInvitation(r, timeout);
+ } finally {
+ lock.release();
+ }
+ }
+
+ @Override
+ public DuplexTransportConnection acceptInvitation(PseudoRandom r,
+ long timeout) {
+ WifiManager wifi =
+ (WifiManager) appContext.getSystemService(WIFI_SERVICE);
+ if(wifi == null || !wifi.isWifiEnabled()) return null;
+ MulticastLock lock = wifi.createMulticastLock("invitation");
+ lock.acquire();
+ try {
+ return super.acceptInvitation(r, timeout);
+ } finally {
+ lock.release();
+ }
+ }
+}
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPluginFactory.java b/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPluginFactory.java
new file mode 100644
index 000000000..44d488165
--- /dev/null
+++ b/briar-core/src/net/sf/briar/plugins/tcp/DroidLanTcpPluginFactory.java
@@ -0,0 +1,37 @@
+package net.sf.briar.plugins.tcp;
+
+import java.util.concurrent.Executor;
+
+import net.sf.briar.api.TransportId;
+import net.sf.briar.api.clock.Clock;
+import net.sf.briar.api.clock.SystemClock;
+import net.sf.briar.api.plugins.duplex.DuplexPlugin;
+import net.sf.briar.api.plugins.duplex.DuplexPluginCallback;
+import net.sf.briar.api.plugins.duplex.DuplexPluginFactory;
+import android.content.Context;
+
+public class DroidLanTcpPluginFactory implements DuplexPluginFactory {
+
+ private static final long MAX_LATENCY = 60 * 1000; // 1 minute
+ private static final long POLLING_INTERVAL = 60 * 1000; // 1 minute
+
+ private final Executor pluginExecutor;
+ private final Context appContext;
+ private final Clock clock;
+
+ public DroidLanTcpPluginFactory(Executor pluginExecutor,
+ Context appContext) {
+ this.pluginExecutor = pluginExecutor;
+ this.appContext = appContext;
+ clock = new SystemClock();
+ }
+
+ public TransportId getId() {
+ return LanTcpPlugin.ID;
+ }
+
+ public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
+ return new DroidLanTcpPlugin(pluginExecutor, appContext, clock,
+ callback, MAX_LATENCY, POLLING_INTERVAL);
+ }
+}
diff --git a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
index aeb307c6f..b81250fd1 100644
--- a/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
+++ b/briar-core/src/net/sf/briar/plugins/tcp/LanTcpPlugin.java
@@ -136,6 +136,7 @@ class LanTcpPlugin extends TcpPlugin {
if(ms != null) tryToClose(ms, mcast.getAddress());
return null;
}
+ if(LOG.isLoggable(INFO)) LOG.info("Listening for multicast packets");
// Listen until a valid packet is received or the timeout occurs
byte[] buffer = new byte[2];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
@@ -150,10 +151,15 @@ class LanTcpPlugin extends TcpPlugin {
int off = packet.getOffset();
int len = packet.getLength();
int port = parsePacket(b, off, len);
+ if(LOG.isLoggable(INFO)){
+ String addr = getHostAddress(packet.getAddress());
+ LOG.info("Received a packet from " + addr + ":" + port);
+ }
if(port >= 32768 && port < 65536) {
try {
// Connect back on the advertised TCP port
Socket s = new Socket(packet.getAddress(), port);
+ if(LOG.isLoggable(INFO)) LOG.info("Connected back");
return new TcpTransportConnection(s, maxLatency);
} catch(IOException e) {
if(LOG.isLoggable(WARNING))
@@ -161,6 +167,7 @@ class LanTcpPlugin extends TcpPlugin {
}
}
} catch(SocketTimeoutException e) {
+ if(LOG.isLoggable(INFO)) LOG.info("Timed out");
break;
}
now = clock.currentTimeMillis();
@@ -282,11 +289,17 @@ class LanTcpPlugin extends TcpPlugin {
try {
int wait = (int) (Math.min(end, nextPacket) - now);
ss.setSoTimeout(wait < 1 ? 1 : wait);
+ if(LOG.isLoggable(INFO))
+ LOG.info("Listening for TCP connections: " + wait);
Socket s = ss.accept();
+ if(LOG.isLoggable(INFO))
+ LOG.info("Received a TCP connection");
return new TcpTransportConnection(s, maxLatency);
} catch(SocketTimeoutException e) {
now = clock.currentTimeMillis();
if(now < end) {
+ if(LOG.isLoggable(INFO))
+ LOG.info("Sending multicast packet");
ms.send(packet);
now = clock.currentTimeMillis();
nextPacket = now + MULTICAST_INTERVAL;