From c776d1e893981b71d7b7a5580cb0e59e619732a1 Mon Sep 17 00:00:00 2001 From: akwizgran <akwizgran@users.sourceforge.net> Date: Wed, 27 Jan 2016 12:16:09 +0000 Subject: [PATCH] Include unique device ID in transport updates. --- .../src/org/briarproject/api/DeviceId.java | 16 ++++++++++ .../api/db/DatabaseComponent.java | 4 +++ .../src/org/briarproject/db/Database.java | 8 +++++ .../db/DatabaseComponentImpl.java | 18 +++++++++++ .../src/org/briarproject/db/JdbcDatabase.java | 6 ++++ .../TransportPropertyManagerImpl.java | 32 +++++++++++-------- .../TransportPropertyValidator.java | 10 +++--- .../org/briarproject/util/StringUtils.java | 3 +- 8 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 briar-api/src/org/briarproject/api/DeviceId.java diff --git a/briar-api/src/org/briarproject/api/DeviceId.java b/briar-api/src/org/briarproject/api/DeviceId.java new file mode 100644 index 0000000000..2b72d681de --- /dev/null +++ b/briar-api/src/org/briarproject/api/DeviceId.java @@ -0,0 +1,16 @@ +package org.briarproject.api; + +import java.util.Arrays; + +/** Type-safe wrapper for a byte array that uniquely identifies a device. */ +public class DeviceId extends UniqueId { + + public DeviceId(byte[] id) { + super(id); + } + + @Override + public boolean equals(Object o) { + return o instanceof DeviceId && Arrays.equals(id, ((DeviceId) o).id); + } +} diff --git a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java index dd165c4812..852affa2db 100644 --- a/briar-api/src/org/briarproject/api/db/DatabaseComponent.java +++ b/briar-api/src/org/briarproject/api/db/DatabaseComponent.java @@ -1,5 +1,6 @@ package org.briarproject.api.db; +import org.briarproject.api.DeviceId; import org.briarproject.api.TransportId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; @@ -137,6 +138,9 @@ public interface DatabaseComponent { /** Returns all contacts associated with the given local pseudonym. */ Collection<ContactId> getContacts(AuthorId a) throws DbException; + /** Returns the unique ID for this device. */ + DeviceId getDeviceId() throws DbException; + /** Returns the group with the given ID, if the user subscribes to it. */ Group getGroup(GroupId g) throws DbException; diff --git a/briar-core/src/org/briarproject/db/Database.java b/briar-core/src/org/briarproject/db/Database.java index 9236c6e296..e912671b53 100644 --- a/briar-core/src/org/briarproject/db/Database.java +++ b/briar-core/src/org/briarproject/db/Database.java @@ -1,5 +1,6 @@ package org.briarproject.db; +import org.briarproject.api.DeviceId; import org.briarproject.api.TransportId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; @@ -256,6 +257,13 @@ interface Database<T> { */ Collection<ContactId> getContacts(T txn, AuthorId a) throws DbException; + /** + * Returns the unique ID for this device. + * <p> + * Locking: read. + */ + DeviceId getDeviceId(T txn) throws DbException; + /** * Returns the amount of free storage space available to the database, in * bytes. This is based on the minimum of the space available on the device diff --git a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java index ccfa60eccf..39c0f796f0 100644 --- a/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java +++ b/briar-core/src/org/briarproject/db/DatabaseComponentImpl.java @@ -1,5 +1,6 @@ package org.briarproject.db; +import org.briarproject.api.DeviceId; import org.briarproject.api.TransportId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; @@ -542,6 +543,23 @@ class DatabaseComponentImpl<T> implements DatabaseComponent { } } + public DeviceId getDeviceId() throws DbException { + lock.readLock().lock(); + try { + T txn = db.startTransaction(); + try { + DeviceId id = db.getDeviceId(txn); + db.commitTransaction(txn); + return id; + } catch (DbException e) { + db.abortTransaction(txn); + throw e; + } + } finally { + lock.readLock().unlock(); + } + } + public Group getGroup(GroupId g) throws DbException { lock.readLock().lock(); try { diff --git a/briar-core/src/org/briarproject/db/JdbcDatabase.java b/briar-core/src/org/briarproject/db/JdbcDatabase.java index 63b6aa1861..411d7246c7 100644 --- a/briar-core/src/org/briarproject/db/JdbcDatabase.java +++ b/briar-core/src/org/briarproject/db/JdbcDatabase.java @@ -1,5 +1,6 @@ package org.briarproject.db; +import org.briarproject.api.DeviceId; import org.briarproject.api.TransportId; import org.briarproject.api.UniqueId; import org.briarproject.api.contact.Contact; @@ -484,6 +485,11 @@ abstract class JdbcDatabase implements Database<Connection> { if (interrupted) Thread.currentThread().interrupt(); } + public DeviceId getDeviceId(Connection txn) throws DbException { + Settings s = getSettings(txn, DEVICE_SETTINGS_NAMESPACE); + return new DeviceId(StringUtils.fromHexString(s.get(DEVICE_ID_KEY))); + } + public ContactId addContact(Connection txn, Author remote, AuthorId local) throws DbException { PreparedStatement ps = null; diff --git a/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java b/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java index 2d4fc5bcc1..5da83e49dd 100644 --- a/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java +++ b/briar-core/src/org/briarproject/properties/TransportPropertyManagerImpl.java @@ -2,6 +2,7 @@ package org.briarproject.properties; import com.google.inject.Inject; +import org.briarproject.api.DeviceId; import org.briarproject.api.FormatException; import org.briarproject.api.TransportId; import org.briarproject.api.UniqueId; @@ -43,6 +44,7 @@ import java.util.Map.Entry; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.logging.Logger; +import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH; import static org.briarproject.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; @@ -100,9 +102,10 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, db.addContactGroup(c, g); db.setVisibility(g.getId(), Collections.singletonList(c)); // Copy the latest local properties into the group + DeviceId dev = db.getDeviceId(); Map<TransportId, TransportProperties> local = getLocalProperties(); for (Entry<TransportId, TransportProperties> e : local.entrySet()) - storeMessage(g.getId(), e.getKey(), e.getValue(), 0); + storeMessage(g.getId(), dev, e.getKey(), e.getValue(), 0); } catch (DbException e) { if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); } catch (FormatException e) { @@ -141,9 +144,10 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, return out.toByteArray(); } - private void storeMessage(GroupId g, TransportId t, TransportProperties p, - long version) throws DbException, IOException { - byte[] body = encodeProperties(t, p, version); + private void storeMessage(GroupId g, DeviceId dev, TransportId t, + TransportProperties p, long version) throws DbException, + IOException { + byte[] body = encodeProperties(dev, t, p, version); long now = clock.currentTimeMillis(); Message m = messageFactory.createMessage(g, now, body); BdfDictionary d = new BdfDictionary(); @@ -153,13 +157,13 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, db.addLocalMessage(m, CLIENT_ID, metadataEncoder.encode(d)); } - private byte[] encodeProperties(TransportId t, TransportProperties p, - long version) { + private byte[] encodeProperties(DeviceId dev, TransportId t, + TransportProperties p, long version) { ByteArrayOutputStream out = new ByteArrayOutputStream(); BdfWriter w = bdfWriterFactory.createWriter(out); try { - // TODO: Device ID w.writeListStart(); + w.writeRaw(dev.getBytes()); w.writeString(t.getString()); w.writeInteger(version); w.writeDictionary(p); @@ -232,8 +236,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, ByteArrayInputStream in = new ByteArrayInputStream(raw, MESSAGE_HEADER_LENGTH, raw.length - MESSAGE_HEADER_LENGTH); BdfReader r = bdfReaderFactory.createReader(in); - // TODO: Device ID r.readListStart(); + r.skipRaw(); // Device ID r.skipString(); // Transport ID r.skipInteger(); // Version r.readDictionaryStart(); @@ -242,9 +246,6 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, String value = r.readString(MAX_PROPERTY_LENGTH); p.put(key, value); } - r.readDictionaryEnd(); - r.readListEnd(); - if (!r.eof()) throw new FormatException(); return p; } @@ -310,14 +311,19 @@ class TransportPropertyManagerImpl implements TransportPropertyManager, p = old; } // Store the merged properties in the local group + DeviceId dev = db.getDeviceId(); long version = latest == null ? 0 : latest.version + 1; - storeMessage(localGroup.getId(), t, p, version); + storeMessage(localGroup.getId(), dev, t, p, version); + if (LOG.isLoggable(INFO)) { + LOG.info("Stored local properties for " + t.getString() + + ", version " + version); + } // Store the merged properties in each contact's group for (Contact c : db.getContacts()) { Group g = getContactGroup(c); latest = findLatest(g.getId(), true).get(t); version = latest == null ? 0 : latest.version + 1; - storeMessage(g.getId(), t, p, version); + storeMessage(g.getId(), dev, t, p, version); } } catch (IOException e) { throw new DbException(e); diff --git a/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java b/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java index 0a140dd5ba..eeee9f3334 100644 --- a/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java +++ b/briar-core/src/org/briarproject/properties/TransportPropertyValidator.java @@ -1,6 +1,7 @@ package org.briarproject.properties; import org.briarproject.api.FormatException; +import org.briarproject.api.UniqueId; import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfReader; import org.briarproject.api.data.BdfReaderFactory; @@ -53,10 +54,11 @@ class TransportPropertyValidator implements MessageValidator { ByteArrayInputStream in = new ByteArrayInputStream(raw, MESSAGE_HEADER_LENGTH, raw.length - MESSAGE_HEADER_LENGTH); BdfReader r = bdfReaderFactory.createReader(in); - // TODO: Device ID r.readListStart(); - String id = r.readString(MAX_TRANSPORT_ID_LENGTH); - if (id.length() == 0) throw new FormatException(); + byte[] deviceId = r.readRaw(UniqueId.LENGTH); + if (deviceId.length != UniqueId.LENGTH) throw new FormatException(); + String transportId = r.readString(MAX_TRANSPORT_ID_LENGTH); + if (transportId.length() == 0) throw new FormatException(); long version = r.readInteger(); if (version < 0) throw new FormatException(); r.readDictionaryStart(); @@ -71,7 +73,7 @@ class TransportPropertyValidator implements MessageValidator { if (!r.eof()) throw new FormatException(); // Return the metadata BdfDictionary d = new BdfDictionary(); - d.put("transportId", id); + d.put("transportId", transportId); d.put("version", version); d.put("local", false); return metadataEncoder.encode(d); diff --git a/briar-core/src/org/briarproject/util/StringUtils.java b/briar-core/src/org/briarproject/util/StringUtils.java index 822831ac05..0753748e88 100644 --- a/briar-core/src/org/briarproject/util/StringUtils.java +++ b/briar-core/src/org/briarproject/util/StringUtils.java @@ -65,7 +65,8 @@ public class StringUtils { /** Converts the given hex string to a byte array. */ public static byte[] fromHexString(String hex) { int len = hex.length(); - if (len % 2 != 0) throw new IllegalArgumentException("Not a hex string"); + if (len % 2 != 0) + throw new IllegalArgumentException("Not a hex string"); byte[] bytes = new byte[len / 2]; for (int i = 0, j = 0; i < len; i += 2, j++) { int high = hexDigitToInt(hex.charAt(i)); -- GitLab