mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 13:49:53 +01:00
Bluetooth debugging and code cleanup.
Generate a random UUID instead of using a fixed UUID. Close sockets when exceptions are thrown (not doing so can cause problems with subsequent sockets on Android). Use a semaphore with tryAcquire() instead of a lock when making alien calls, to avoid possible deadlocks.
This commit is contained in:
@@ -6,6 +6,7 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import net.sf.briar.api.android.AndroidExecutor;
|
import net.sf.briar.api.android.AndroidExecutor;
|
||||||
|
import net.sf.briar.api.crypto.CryptoComponent;
|
||||||
import net.sf.briar.api.lifecycle.ShutdownManager;
|
import net.sf.briar.api.lifecycle.ShutdownManager;
|
||||||
import net.sf.briar.api.plugins.PluginExecutor;
|
import net.sf.briar.api.plugins.PluginExecutor;
|
||||||
import net.sf.briar.api.plugins.PluginManager;
|
import net.sf.briar.api.plugins.PluginManager;
|
||||||
@@ -63,14 +64,15 @@ public class PluginsModule extends AbstractModule {
|
|||||||
@PluginExecutor ExecutorService pluginExecutor,
|
@PluginExecutor ExecutorService pluginExecutor,
|
||||||
AndroidExecutor androidExecutor, Context appContext,
|
AndroidExecutor androidExecutor, Context appContext,
|
||||||
ReliabilityLayerFactory reliabilityFactory,
|
ReliabilityLayerFactory reliabilityFactory,
|
||||||
ShutdownManager shutdownManager) {
|
ShutdownManager shutdownManager, CryptoComponent crypto) {
|
||||||
final Collection<DuplexPluginFactory> factories =
|
final Collection<DuplexPluginFactory> factories =
|
||||||
new ArrayList<DuplexPluginFactory>();
|
new ArrayList<DuplexPluginFactory>();
|
||||||
if(OsUtils.isAndroid()) {
|
if(OsUtils.isAndroid()) {
|
||||||
factories.add(new DroidtoothPluginFactory(pluginExecutor,
|
factories.add(new DroidtoothPluginFactory(pluginExecutor,
|
||||||
androidExecutor, appContext));
|
androidExecutor, appContext, crypto.getSecureRandom()));
|
||||||
} else {
|
} else {
|
||||||
factories.add(new BluetoothPluginFactory(pluginExecutor));
|
factories.add(new BluetoothPluginFactory(pluginExecutor,
|
||||||
|
crypto.getSecureRandom()));
|
||||||
factories.add(new ModemPluginFactory(pluginExecutor,
|
factories.add(new ModemPluginFactory(pluginExecutor,
|
||||||
reliabilityFactory));
|
reliabilityFactory));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import static java.util.logging.Level.WARNING;
|
|||||||
import static javax.bluetooth.DiscoveryAgent.GIAC;
|
import static javax.bluetooth.DiscoveryAgent.GIAC;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -14,6 +15,7 @@ import java.util.concurrent.Executor;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.bluetooth.BluetoothStateException;
|
import javax.bluetooth.BluetoothStateException;
|
||||||
@@ -46,12 +48,14 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(BluetoothPlugin.class.getName());
|
Logger.getLogger(BluetoothPlugin.class.getName());
|
||||||
|
private static final int UUID_BYTES = 16;
|
||||||
|
|
||||||
private final Executor pluginExecutor;
|
private final Executor pluginExecutor;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
|
private final SecureRandom secureRandom;
|
||||||
private final DuplexPluginCallback callback;
|
private final DuplexPluginCallback callback;
|
||||||
private final long maxLatency, pollingInterval;
|
private final long maxLatency, pollingInterval;
|
||||||
private final Object discoveryLock = new Object();
|
private final Semaphore discoverySemaphore = new Semaphore(1);
|
||||||
private final ScheduledExecutorService scheduler;
|
private final ScheduledExecutorService scheduler;
|
||||||
|
|
||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
@@ -61,10 +65,11 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
private volatile LocalDevice localDevice = null;
|
private volatile LocalDevice localDevice = null;
|
||||||
|
|
||||||
BluetoothPlugin(@PluginExecutor Executor pluginExecutor, Clock clock,
|
BluetoothPlugin(@PluginExecutor Executor pluginExecutor, Clock clock,
|
||||||
DuplexPluginCallback callback, long maxLatency,
|
SecureRandom secureRandom, DuplexPluginCallback callback,
|
||||||
long pollingInterval) {
|
long maxLatency, long pollingInterval) {
|
||||||
this.pluginExecutor = pluginExecutor;
|
this.pluginExecutor = pluginExecutor;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
|
this.secureRandom = secureRandom;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.maxLatency = maxLatency;
|
this.maxLatency = maxLatency;
|
||||||
this.pollingInterval = pollingInterval;
|
this.pollingInterval = pollingInterval;
|
||||||
@@ -130,9 +135,17 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
return "btspp://" + address + ":" + uuid + ";name=RFCOMM";
|
return "btspp://" + address + ":" + uuid + ";name=RFCOMM";
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Get the UUID from the local transport properties
|
|
||||||
private String getUuid() {
|
private String getUuid() {
|
||||||
return UUID.nameUUIDFromBytes(new byte[0]).toString();
|
String uuid = callback.getLocalProperties().get("uuid");
|
||||||
|
if(uuid == null) {
|
||||||
|
byte[] random = new byte[UUID_BYTES];
|
||||||
|
secureRandom.nextBytes(random);
|
||||||
|
uuid = UUID.nameUUIDFromBytes(random).toString();
|
||||||
|
TransportProperties p = new TransportProperties();
|
||||||
|
p.put("uuid", uuid);
|
||||||
|
callback.mergeLocalProperties(p);
|
||||||
|
}
|
||||||
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryToClose(StreamConnectionNotifier scn) {
|
private void tryToClose(StreamConnectionNotifier scn) {
|
||||||
@@ -229,29 +242,33 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
long timeout) {
|
long timeout) {
|
||||||
if(!running) return null;
|
if(!running) return null;
|
||||||
// Use the same pseudo-random UUID as the contact
|
// Use the same pseudo-random UUID as the contact
|
||||||
String uuid = generateUuid(r.nextBytes(16));
|
byte[] b = r.nextBytes(UUID_BYTES);
|
||||||
|
String uuid = UUID.nameUUIDFromBytes(b).toString();
|
||||||
// Discover nearby devices and connect to any with the right UUID
|
// Discover nearby devices and connect to any with the right UUID
|
||||||
DiscoveryAgent discoveryAgent = localDevice.getDiscoveryAgent();
|
DiscoveryAgent discoveryAgent = localDevice.getDiscoveryAgent();
|
||||||
long end = clock.currentTimeMillis() + timeout;
|
long end = clock.currentTimeMillis() + timeout;
|
||||||
String url = null;
|
String url = null;
|
||||||
while(url == null && clock.currentTimeMillis() < end) {
|
while(url == null && clock.currentTimeMillis() < end) {
|
||||||
InvitationListener listener =
|
if(!discoverySemaphore.tryAcquire()) {
|
||||||
new InvitationListener(discoveryAgent, uuid);
|
if(LOG.isLoggable(INFO))
|
||||||
// FIXME: Avoid making alien calls with a lock held
|
LOG.info("Another device discovery is in progress");
|
||||||
synchronized(discoveryLock) {
|
return null;
|
||||||
try {
|
}
|
||||||
discoveryAgent.startInquiry(GIAC, listener);
|
try {
|
||||||
url = listener.waitForUrl();
|
InvitationListener listener =
|
||||||
} catch(BluetoothStateException e) {
|
new InvitationListener(discoveryAgent, uuid);
|
||||||
if(LOG.isLoggable(WARNING))
|
discoveryAgent.startInquiry(GIAC, listener);
|
||||||
LOG.log(WARNING, e.toString(), e);
|
url = listener.waitForUrl();
|
||||||
return null;
|
} catch(BluetoothStateException e) {
|
||||||
} catch(InterruptedException e) {
|
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
if(LOG.isLoggable(INFO))
|
return null;
|
||||||
LOG.info("Interrupted while waiting for URL");
|
} catch(InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
if(LOG.isLoggable(INFO))
|
||||||
return null;
|
LOG.info("Interrupted while waiting for URL");
|
||||||
}
|
Thread.currentThread().interrupt();
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
discoverySemaphore.release();
|
||||||
}
|
}
|
||||||
if(!running) return null;
|
if(!running) return null;
|
||||||
}
|
}
|
||||||
@@ -259,16 +276,12 @@ class BluetoothPlugin implements DuplexPlugin {
|
|||||||
return connect(url);
|
return connect(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String generateUuid(byte[] b) {
|
|
||||||
UUID uuid = UUID.nameUUIDFromBytes(b);
|
|
||||||
return uuid.toString().replaceAll("-", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public DuplexTransportConnection acceptInvitation(PseudoRandom r,
|
public DuplexTransportConnection acceptInvitation(PseudoRandom r,
|
||||||
long timeout) {
|
long timeout) {
|
||||||
if(!running) return null;
|
if(!running) return null;
|
||||||
// Use the same pseudo-random UUID as the contact
|
// Use the same pseudo-random UUID as the contact
|
||||||
String uuid = generateUuid(r.nextBytes(16));
|
byte[] b = r.nextBytes(UUID_BYTES);
|
||||||
|
String uuid = UUID.nameUUIDFromBytes(b).toString();
|
||||||
String url = makeUrl("localhost", uuid);
|
String url = makeUrl("localhost", uuid);
|
||||||
// Make the device discoverable if possible
|
// Make the device discoverable if possible
|
||||||
makeDeviceDiscoverable();
|
makeDeviceDiscoverable();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.sf.briar.plugins.bluetooth;
|
package net.sf.briar.plugins.bluetooth;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import net.sf.briar.api.clock.Clock;
|
import net.sf.briar.api.clock.Clock;
|
||||||
@@ -16,10 +17,13 @@ public class BluetoothPluginFactory implements DuplexPluginFactory {
|
|||||||
private static final long POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes
|
private static final long POLLING_INTERVAL = 3 * 60 * 1000; // 3 minutes
|
||||||
|
|
||||||
private final Executor pluginExecutor;
|
private final Executor pluginExecutor;
|
||||||
|
private final SecureRandom secureRandom;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
|
|
||||||
public BluetoothPluginFactory(@PluginExecutor Executor pluginExecutor) {
|
public BluetoothPluginFactory(@PluginExecutor Executor pluginExecutor,
|
||||||
|
SecureRandom secureRandom) {
|
||||||
this.pluginExecutor = pluginExecutor;
|
this.pluginExecutor = pluginExecutor;
|
||||||
|
this.secureRandom = secureRandom;
|
||||||
clock = new SystemClock();
|
clock = new SystemClock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +32,7 @@ public class BluetoothPluginFactory implements DuplexPluginFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
|
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
|
||||||
return new BluetoothPlugin(pluginExecutor, clock, callback,
|
return new BluetoothPlugin(pluginExecutor, clock, secureRandom,
|
||||||
MAX_LATENCY, POLLING_INTERVAL);
|
callback, MAX_LATENCY, POLLING_INTERVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import static java.util.logging.Level.WARNING;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -52,6 +53,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(DroidtoothPlugin.class.getName());
|
Logger.getLogger(DroidtoothPlugin.class.getName());
|
||||||
|
private static final int UUID_BYTES = 16;
|
||||||
private static final String FOUND = "android.bluetooth.device.action.FOUND";
|
private static final String FOUND = "android.bluetooth.device.action.FOUND";
|
||||||
private static final String DISCOVERY_FINISHED =
|
private static final String DISCOVERY_FINISHED =
|
||||||
"android.bluetooth.adapter.action.DISCOVERY_FINISHED";
|
"android.bluetooth.adapter.action.DISCOVERY_FINISHED";
|
||||||
@@ -59,6 +61,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
private final Executor pluginExecutor;
|
private final Executor pluginExecutor;
|
||||||
private final AndroidExecutor androidExecutor;
|
private final AndroidExecutor androidExecutor;
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
|
private final SecureRandom secureRandom;
|
||||||
private final DuplexPluginCallback callback;
|
private final DuplexPluginCallback callback;
|
||||||
private final long maxLatency, pollingInterval;
|
private final long maxLatency, pollingInterval;
|
||||||
|
|
||||||
@@ -69,11 +72,12 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
DroidtoothPlugin(@PluginExecutor Executor pluginExecutor,
|
DroidtoothPlugin(@PluginExecutor Executor pluginExecutor,
|
||||||
AndroidExecutor androidExecutor, Context appContext,
|
AndroidExecutor androidExecutor, Context appContext,
|
||||||
DuplexPluginCallback callback, long maxLatency,
|
SecureRandom secureRandom, DuplexPluginCallback callback,
|
||||||
long pollingInterval) {
|
long maxLatency, long pollingInterval) {
|
||||||
this.pluginExecutor = pluginExecutor;
|
this.pluginExecutor = pluginExecutor;
|
||||||
this.androidExecutor = androidExecutor;
|
this.androidExecutor = androidExecutor;
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
|
this.secureRandom = secureRandom;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.maxLatency = maxLatency;
|
this.maxLatency = maxLatency;
|
||||||
this.pollingInterval = pollingInterval;
|
this.pollingInterval = pollingInterval;
|
||||||
@@ -129,11 +133,12 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
p.put("address", adapter.getAddress());
|
p.put("address", adapter.getAddress());
|
||||||
callback.mergeLocalProperties(p);
|
callback.mergeLocalProperties(p);
|
||||||
// Bind a server socket to accept connections from contacts
|
// Bind a server socket to accept connections from contacts
|
||||||
BluetoothServerSocket ss;
|
BluetoothServerSocket ss = null;
|
||||||
try {
|
try {
|
||||||
ss = InsecureBluetooth.listen(adapter, "RFCOMM", getUuid());
|
ss = InsecureBluetooth.listen(adapter, "RFCOMM", getUuid());
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
tryToClose(ss);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!running) {
|
if(!running) {
|
||||||
@@ -161,14 +166,22 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Get the UUID from the local transport properties
|
|
||||||
private UUID getUuid() {
|
private UUID getUuid() {
|
||||||
return UUID.nameUUIDFromBytes(new byte[0]);
|
String uuid = callback.getLocalProperties().get("uuid");
|
||||||
|
if(uuid == null) {
|
||||||
|
byte[] random = new byte[UUID_BYTES];
|
||||||
|
secureRandom.nextBytes(random);
|
||||||
|
uuid = UUID.nameUUIDFromBytes(random).toString();
|
||||||
|
TransportProperties p = new TransportProperties();
|
||||||
|
p.put("uuid", uuid);
|
||||||
|
callback.mergeLocalProperties(p);
|
||||||
|
}
|
||||||
|
return UUID.fromString(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryToClose(BluetoothServerSocket ss) {
|
private void tryToClose(BluetoothServerSocket ss) {
|
||||||
try {
|
try {
|
||||||
ss.close();
|
if(ss != null) ss.close();
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
}
|
}
|
||||||
@@ -244,16 +257,28 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
// Try to connect
|
// Try to connect
|
||||||
BluetoothDevice d = adapter.getRemoteDevice(address);
|
BluetoothDevice d = adapter.getRemoteDevice(address);
|
||||||
|
BluetoothSocket s = null;
|
||||||
try {
|
try {
|
||||||
BluetoothSocket s = InsecureBluetooth.createSocket(d, u);
|
s = InsecureBluetooth.createSocket(d, u);
|
||||||
|
if(LOG.isLoggable(INFO)) LOG.info("Connecting to " + address);
|
||||||
s.connect();
|
s.connect();
|
||||||
|
if(LOG.isLoggable(INFO)) LOG.info("Connected to " + address);
|
||||||
return new DroidtoothTransportConnection(s, maxLatency);
|
return new DroidtoothTransportConnection(s, maxLatency);
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
tryToClose(s);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tryToClose(BluetoothSocket s) {
|
||||||
|
try {
|
||||||
|
if(s != null) s.close();
|
||||||
|
} catch(IOException e) {
|
||||||
|
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public DuplexTransportConnection createConnection(ContactId c) {
|
public DuplexTransportConnection createConnection(ContactId c) {
|
||||||
if(!running) return null;
|
if(!running) return null;
|
||||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
TransportProperties p = callback.getRemoteProperties().get(c);
|
||||||
@@ -273,7 +298,9 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
long timeout) {
|
long timeout) {
|
||||||
if(!running) return null;
|
if(!running) return null;
|
||||||
// Use the same pseudo-random UUID as the contact
|
// Use the same pseudo-random UUID as the contact
|
||||||
String uuid = UUID.nameUUIDFromBytes(r.nextBytes(16)).toString();
|
byte[] b = r.nextBytes(UUID_BYTES);
|
||||||
|
String uuid = UUID.nameUUIDFromBytes(b).toString();
|
||||||
|
if(LOG.isLoggable(INFO)) LOG.info("Sending invitation, UUID " + uuid);
|
||||||
// Register to receive Bluetooth discovery intents
|
// Register to receive Bluetooth discovery intents
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
filter.addAction(FOUND);
|
filter.addAction(FOUND);
|
||||||
@@ -296,18 +323,25 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
long timeout) {
|
long timeout) {
|
||||||
if(!running) return null;
|
if(!running) return null;
|
||||||
// Use the same pseudo-random UUID as the contact
|
// Use the same pseudo-random UUID as the contact
|
||||||
UUID uuid = UUID.nameUUIDFromBytes(r.nextBytes(16));
|
byte[] b = r.nextBytes(UUID_BYTES);
|
||||||
|
UUID uuid = UUID.nameUUIDFromBytes(b);
|
||||||
|
if(LOG.isLoggable(INFO)) LOG.info("Accepting invitation, UUID " + uuid);
|
||||||
// Bind a new server socket to accept the invitation connection
|
// Bind a new server socket to accept the invitation connection
|
||||||
final BluetoothServerSocket ss;
|
BluetoothServerSocket ss = null;
|
||||||
try {
|
try {
|
||||||
ss = InsecureBluetooth.listen(adapter, "RFCOMM", uuid);
|
ss = InsecureBluetooth.listen(adapter, "RFCOMM", uuid);
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
tryToClose(ss);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Return the first connection received by the socket, if any
|
// Return the first connection received by the socket, if any
|
||||||
try {
|
try {
|
||||||
BluetoothSocket s = ss.accept((int) timeout);
|
BluetoothSocket s = ss.accept((int) timeout);
|
||||||
|
if(LOG.isLoggable(INFO)) {
|
||||||
|
String address = s.getRemoteDevice().getAddress();
|
||||||
|
LOG.info("Incoming connection from " + address);
|
||||||
|
}
|
||||||
return new DroidtoothTransportConnection(s, maxLatency);
|
return new DroidtoothTransportConnection(s, maxLatency);
|
||||||
} catch(SocketTimeoutException e) {
|
} catch(SocketTimeoutException e) {
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Invitation timed out");
|
if(LOG.isLoggable(INFO)) LOG.info("Invitation timed out");
|
||||||
@@ -368,7 +402,8 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
connectToDiscoveredDevices();
|
connectToDiscoveredDevices();
|
||||||
} else if(action.equals(FOUND)) {
|
} else if(action.equals(FOUND)) {
|
||||||
BluetoothDevice d = intent.getParcelableExtra(EXTRA_DEVICE);
|
BluetoothDevice d = intent.getParcelableExtra(EXTRA_DEVICE);
|
||||||
addresses.add(d.getAddress());
|
String address = d.getAddress();
|
||||||
|
addresses.add(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.sf.briar.plugins.droidtooth;
|
package net.sf.briar.plugins.droidtooth;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import net.sf.briar.api.android.AndroidExecutor;
|
import net.sf.briar.api.android.AndroidExecutor;
|
||||||
@@ -18,12 +19,15 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
|
|||||||
private final Executor pluginExecutor;
|
private final Executor pluginExecutor;
|
||||||
private final AndroidExecutor androidExecutor;
|
private final AndroidExecutor androidExecutor;
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
|
private final SecureRandom secureRandom;
|
||||||
|
|
||||||
public DroidtoothPluginFactory(@PluginExecutor Executor pluginExecutor,
|
public DroidtoothPluginFactory(@PluginExecutor Executor pluginExecutor,
|
||||||
AndroidExecutor androidExecutor, Context appContext) {
|
AndroidExecutor androidExecutor, Context appContext,
|
||||||
|
SecureRandom secureRandom) {
|
||||||
this.pluginExecutor = pluginExecutor;
|
this.pluginExecutor = pluginExecutor;
|
||||||
this.androidExecutor = androidExecutor;
|
this.androidExecutor = androidExecutor;
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
|
this.secureRandom = secureRandom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransportId getId() {
|
public TransportId getId() {
|
||||||
@@ -32,6 +36,6 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
|
|||||||
|
|
||||||
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
|
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
|
||||||
return new DroidtoothPlugin(pluginExecutor, androidExecutor, appContext,
|
return new DroidtoothPlugin(pluginExecutor, androidExecutor, appContext,
|
||||||
callback, MAX_LATENCY, POLLING_INTERVAL);
|
secureRandom, callback, MAX_LATENCY, POLLING_INTERVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.sf.briar.plugins.bluetooth;
|
package net.sf.briar.plugins.bluetooth;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@@ -20,14 +21,14 @@ public class BluetoothClientTest extends DuplexClientTest {
|
|||||||
// Store the server's Bluetooth address and UUID
|
// Store the server's Bluetooth address and UUID
|
||||||
TransportProperties p = new TransportProperties();
|
TransportProperties p = new TransportProperties();
|
||||||
p.put("address", serverAddress);
|
p.put("address", serverAddress);
|
||||||
p.put("uuid", BluetoothTest.getUuid());
|
p.put("uuid", BluetoothTest.EMPTY_UUID);
|
||||||
Map<ContactId, TransportProperties> remote =
|
Map<ContactId, TransportProperties> remote =
|
||||||
Collections.singletonMap(contactId, p);
|
Collections.singletonMap(contactId, p);
|
||||||
// Create the plugin
|
// Create the plugin
|
||||||
callback = new ClientCallback(new TransportConfig(),
|
callback = new ClientCallback(new TransportConfig(),
|
||||||
new TransportProperties(), remote);
|
new TransportProperties(), remote);
|
||||||
plugin = new BluetoothPlugin(executor, new SystemClock(), callback, 0,
|
plugin = new BluetoothPlugin(executor, new SystemClock(),
|
||||||
0);
|
new SecureRandom(), callback, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.sf.briar.plugins.bluetooth;
|
package net.sf.briar.plugins.bluetooth;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
@@ -17,12 +18,12 @@ public class BluetoothServerTest extends DuplexServerTest {
|
|||||||
private BluetoothServerTest(Executor executor) {
|
private BluetoothServerTest(Executor executor) {
|
||||||
// Store the UUID
|
// Store the UUID
|
||||||
TransportProperties local = new TransportProperties();
|
TransportProperties local = new TransportProperties();
|
||||||
local.put("uuid", BluetoothTest.getUuid());
|
local.put("uuid", BluetoothTest.EMPTY_UUID);
|
||||||
// Create the plugin
|
// Create the plugin
|
||||||
callback = new ServerCallback(new TransportConfig(), local,
|
callback = new ServerCallback(new TransportConfig(), local,
|
||||||
Collections.singletonMap(contactId, new TransportProperties()));
|
Collections.singletonMap(contactId, new TransportProperties()));
|
||||||
plugin = new BluetoothPlugin(executor, new SystemClock(), callback, 0,
|
plugin = new BluetoothPlugin(executor, new SystemClock(),
|
||||||
0);
|
new SecureRandom(), callback, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
|||||||
@@ -4,10 +4,6 @@ import java.util.UUID;
|
|||||||
|
|
||||||
class BluetoothTest {
|
class BluetoothTest {
|
||||||
|
|
||||||
private static final String EMPTY_UUID =
|
static final String EMPTY_UUID =
|
||||||
UUID.nameUUIDFromBytes(new byte[0]).toString().replaceAll("-", "");
|
UUID.nameUUIDFromBytes(new byte[0]).toString();
|
||||||
|
|
||||||
static String getUuid() {
|
|
||||||
return EMPTY_UUID;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user