mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 05:09:53 +01:00
Merge branch '346-smaller-qr-codes' into 'master'
Encode transport properties more compactly in QR codes The [original BQP spec](https://code.briarproject.org/akwizgran/briar/wikis/BQP) described a compact encoding for transport properties, with the goal of making the QR code as small as possible. At some point during the implementation, I asked @str4d to use TransportIds and TransportProperties instead, as described in the [current spec](https://code.briarproject.org/akwizgran/briar-spec/blob/master/protocols/BQP.md). That was a mistake. Using the original format reduces the payload from 60 to 34 bytes (43% smaller) for Bluetooth only, and from 96 to 49 bytes (49% smaller) for Bluetooth and LAN. This makes it easier to scan codes from low-resolution screens using fixed-focus and/or low-resolution cameras. Using this branch I can exchange codes between the Sony Xperia Tipo (320x480 screen, fixed focus, 640x480 preview size) and the Huawei Ascend Y300 (480x800 screen, infinity focus, 1280x720 preview size). This also removes an obstacle to implementing #558, as TransportIds are no longer included in QR codes. Closes #346. See merge request !394
This commit is contained in:
@@ -2,9 +2,9 @@ package org.briarproject.plugins.tcp;
|
||||
|
||||
import org.briarproject.BriarTestCase;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.data.BdfList;
|
||||
import org.briarproject.api.keyagreement.KeyAgreementConnection;
|
||||
import org.briarproject.api.keyagreement.KeyAgreementListener;
|
||||
import org.briarproject.api.keyagreement.TransportDescriptor;
|
||||
import org.briarproject.api.plugins.Backoff;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
@@ -27,11 +27,12 @@ import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.briarproject.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
|
||||
import static org.briarproject.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -188,23 +189,22 @@ public class LanTcpPluginTest extends BriarTestCase {
|
||||
0, 0);
|
||||
plugin.start();
|
||||
assertTrue(callback.propertiesLatch.await(5, SECONDS));
|
||||
KeyAgreementListener kal = plugin.createKeyAgreementListener(null);
|
||||
KeyAgreementListener kal =
|
||||
plugin.createKeyAgreementListener(new byte[COMMIT_LENGTH]);
|
||||
assertNotNull(kal);
|
||||
Callable<KeyAgreementConnection> c = kal.listen();
|
||||
FutureTask<KeyAgreementConnection> f = new FutureTask<>(c);
|
||||
new Thread(f).start();
|
||||
// The plugin should have bound a socket and stored the port number
|
||||
TransportDescriptor d = kal.getDescriptor();
|
||||
TransportProperties p = d.getProperties();
|
||||
String ipPort = p.get("ipPort");
|
||||
assertNotNull(ipPort);
|
||||
String[] split = ipPort.split(":");
|
||||
assertEquals(2, split.length);
|
||||
String addrString = split[0], portString = split[1];
|
||||
InetAddress addr = InetAddress.getByName(addrString);
|
||||
BdfList descriptor = kal.getDescriptor();
|
||||
assertEquals(3, descriptor.size());
|
||||
assertEquals(TRANSPORT_ID_LAN, descriptor.getLong(0).longValue());
|
||||
byte[] address = descriptor.getRaw(1);
|
||||
InetAddress addr = InetAddress.getByAddress(address);
|
||||
assertTrue(addr instanceof Inet4Address);
|
||||
assertFalse(addr.isLoopbackAddress());
|
||||
assertTrue(addr.isLinkLocalAddress() || addr.isSiteLocalAddress());
|
||||
int port = Integer.parseInt(portString);
|
||||
int port = descriptor.getLong(2).intValue();
|
||||
assertTrue(port > 0 && port < 65536);
|
||||
// The plugin should be listening on the port
|
||||
InetSocketAddress socketAddr = new InetSocketAddress(addr, port);
|
||||
@@ -240,7 +240,6 @@ public class LanTcpPluginTest extends BriarTestCase {
|
||||
// Listen on the same interface as the plugin
|
||||
final ServerSocket ss = new ServerSocket();
|
||||
ss.bind(new InetSocketAddress(addrString, 0), 10);
|
||||
int port = ss.getLocalPort();
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
final AtomicBoolean error = new AtomicBoolean(false);
|
||||
new Thread() {
|
||||
@@ -255,12 +254,15 @@ public class LanTcpPluginTest extends BriarTestCase {
|
||||
}
|
||||
}.start();
|
||||
// Tell the plugin about the port
|
||||
TransportProperties p = new TransportProperties();
|
||||
p.put("ipPort", addrString + ":" + port);
|
||||
TransportDescriptor desc = new TransportDescriptor(plugin.getId(), p);
|
||||
BdfList descriptor = new BdfList();
|
||||
descriptor.add(TRANSPORT_ID_LAN);
|
||||
InetSocketAddress local =
|
||||
(InetSocketAddress) ss.getLocalSocketAddress();
|
||||
descriptor.add(local.getAddress().getAddress());
|
||||
descriptor.add(local.getPort());
|
||||
// Connect to the port
|
||||
DuplexTransportConnection d =
|
||||
plugin.createKeyAgreementConnection(null, desc, 5000);
|
||||
DuplexTransportConnection d = plugin.createKeyAgreementConnection(
|
||||
new byte[COMMIT_LENGTH], descriptor, 5000);
|
||||
assertNotNull(d);
|
||||
// Check that the connection was accepted
|
||||
assertTrue(latch.await(5, SECONDS));
|
||||
@@ -291,61 +293,76 @@ public class LanTcpPluginTest extends BriarTestCase {
|
||||
private final CountDownLatch connectionsLatch = new CountDownLatch(1);
|
||||
private final TransportProperties local = new TransportProperties();
|
||||
|
||||
@Override
|
||||
public Settings getSettings() {
|
||||
return new Settings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportProperties getLocalProperties() {
|
||||
return local;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<ContactId, TransportProperties> getRemoteProperties() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeSettings(Settings s) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeLocalProperties(TransportProperties p) {
|
||||
local.putAll(p);
|
||||
propertiesLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int showChoice(String[] options, String... message) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showConfirmationMessage(String... message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(String... message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incomingConnectionCreated(DuplexTransportConnection d) {
|
||||
connectionsLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outgoingConnectionCreated(ContactId c,
|
||||
DuplexTransportConnection d) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transportEnabled() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transportDisabled() {
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestBackoff implements Backoff {
|
||||
|
||||
@Override
|
||||
public int getPollingInterval() {
|
||||
return 60 * 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void increment() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,4 +173,55 @@ public class StringUtilsTest extends BriarTestCase {
|
||||
public void testTruncateUtf8EmptyInput() {
|
||||
assertEquals("", StringUtils.truncateUtf8("", 123));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMacToBytesRejectsShortMac() {
|
||||
StringUtils.macToBytes("00:00:00:00:00");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMacToBytesRejectsLongMac() {
|
||||
StringUtils.macToBytes("00:00:00:00:00:00:00");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMacToBytesRejectsInvalidCharacter() {
|
||||
StringUtils.macToBytes("00:00:00:00:00:0g");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMacToBytesRejectsInvalidFormat() {
|
||||
StringUtils.macToBytes("0:000:00:00:00:00");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMacToBytesUpperCase() {
|
||||
byte[] expected = new byte[] {0x0A, 0x1B, 0x2C, 0x3D, 0x4E, 0x5F};
|
||||
String mac = "0A:1B:2C:3D:4E:5F";
|
||||
assertArrayEquals(expected, StringUtils.macToBytes(mac));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMacToBytesLowerCase() {
|
||||
byte[] expected = new byte[] {0x0A, 0x1B, 0x2C, 0x3D, 0x4E, 0x5F};
|
||||
String mac = "0a:1b:2c:3d:4e:5f";
|
||||
assertArrayEquals(expected, StringUtils.macToBytes(mac));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMacToStringRejectsShortMac() {
|
||||
StringUtils.macToString(new byte[5]);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMacToStringRejectsLongMac() {
|
||||
StringUtils.macToString(new byte[7]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMacToString() {
|
||||
byte[] mac = new byte[] {0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f};
|
||||
String expected = "0A:1B:2C:3D:4E:5F";
|
||||
assertEquals(expected, StringUtils.macToString(mac));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user