Merge branch '112-metadata' into 'master'

Structured metadata. #112

Task #112 involves defining an interface between the sync protocol and its clients. To avoid the need for clients to keep their own databases, which could get out of step with the sync protocol's database, we're giving clients that ability to store metadata in the sync protocol's database.

Metadata can be associated with any message, channel, or client. Each metadata object is a simple map from strings to byte arrays. We'll provide a simple query interface to retrieve metadata and/or data by specifying a set of metadata keys. Basically we're building a shitty NoSQL database... erm, I mean, an enterprise-grade key-value store.

The basic metadata object is kind of Spartan, so this patch provides an encoder and parser for storing structured metadata. This gives clients an easy way to associate structured data with messages and channels, while leaving them the option of using their own encoding if they prefer.

This MR depends on !49.

See merge request !50
This commit is contained in:
akwizgran
2016-01-12 12:03:39 +00:00
47 changed files with 852 additions and 429 deletions

View File

@@ -0,0 +1,49 @@
package org.briarproject.api.data;
import java.util.HashMap;
// This class is not thread-safe
public class BdfDictionary extends HashMap<String, Object> {
public Boolean getBoolean(String key, Boolean defaultValue) {
Object o = get(key);
if (o instanceof Boolean) return (Boolean) o;
return defaultValue;
}
public Long getInteger(String key, Long defaultValue) {
Object o = get(key);
if (o instanceof Long) return (Long) o;
return defaultValue;
}
public Double getFloat(String key, Double defaultValue) {
Object o = get(key);
if (o instanceof Double) return (Double) o;
return defaultValue;
}
public String getString(String key, String defaultValue) {
Object o = get(key);
if (o instanceof String) return (String) o;
return defaultValue;
}
public byte[] getRaw(String key, byte[] defaultValue) {
Object o = get(key);
if (o instanceof byte[]) return (byte[]) o;
return defaultValue;
}
public BdfList getList(String key, BdfList defaultValue) {
Object o = get(key);
if (o instanceof BdfList) return (BdfList) o;
return defaultValue;
}
public BdfDictionary getDictionary(String key, BdfDictionary defaultValue) {
Object o = get(key);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
return defaultValue;
}
}

View File

@@ -0,0 +1,49 @@
package org.briarproject.api.data;
import java.util.ArrayList;
// This class is not thread-safe
public class BdfList extends ArrayList<Object> {
public Boolean getBoolean(int index, Boolean defaultValue) {
Object o = get(index);
if (o instanceof Boolean) return (Boolean) o;
return defaultValue;
}
public Long getInteger(int index, Long defaultValue) {
Object o = get(index);
if (o instanceof Long) return (Long) o;
return defaultValue;
}
public Double getFloat(int index, Double defaultValue) {
Object o = get(index);
if (o instanceof Double) return (Double) o;
return defaultValue;
}
public String getString(int index, String defaultValue) {
Object o = get(index);
if (o instanceof String) return (String) o;
return defaultValue;
}
public byte[] getRaw(int index, byte[] defaultValue) {
Object o = get(index);
if (o instanceof byte[]) return (byte[]) o;
return defaultValue;
}
public BdfList getList(int index, BdfList defaultValue) {
Object o = get(index);
if (o instanceof BdfList) return (BdfList) o;
return defaultValue;
}
public BdfDictionary getDictionary(int index, BdfDictionary defaultValue) {
Object o = get(index);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
return defaultValue;
}
}

View File

@@ -2,7 +2,7 @@ package org.briarproject.api.data;
import java.io.IOException; import java.io.IOException;
public interface Reader { public interface BdfReader {
boolean eof() throws IOException; boolean eof() throws IOException;
void close() throws IOException; void close() throws IOException;
@@ -40,9 +40,9 @@ public interface Reader {
void readListEnd() throws IOException; void readListEnd() throws IOException;
void skipList() throws IOException; void skipList() throws IOException;
boolean hasMap() throws IOException; boolean hasDictionary() throws IOException;
void readMapStart() throws IOException; void readDictionaryStart() throws IOException;
boolean hasMapEnd() throws IOException; boolean hasDictionaryEnd() throws IOException;
void readMapEnd() throws IOException; void readDictionaryEnd() throws IOException;
void skipMap() throws IOException; void skipDictionary() throws IOException;
} }

View File

@@ -0,0 +1,8 @@
package org.briarproject.api.data;
import java.io.InputStream;
public interface BdfReaderFactory {
BdfReader createReader(InputStream in);
}

View File

@@ -4,7 +4,7 @@ import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
public interface Writer { public interface BdfWriter {
void flush() throws IOException; void flush() throws IOException;
void close() throws IOException; void close() throws IOException;
@@ -23,7 +23,7 @@ public interface Writer {
void writeListStart() throws IOException; void writeListStart() throws IOException;
void writeListEnd() throws IOException; void writeListEnd() throws IOException;
void writeMap(Map<?, ?> m) throws IOException; void writeDictionary(Map<?, ?> m) throws IOException;
void writeMapStart() throws IOException; void writeDictionaryStart() throws IOException;
void writeMapEnd() throws IOException; void writeDictionaryEnd() throws IOException;
} }

View File

@@ -0,0 +1,8 @@
package org.briarproject.api.data;
import java.io.OutputStream;
public interface BdfWriterFactory {
BdfWriter createWriter(OutputStream out);
}

View File

@@ -0,0 +1,9 @@
package org.briarproject.api.data;
import org.briarproject.api.FormatException;
import org.briarproject.api.db.Metadata;
public interface MetadataEncoder {
Metadata encode(BdfDictionary d) throws FormatException;
}

View File

@@ -0,0 +1,9 @@
package org.briarproject.api.data;
import org.briarproject.api.FormatException;
import org.briarproject.api.db.Metadata;
public interface MetadataParser {
BdfDictionary parse(Metadata m) throws FormatException;
}

View File

@@ -4,5 +4,5 @@ import java.io.IOException;
public interface ObjectReader<T> { public interface ObjectReader<T> {
T readObject(Reader r) throws IOException; T readObject(BdfReader r) throws IOException;
} }

View File

@@ -1,8 +0,0 @@
package org.briarproject.api.data;
import java.io.InputStream;
public interface ReaderFactory {
Reader createReader(InputStream in);
}

View File

@@ -1,8 +0,0 @@
package org.briarproject.api.data;
import java.io.OutputStream;
public interface WriterFactory {
Writer createWriter(OutputStream out);
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.api.db;
import java.util.Hashtable;
public class Metadata extends Hashtable<String, byte[]> {
/**
* Special value to indicate that a key is being removed.
*/
public static final byte[] REMOVE = new byte[0];
}

View File

@@ -0,0 +1,13 @@
package org.briarproject.data;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.BdfReaderFactory;
import java.io.InputStream;
class BdfReaderFactoryImpl implements BdfReaderFactory {
public BdfReader createReader(InputStream in) {
return new BdfReaderImpl(in);
}
}

View File

@@ -1,5 +1,15 @@
package org.briarproject.data; package org.briarproject.data;
import org.briarproject.api.FormatException;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.Consumer;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import static org.briarproject.data.Types.DICTIONARY;
import static org.briarproject.data.Types.END; import static org.briarproject.data.Types.END;
import static org.briarproject.data.Types.FALSE; import static org.briarproject.data.Types.FALSE;
import static org.briarproject.data.Types.FLOAT_64; import static org.briarproject.data.Types.FLOAT_64;
@@ -8,7 +18,6 @@ import static org.briarproject.data.Types.INT_32;
import static org.briarproject.data.Types.INT_64; import static org.briarproject.data.Types.INT_64;
import static org.briarproject.data.Types.INT_8; import static org.briarproject.data.Types.INT_8;
import static org.briarproject.data.Types.LIST; import static org.briarproject.data.Types.LIST;
import static org.briarproject.data.Types.MAP;
import static org.briarproject.data.Types.NULL; import static org.briarproject.data.Types.NULL;
import static org.briarproject.data.Types.RAW_16; import static org.briarproject.data.Types.RAW_16;
import static org.briarproject.data.Types.RAW_32; import static org.briarproject.data.Types.RAW_32;
@@ -18,17 +27,8 @@ import static org.briarproject.data.Types.STRING_32;
import static org.briarproject.data.Types.STRING_8; import static org.briarproject.data.Types.STRING_8;
import static org.briarproject.data.Types.TRUE; import static org.briarproject.data.Types.TRUE;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import org.briarproject.api.FormatException;
import org.briarproject.api.data.Consumer;
import org.briarproject.api.data.Reader;
// This class is not thread-safe // This class is not thread-safe
class ReaderImpl implements Reader { class BdfReaderImpl implements BdfReader {
private static final byte[] EMPTY_BUFFER = new byte[] {}; private static final byte[] EMPTY_BUFFER = new byte[] {};
@@ -39,7 +39,7 @@ class ReaderImpl implements Reader {
private byte next; private byte next;
private byte[] buf = new byte[8]; private byte[] buf = new byte[8];
ReaderImpl(InputStream in) { BdfReaderImpl(InputStream in) {
this.in = in; this.in = in;
} }
@@ -88,14 +88,14 @@ class ReaderImpl implements Reader {
} }
private void skipObject() throws IOException { private void skipObject() throws IOException {
if (hasBoolean()) skipBoolean(); if (hasNull()) skipNull();
else if (hasBoolean()) skipBoolean();
else if (hasInteger()) skipInteger(); else if (hasInteger()) skipInteger();
else if (hasFloat()) skipFloat(); else if (hasFloat()) skipFloat();
else if (hasString()) skipString(); else if (hasString()) skipString();
else if (hasRaw()) skipRaw(); else if (hasRaw()) skipRaw();
else if (hasList()) skipList(); else if (hasList()) skipList();
else if (hasMap()) skipMap(); else if (hasDictionary()) skipDictionary();
else if (hasNull()) skipNull();
else throw new FormatException(); else throw new FormatException();
} }
@@ -173,18 +173,13 @@ class ReaderImpl implements Reader {
private short readInt16(boolean consume) throws IOException { private short readInt16(boolean consume) throws IOException {
readIntoBuffer(2, consume); readIntoBuffer(2, consume);
short value = (short) (((buf[0] & 0xFF) << 8) + (buf[1] & 0xFF)); return (short) (((buf[0] & 0xFF) << 8) + (buf[1] & 0xFF));
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
throw new FormatException();
return value;
} }
private int readInt32(boolean consume) throws IOException { private int readInt32(boolean consume) throws IOException {
readIntoBuffer(4, consume); readIntoBuffer(4, consume);
int value = 0; int value = 0;
for (int i = 0; i < 4; i++) value |= (buf[i] & 0xFF) << (24 - i * 8); for (int i = 0; i < 4; i++) value |= (buf[i] & 0xFF) << (24 - i * 8);
if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
throw new FormatException();
return value; return value;
} }
@@ -192,8 +187,6 @@ class ReaderImpl implements Reader {
readIntoBuffer(8, consume); readIntoBuffer(8, consume);
long value = 0; long value = 0;
for (int i = 0; i < 8; i++) value |= (buf[i] & 0xFFL) << (56 - i * 8); for (int i = 0; i < 8; i++) value |= (buf[i] & 0xFFL) << (56 - i * 8);
if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE)
throw new FormatException();
return value; return value;
} }
@@ -327,30 +320,30 @@ class ReaderImpl implements Reader {
hasLookahead = false; hasLookahead = false;
} }
public boolean hasMap() throws IOException { public boolean hasDictionary() throws IOException {
if (!hasLookahead) readLookahead(); if (!hasLookahead) readLookahead();
if (eof) return false; if (eof) return false;
return next == MAP; return next == DICTIONARY;
} }
public void readMapStart() throws IOException { public void readDictionaryStart() throws IOException {
if (!hasMap()) throw new FormatException(); if (!hasDictionary()) throw new FormatException();
consumeLookahead(); consumeLookahead();
} }
public boolean hasMapEnd() throws IOException { public boolean hasDictionaryEnd() throws IOException {
return hasEnd(); return hasEnd();
} }
public void readMapEnd() throws IOException { public void readDictionaryEnd() throws IOException {
readEnd(); readEnd();
} }
public void skipMap() throws IOException { public void skipDictionary() throws IOException {
if (!hasMap()) throw new FormatException(); if (!hasDictionary()) throw new FormatException();
hasLookahead = false; hasLookahead = false;
while (!hasMapEnd()) { while (!hasDictionaryEnd()) {
skipObject(); skipString();
skipObject(); skipObject();
} }
hasLookahead = false; hasLookahead = false;

View File

@@ -0,0 +1,13 @@
package org.briarproject.data;
import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.BdfWriterFactory;
import java.io.OutputStream;
class BdfWriterFactoryImpl implements BdfWriterFactory {
public BdfWriter createWriter(OutputStream out) {
return new BdfWriterImpl(out);
}
}

View File

@@ -1,22 +1,9 @@
package org.briarproject.data; package org.briarproject.data;
import static org.briarproject.data.Types.END; import org.briarproject.api.Bytes;
import static org.briarproject.data.Types.FALSE; import org.briarproject.api.FormatException;
import static org.briarproject.data.Types.FLOAT_64; import org.briarproject.api.data.BdfWriter;
import static org.briarproject.data.Types.INT_16; import org.briarproject.api.data.Consumer;
import static org.briarproject.data.Types.INT_32;
import static org.briarproject.data.Types.INT_64;
import static org.briarproject.data.Types.INT_8;
import static org.briarproject.data.Types.LIST;
import static org.briarproject.data.Types.MAP;
import static org.briarproject.data.Types.NULL;
import static org.briarproject.data.Types.RAW_16;
import static org.briarproject.data.Types.RAW_32;
import static org.briarproject.data.Types.RAW_8;
import static org.briarproject.data.Types.STRING_16;
import static org.briarproject.data.Types.STRING_32;
import static org.briarproject.data.Types.STRING_8;
import static org.briarproject.data.Types.TRUE;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
@@ -26,17 +13,31 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.briarproject.api.Bytes; import static org.briarproject.data.Types.DICTIONARY;
import org.briarproject.api.data.Consumer; import static org.briarproject.data.Types.END;
import org.briarproject.api.data.Writer; import static org.briarproject.data.Types.FALSE;
import static org.briarproject.data.Types.FLOAT_64;
import static org.briarproject.data.Types.INT_16;
import static org.briarproject.data.Types.INT_32;
import static org.briarproject.data.Types.INT_64;
import static org.briarproject.data.Types.INT_8;
import static org.briarproject.data.Types.LIST;
import static org.briarproject.data.Types.NULL;
import static org.briarproject.data.Types.RAW_16;
import static org.briarproject.data.Types.RAW_32;
import static org.briarproject.data.Types.RAW_8;
import static org.briarproject.data.Types.STRING_16;
import static org.briarproject.data.Types.STRING_32;
import static org.briarproject.data.Types.STRING_8;
import static org.briarproject.data.Types.TRUE;
// This class is not thread-safe // This class is not thread-safe
class WriterImpl implements Writer { class BdfWriterImpl implements BdfWriter {
private final OutputStream out; private final OutputStream out;
private final Collection<Consumer> consumers = new ArrayList<Consumer>(0); private final Collection<Consumer> consumers = new ArrayList<Consumer>(0);
WriterImpl(OutputStream out) { BdfWriterImpl(OutputStream out) {
this.out = out; this.out = out;
} }
@@ -145,7 +146,8 @@ class WriterImpl implements Writer {
} }
private void writeObject(Object o) throws IOException { private void writeObject(Object o) throws IOException {
if (o instanceof Boolean) writeBoolean((Boolean) o); if (o == null) writeNull();
else if (o instanceof Boolean) writeBoolean((Boolean) o);
else if (o instanceof Byte) writeInteger((Byte) o); else if (o instanceof Byte) writeInteger((Byte) o);
else if (o instanceof Short) writeInteger((Short) o); else if (o instanceof Short) writeInteger((Short) o);
else if (o instanceof Integer) writeInteger((Integer) o); else if (o instanceof Integer) writeInteger((Integer) o);
@@ -155,10 +157,9 @@ class WriterImpl implements Writer {
else if (o instanceof String) writeString((String) o); else if (o instanceof String) writeString((String) o);
else if (o instanceof byte[]) writeRaw((byte[]) o); else if (o instanceof byte[]) writeRaw((byte[]) o);
else if (o instanceof Bytes) writeRaw(((Bytes) o).getBytes()); else if (o instanceof Bytes) writeRaw(((Bytes) o).getBytes());
else if (o instanceof List<?>) writeList((List<?>) o); else if (o instanceof List) writeList((List) o);
else if (o instanceof Map<?, ?>) writeMap((Map<?, ?>) o); else if (o instanceof Map) writeDictionary((Map) o);
else if (o == null) writeNull(); else throw new FormatException();
else throw new IllegalStateException();
} }
public void writeListStart() throws IOException { public void writeListStart() throws IOException {
@@ -169,20 +170,21 @@ class WriterImpl implements Writer {
write(END); write(END);
} }
public void writeMap(Map<?, ?> m) throws IOException { public void writeDictionary(Map<?, ?> m) throws IOException {
write(MAP); write(DICTIONARY);
for (Entry<?, ?> e : m.entrySet()) { for (Entry<?, ?> e : m.entrySet()) {
writeObject(e.getKey()); if (!(e.getKey() instanceof String)) throw new FormatException();
writeString((String) e.getKey());
writeObject(e.getValue()); writeObject(e.getValue());
} }
write(END); write(END);
} }
public void writeMapStart() throws IOException { public void writeDictionaryStart() throws IOException {
write(MAP); write(DICTIONARY);
} }
public void writeMapEnd() throws IOException { public void writeDictionaryEnd() throws IOException {
write(END); write(END);
} }

View File

@@ -1,15 +1,19 @@
package org.briarproject.data; package org.briarproject.data;
import org.briarproject.api.data.ReaderFactory;
import org.briarproject.api.data.WriterFactory;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.data.MetadataParser;
public class DataModule extends AbstractModule { public class DataModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
bind(ReaderFactory.class).to(ReaderFactoryImpl.class); bind(BdfReaderFactory.class).to(BdfReaderFactoryImpl.class);
bind(WriterFactory.class).to(WriterFactoryImpl.class); bind(BdfWriterFactory.class).to(BdfWriterFactoryImpl.class);
bind(MetadataParser.class).to(MetadataParserImpl.class);
bind(MetadataEncoder.class).to(MetadataEncoderImpl.class);
} }
} }

View File

@@ -0,0 +1,175 @@
package org.briarproject.data;
import org.briarproject.api.FormatException;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.db.Metadata;
import org.briarproject.util.StringUtils;
import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import static org.briarproject.api.db.Metadata.REMOVE;
import static org.briarproject.data.Types.DICTIONARY;
import static org.briarproject.data.Types.END;
import static org.briarproject.data.Types.FALSE;
import static org.briarproject.data.Types.FLOAT_64;
import static org.briarproject.data.Types.INT_16;
import static org.briarproject.data.Types.INT_32;
import static org.briarproject.data.Types.INT_64;
import static org.briarproject.data.Types.INT_8;
import static org.briarproject.data.Types.LIST;
import static org.briarproject.data.Types.NULL;
import static org.briarproject.data.Types.RAW_16;
import static org.briarproject.data.Types.RAW_32;
import static org.briarproject.data.Types.RAW_8;
import static org.briarproject.data.Types.STRING_16;
import static org.briarproject.data.Types.STRING_32;
import static org.briarproject.data.Types.STRING_8;
import static org.briarproject.data.Types.TRUE;
class MetadataEncoderImpl implements MetadataEncoder {
@Override
public Metadata encode(BdfDictionary d) throws FormatException {
Metadata m = new Metadata();
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (Entry<String, Object> e : d.entrySet()) {
if (e.getValue() == null) {
// Special case: if the value is null, the key is being removed
m.put(e.getKey(), REMOVE);
} else {
encodeObject(out, e.getValue());
m.put(e.getKey(), out.toByteArray());
out.reset();
}
}
return m;
}
private void encodeObject(ByteArrayOutputStream out, Object o)
throws FormatException {
if (o == null) out.write(NULL);
else if (o instanceof Boolean) out.write((Boolean) o ? TRUE : FALSE);
else if (o instanceof Byte) encodeInteger(out, (Byte) o);
else if (o instanceof Short) encodeInteger(out, (Short) o);
else if (o instanceof Integer) encodeInteger(out, (Integer) o);
else if (o instanceof Long) encodeInteger(out, (Long) o);
else if (o instanceof Float) encodeFloat(out, (Float) o);
else if (o instanceof Double) encodeFloat(out, (Double) o);
else if (o instanceof String) encodeString(out, (String) o);
else if (o instanceof byte[]) encodeRaw(out, (byte[]) o);
else if (o instanceof List) encodeList(out, (List) o);
else if (o instanceof Map) encodeDictionary(out, (Map) o);
else throw new FormatException();
}
private void encodeInteger(ByteArrayOutputStream out, byte i) {
out.write(INT_8);
out.write(i);
}
private void encodeInteger(ByteArrayOutputStream out, short i) {
if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE) {
encodeInteger(out, (byte) i);
} else {
out.write(INT_16);
out.write((byte) (i >> 8));
out.write((byte) ((i << 8) >> 8));
}
}
private void encodeInteger(ByteArrayOutputStream out, int i) {
if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) {
encodeInteger(out, (short) i);
} else {
out.write(INT_32);
out.write((byte) (i >> 24));
out.write((byte) ((i << 8) >> 24));
out.write((byte) ((i << 16) >> 24));
out.write((byte) ((i << 24) >> 24));
}
}
private void encodeInteger(ByteArrayOutputStream out, long i) {
if (i >= Integer.MIN_VALUE && i <= Integer.MAX_VALUE) {
encodeInteger(out, (int) i);
} else {
out.write(INT_64);
out.write((byte) (i >> 56));
out.write((byte) ((i << 8) >> 56));
out.write((byte) ((i << 16) >> 56));
out.write((byte) ((i << 24) >> 56));
out.write((byte) ((i << 32) >> 56));
out.write((byte) ((i << 40) >> 56));
out.write((byte) ((i << 48) >> 56));
out.write((byte) ((i << 56) >> 56));
}
}
private void encodeFloat(ByteArrayOutputStream out, float f) {
encodeFloat(out, (double) f);
}
private void encodeFloat(ByteArrayOutputStream out, double d) {
long i = Double.doubleToLongBits(d);
out.write(FLOAT_64);
out.write((byte) (i >> 56));
out.write((byte) ((i << 8) >> 56));
out.write((byte) ((i << 16) >> 56));
out.write((byte) ((i << 24) >> 56));
out.write((byte) ((i << 32) >> 56));
out.write((byte) ((i << 40) >> 56));
out.write((byte) ((i << 48) >> 56));
out.write((byte) ((i << 56) >> 56));
}
private void encodeString(ByteArrayOutputStream out, String s) {
byte[] b = StringUtils.toUtf8(s);
if (b.length <= Byte.MAX_VALUE) {
out.write(STRING_8);
encodeInteger(out, (byte) b.length);
} else if (b.length <= Short.MAX_VALUE) {
out.write(STRING_16);
encodeInteger(out, (short) b.length);
} else {
out.write(STRING_32);
encodeInteger(out, b.length);
}
out.write(b, 0, b.length);
}
private void encodeRaw(ByteArrayOutputStream out, byte[] b) {
if (b.length <= Byte.MAX_VALUE) {
out.write(RAW_8);
encodeInteger(out, (byte) b.length);
} else if (b.length <= Short.MAX_VALUE) {
out.write(RAW_16);
encodeInteger(out, (short) b.length);
} else {
out.write(RAW_32);
encodeInteger(out, b.length);
}
out.write(b, 0, b.length);
}
private void encodeList(ByteArrayOutputStream out, List list)
throws FormatException {
out.write(LIST);
for (Object o : list) encodeObject(out, o);
out.write(END);
}
private void encodeDictionary(ByteArrayOutputStream out, Map<?, ?> map)
throws FormatException {
out.write(DICTIONARY);
for (Entry<?, ?> e : map.entrySet()) {
if (!(e.getKey() instanceof String)) throw new FormatException();
encodeString(out, (String) e.getKey());
encodeObject(out, e.getValue());
}
out.write(END);
}
}

View File

@@ -0,0 +1,165 @@
package org.briarproject.data;
import org.briarproject.api.FormatException;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataParser;
import org.briarproject.api.db.Metadata;
import org.briarproject.util.StringUtils;
import java.io.ByteArrayInputStream;
import java.util.Map.Entry;
import static org.briarproject.api.db.Metadata.REMOVE;
import static org.briarproject.data.Types.DICTIONARY;
import static org.briarproject.data.Types.END;
import static org.briarproject.data.Types.FALSE;
import static org.briarproject.data.Types.FLOAT_64;
import static org.briarproject.data.Types.INT_16;
import static org.briarproject.data.Types.INT_32;
import static org.briarproject.data.Types.INT_64;
import static org.briarproject.data.Types.INT_8;
import static org.briarproject.data.Types.LIST;
import static org.briarproject.data.Types.NULL;
import static org.briarproject.data.Types.RAW_16;
import static org.briarproject.data.Types.RAW_32;
import static org.briarproject.data.Types.RAW_8;
import static org.briarproject.data.Types.STRING_16;
import static org.briarproject.data.Types.STRING_32;
import static org.briarproject.data.Types.STRING_8;
import static org.briarproject.data.Types.TRUE;
class MetadataParserImpl implements MetadataParser {
@Override
public BdfDictionary parse(Metadata m) throws FormatException {
BdfDictionary dict = new BdfDictionary();
for (Entry<String, byte[]> e : m.entrySet())
dict.put(e.getKey(), parseObject(e.getValue()));
return dict;
}
private Object parseObject(byte[] b) throws FormatException {
if (b == REMOVE) return null;
ByteArrayInputStream in = new ByteArrayInputStream(b);
Object o = parseObject(in);
if (in.available() > 0) throw new FormatException();
return o;
}
private Object parseObject(ByteArrayInputStream in) throws FormatException {
switch(in.read()) {
case NULL:
return null;
case TRUE:
return Boolean.TRUE;
case FALSE:
return Boolean.FALSE;
case INT_8:
return (long) parseInt8(in);
case INT_16:
return (long) parseInt16(in);
case INT_32:
return (long) parseInt32(in);
case INT_64:
return parseInt64(in);
case FLOAT_64:
return Double.longBitsToDouble(parseInt64(in));
case STRING_8:
return parseString(in, parseInt8(in));
case STRING_16:
return parseString(in, parseInt16(in));
case STRING_32:
return parseString(in, parseInt32(in));
case RAW_8:
return parseRaw(in, parseInt8(in));
case RAW_16:
return parseRaw(in, parseInt16(in));
case RAW_32:
return parseRaw(in, parseInt32(in));
case LIST:
return parseList(in);
case DICTIONARY:
return parseDictionary(in);
default:
throw new FormatException();
}
}
private String parseString(ByteArrayInputStream in) throws FormatException {
switch(in.read()) {
case STRING_8:
return parseString(in, parseInt8(in));
case STRING_16:
return parseString(in, parseInt16(in));
case STRING_32:
return parseString(in, parseInt32(in));
default:
throw new FormatException();
}
}
private byte parseInt8(ByteArrayInputStream in) throws FormatException {
if (in.available() < 1) throw new FormatException();
return (byte) in.read();
}
private short parseInt16(ByteArrayInputStream in) throws FormatException {
if (in.available() < 2) throw new FormatException();
return (short) (((in.read() & 0xFF) << 8) + (in.read() & 0xFF));
}
private int parseInt32(ByteArrayInputStream in) throws FormatException {
if (in.available() < 4) throw new FormatException();
int value = 0;
for (int i = 0; i < 4; i++)
value |= (in.read() & 0xFF) << (24 - i * 8);
return value;
}
private long parseInt64(ByteArrayInputStream in) throws FormatException {
if (in.available() < 8) throw new FormatException();
long value = 0;
for (int i = 0; i < 8; i++)
value |= (in.read() & 0xFFL) << (56 - i * 8);
return value;
}
private String parseString(ByteArrayInputStream in, int len)
throws FormatException {
if (len < 0) throw new FormatException();
byte[] b = new byte[len];
if (in.read(b, 0, len) != len) throw new FormatException();
return StringUtils.fromUtf8(b, 0, len);
}
private byte[] parseRaw(ByteArrayInputStream in, int len)
throws FormatException {
if (len < 0) throw new FormatException();
byte[] b = new byte[len];
if (in.read(b, 0, len) != len) throw new FormatException();
return b;
}
private BdfList parseList(ByteArrayInputStream in) throws FormatException {
BdfList list = new BdfList();
while (peek(in) != END) list.add(parseObject(in));
if (in.read() != END) throw new FormatException();
return list;
}
private BdfDictionary parseDictionary(ByteArrayInputStream in)
throws FormatException {
BdfDictionary dict = new BdfDictionary();
while (peek(in) != END) dict.put(parseString(in), parseObject(in));
if (in.read() != END) throw new FormatException();
return dict;
}
private int peek(ByteArrayInputStream in) {
in.mark(1);
int next = in.read();
in.reset();
return next;
}
}

View File

@@ -1,13 +0,0 @@
package org.briarproject.data;
import java.io.InputStream;
import org.briarproject.api.data.Reader;
import org.briarproject.api.data.ReaderFactory;
class ReaderFactoryImpl implements ReaderFactory {
public Reader createReader(InputStream in) {
return new ReaderImpl(in);
}
}

View File

@@ -17,6 +17,6 @@ interface Types {
byte RAW_16 = 0x52; byte RAW_16 = 0x52;
byte RAW_32 = 0x54; byte RAW_32 = 0x54;
byte LIST = 0x60; byte LIST = 0x60;
byte MAP = 0x70; byte DICTIONARY = 0x70;
byte END = (byte) 0x80; byte END = (byte) 0x80;
} }

View File

@@ -1,13 +0,0 @@
package org.briarproject.data;
import java.io.OutputStream;
import org.briarproject.api.data.Writer;
import org.briarproject.api.data.WriterFactory;
class WriterFactoryImpl implements WriterFactory {
public Writer createWriter(OutputStream out) {
return new WriterImpl(out);
}
}

View File

@@ -6,10 +6,10 @@ import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.PseudoRandom; import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.data.Reader; import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.ReaderFactory; import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.Writer; import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.WriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.AuthorFactory;
@@ -42,7 +42,8 @@ class AliceConnector extends Connector {
Logger.getLogger(AliceConnector.class.getName()); Logger.getLogger(AliceConnector.class.getName());
AliceConnector(CryptoComponent crypto, AliceConnector(CryptoComponent crypto,
ReaderFactory readerFactory, WriterFactory writerFactory, BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory, StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory, StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, GroupFactory groupFactory, AuthorFactory authorFactory, GroupFactory groupFactory,
@@ -53,7 +54,7 @@ class AliceConnector extends Connector {
LocalAuthor localAuthor, LocalAuthor localAuthor,
Map<TransportId, TransportProperties> localProps, Map<TransportId, TransportProperties> localProps,
PseudoRandom random) { PseudoRandom random) {
super(crypto, readerFactory, writerFactory, streamReaderFactory, super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory,
streamWriterFactory, authorFactory, groupFactory, streamWriterFactory, authorFactory, groupFactory,
keyManager, connectionManager, contactManager, keyManager, connectionManager, contactManager,
messagingManager, transportPropertyManager, clock, messagingManager, transportPropertyManager, clock,
@@ -76,14 +77,14 @@ class AliceConnector extends Connector {
// Carry out the key agreement protocol // Carry out the key agreement protocol
InputStream in; InputStream in;
OutputStream out; OutputStream out;
Reader r; BdfReader r;
Writer w; BdfWriter w;
SecretKey master; SecretKey master;
try { try {
in = conn.getReader().getInputStream(); in = conn.getReader().getInputStream();
out = conn.getWriter().getOutputStream(); out = conn.getWriter().getOutputStream();
r = readerFactory.createReader(in); r = bdfReaderFactory.createReader(in);
w = writerFactory.createWriter(out); w = bdfWriterFactory.createWriter(out);
// Alice goes first // Alice goes first
sendPublicKeyHash(w); sendPublicKeyHash(w);
byte[] hash = receivePublicKeyHash(r); byte[] hash = receivePublicKeyHash(r);
@@ -144,12 +145,12 @@ class AliceConnector extends Connector {
InputStream streamReader = InputStream streamReader =
streamReaderFactory.createInvitationStreamReader(in, streamReaderFactory.createInvitationStreamReader(in,
bobHeaderKey); bobHeaderKey);
r = readerFactory.createReader(streamReader); r = bdfReaderFactory.createReader(streamReader);
// Create the writers // Create the writers
OutputStream streamWriter = OutputStream streamWriter =
streamWriterFactory.createInvitationStreamWriter(out, streamWriterFactory.createInvitationStreamWriter(out,
aliceHeaderKey); aliceHeaderKey);
w = writerFactory.createWriter(streamWriter); w = bdfWriterFactory.createWriter(streamWriter);
// Derive the invitation nonces // Derive the invitation nonces
byte[] aliceNonce = crypto.deriveSignatureNonce(master, true); byte[] aliceNonce = crypto.deriveSignatureNonce(master, true);
byte[] bobNonce = crypto.deriveSignatureNonce(master, false); byte[] bobNonce = crypto.deriveSignatureNonce(master, false);

View File

@@ -6,10 +6,10 @@ import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.PseudoRandom; import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.data.Reader; import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.ReaderFactory; import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.Writer; import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.WriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.AuthorFactory;
@@ -42,7 +42,8 @@ class BobConnector extends Connector {
Logger.getLogger(BobConnector.class.getName()); Logger.getLogger(BobConnector.class.getName());
BobConnector(CryptoComponent crypto, BobConnector(CryptoComponent crypto,
ReaderFactory readerFactory, WriterFactory writerFactory, BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory, StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory, StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, GroupFactory groupFactory, AuthorFactory authorFactory, GroupFactory groupFactory,
@@ -53,7 +54,7 @@ class BobConnector extends Connector {
LocalAuthor localAuthor, LocalAuthor localAuthor,
Map<TransportId, TransportProperties> localProps, Map<TransportId, TransportProperties> localProps,
PseudoRandom random) { PseudoRandom random) {
super(crypto, readerFactory, writerFactory, streamReaderFactory, super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory,
streamWriterFactory, authorFactory, groupFactory, streamWriterFactory, authorFactory, groupFactory,
keyManager, connectionManager, contactManager, keyManager, connectionManager, contactManager,
messagingManager, transportPropertyManager, clock, messagingManager, transportPropertyManager, clock,
@@ -70,14 +71,14 @@ class BobConnector extends Connector {
// Carry out the key agreement protocol // Carry out the key agreement protocol
InputStream in; InputStream in;
OutputStream out; OutputStream out;
Reader r; BdfReader r;
Writer w; BdfWriter w;
SecretKey master; SecretKey master;
try { try {
in = conn.getReader().getInputStream(); in = conn.getReader().getInputStream();
out = conn.getWriter().getOutputStream(); out = conn.getWriter().getOutputStream();
r = readerFactory.createReader(in); r = bdfReaderFactory.createReader(in);
w = writerFactory.createWriter(out); w = bdfWriterFactory.createWriter(out);
// Alice goes first // Alice goes first
byte[] hash = receivePublicKeyHash(r); byte[] hash = receivePublicKeyHash(r);
// Don't proceed with more than one connection // Don't proceed with more than one connection
@@ -144,12 +145,12 @@ class BobConnector extends Connector {
InputStream streamReader = InputStream streamReader =
streamReaderFactory.createInvitationStreamReader(in, streamReaderFactory.createInvitationStreamReader(in,
aliceHeaderKey); aliceHeaderKey);
r = readerFactory.createReader(streamReader); r = bdfReaderFactory.createReader(streamReader);
// Create the writers // Create the writers
OutputStream streamWriter = OutputStream streamWriter =
streamWriterFactory.createInvitationStreamWriter(out, streamWriterFactory.createInvitationStreamWriter(out,
bobHeaderKey); bobHeaderKey);
w = writerFactory.createWriter(streamWriter); w = bdfWriterFactory.createWriter(streamWriter);
// Derive the nonces // Derive the nonces
byte[] aliceNonce = crypto.deriveSignatureNonce(master, true); byte[] aliceNonce = crypto.deriveSignatureNonce(master, true);
byte[] bobNonce = crypto.deriveSignatureNonce(master, false); byte[] bobNonce = crypto.deriveSignatureNonce(master, false);

View File

@@ -12,10 +12,10 @@ import org.briarproject.api.crypto.MessageDigest;
import org.briarproject.api.crypto.PseudoRandom; import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.crypto.Signature; import org.briarproject.api.crypto.Signature;
import org.briarproject.api.data.Reader; import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.ReaderFactory; import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.Writer; import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.WriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.AuthorFactory;
@@ -56,8 +56,8 @@ abstract class Connector extends Thread {
Logger.getLogger(Connector.class.getName()); Logger.getLogger(Connector.class.getName());
protected final CryptoComponent crypto; protected final CryptoComponent crypto;
protected final ReaderFactory readerFactory; protected final BdfReaderFactory bdfReaderFactory;
protected final WriterFactory writerFactory; protected final BdfWriterFactory bdfWriterFactory;
protected final StreamReaderFactory streamReaderFactory; protected final StreamReaderFactory streamReaderFactory;
protected final StreamWriterFactory streamWriterFactory; protected final StreamWriterFactory streamWriterFactory;
protected final AuthorFactory authorFactory; protected final AuthorFactory authorFactory;
@@ -83,7 +83,8 @@ abstract class Connector extends Thread {
private volatile ContactId contactId = null; private volatile ContactId contactId = null;
Connector(CryptoComponent crypto, Connector(CryptoComponent crypto,
ReaderFactory readerFactory, WriterFactory writerFactory, BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory, StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory, StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, GroupFactory groupFactory, AuthorFactory authorFactory, GroupFactory groupFactory,
@@ -96,8 +97,8 @@ abstract class Connector extends Thread {
PseudoRandom random) { PseudoRandom random) {
super("Connector"); super("Connector");
this.crypto = crypto; this.crypto = crypto;
this.readerFactory = readerFactory; this.bdfReaderFactory = bdfReaderFactory;
this.writerFactory = writerFactory; this.bdfWriterFactory = bdfWriterFactory;
this.streamReaderFactory = streamReaderFactory; this.streamReaderFactory = streamReaderFactory;
this.streamWriterFactory = streamWriterFactory; this.streamWriterFactory = streamWriterFactory;
this.authorFactory = authorFactory; this.authorFactory = authorFactory;
@@ -126,13 +127,13 @@ abstract class Connector extends Thread {
return plugin.createInvitationConnection(random, CONNECTION_TIMEOUT); return plugin.createInvitationConnection(random, CONNECTION_TIMEOUT);
} }
protected void sendPublicKeyHash(Writer w) throws IOException { protected void sendPublicKeyHash(BdfWriter w) throws IOException {
w.writeRaw(messageDigest.digest(keyPair.getPublic().getEncoded())); w.writeRaw(messageDigest.digest(keyPair.getPublic().getEncoded()));
w.flush(); w.flush();
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent hash"); if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent hash");
} }
protected byte[] receivePublicKeyHash(Reader r) throws IOException { protected byte[] receivePublicKeyHash(BdfReader r) throws IOException {
int hashLength = messageDigest.getDigestLength(); int hashLength = messageDigest.getDigestLength();
byte[] b = r.readRaw(hashLength); byte[] b = r.readRaw(hashLength);
if (b.length < hashLength) throw new FormatException(); if (b.length < hashLength) throw new FormatException();
@@ -140,15 +141,15 @@ abstract class Connector extends Thread {
return b; return b;
} }
protected void sendPublicKey(Writer w) throws IOException { protected void sendPublicKey(BdfWriter w) throws IOException {
byte[] key = keyPair.getPublic().getEncoded(); byte[] key = keyPair.getPublic().getEncoded();
w.writeRaw(key); w.writeRaw(key);
w.flush(); w.flush();
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent key"); if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent key");
} }
protected byte[] receivePublicKey(Reader r) throws GeneralSecurityException, protected byte[] receivePublicKey(BdfReader r)
IOException { throws GeneralSecurityException, IOException {
byte[] b = r.readRaw(MAX_PUBLIC_KEY_LENGTH); byte[] b = r.readRaw(MAX_PUBLIC_KEY_LENGTH);
keyParser.parsePublicKey(b); keyParser.parsePublicKey(b);
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " received key"); if (LOG.isLoggable(INFO)) LOG.info(pluginName + " received key");
@@ -169,7 +170,7 @@ abstract class Connector extends Thread {
return crypto.deriveMasterSecret(key, keyPair, alice); return crypto.deriveMasterSecret(key, keyPair, alice);
} }
protected void sendConfirmation(Writer w, boolean confirmed) protected void sendConfirmation(BdfWriter w, boolean confirmed)
throws IOException { throws IOException {
w.writeBoolean(confirmed); w.writeBoolean(confirmed);
w.flush(); w.flush();
@@ -177,14 +178,14 @@ abstract class Connector extends Thread {
LOG.info(pluginName + " sent confirmation: " + confirmed); LOG.info(pluginName + " sent confirmation: " + confirmed);
} }
protected boolean receiveConfirmation(Reader r) throws IOException { protected boolean receiveConfirmation(BdfReader r) throws IOException {
boolean confirmed = r.readBoolean(); boolean confirmed = r.readBoolean();
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info(pluginName + " received confirmation: " + confirmed); LOG.info(pluginName + " received confirmation: " + confirmed);
return confirmed; return confirmed;
} }
protected void sendPseudonym(Writer w, byte[] nonce) protected void sendPseudonym(BdfWriter w, byte[] nonce)
throws GeneralSecurityException, IOException { throws GeneralSecurityException, IOException {
// Sign the nonce // Sign the nonce
Signature signature = crypto.getSignature(); Signature signature = crypto.getSignature();
@@ -201,7 +202,7 @@ abstract class Connector extends Thread {
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent pseudonym"); if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent pseudonym");
} }
protected Author receivePseudonym(Reader r, byte[] nonce) protected Author receivePseudonym(BdfReader r, byte[] nonce)
throws GeneralSecurityException, IOException { throws GeneralSecurityException, IOException {
// Read the name, public key and signature // Read the name, public key and signature
String name = r.readString(MAX_AUTHOR_NAME_LENGTH); String name = r.readString(MAX_AUTHOR_NAME_LENGTH);
@@ -221,24 +222,26 @@ abstract class Connector extends Thread {
return authorFactory.createAuthor(name, publicKey); return authorFactory.createAuthor(name, publicKey);
} }
protected void sendTimestamp(Writer w, long timestamp) throws IOException { protected void sendTimestamp(BdfWriter w, long timestamp)
throws IOException {
w.writeInteger(timestamp); w.writeInteger(timestamp);
w.flush(); w.flush();
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent timestamp"); if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent timestamp");
} }
protected long receiveTimestamp(Reader r) throws IOException { protected long receiveTimestamp(BdfReader r) throws IOException {
long timestamp = r.readInteger(); long timestamp = r.readInteger();
if (timestamp < 0) throw new FormatException(); if (timestamp < 0) throw new FormatException();
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " received timestamp"); if (LOG.isLoggable(INFO)) LOG.info(pluginName + " received timestamp");
return timestamp; return timestamp;
} }
protected void sendTransportProperties(Writer w) throws IOException { protected void sendTransportProperties(BdfWriter w) throws IOException {
w.writeListStart(); w.writeListStart();
for (Entry<TransportId, TransportProperties> e : localProps.entrySet()) { for (Entry<TransportId, TransportProperties> e :
localProps.entrySet()) {
w.writeString(e.getKey().getString()); w.writeString(e.getKey().getString());
w.writeMap(e.getValue()); w.writeDictionary(e.getValue());
} }
w.writeListEnd(); w.writeListEnd();
w.flush(); w.flush();
@@ -247,7 +250,7 @@ abstract class Connector extends Thread {
} }
protected Map<TransportId, TransportProperties> receiveTransportProperties( protected Map<TransportId, TransportProperties> receiveTransportProperties(
Reader r) throws IOException { BdfReader r) throws IOException {
Map<TransportId, TransportProperties> remoteProps = Map<TransportId, TransportProperties> remoteProps =
new HashMap<TransportId, TransportProperties>(); new HashMap<TransportId, TransportProperties>();
r.readListStart(); r.readListStart();
@@ -256,15 +259,15 @@ abstract class Connector extends Thread {
if (idString.length() == 0) throw new FormatException(); if (idString.length() == 0) throw new FormatException();
TransportId id = new TransportId(idString); TransportId id = new TransportId(idString);
Map<String, String> p = new HashMap<String, String>(); Map<String, String> p = new HashMap<String, String>();
r.readMapStart(); r.readDictionaryStart();
for (int i = 0; !r.hasMapEnd(); i++) { for (int i = 0; !r.hasDictionaryEnd(); i++) {
if (i == MAX_PROPERTIES_PER_TRANSPORT) if (i == MAX_PROPERTIES_PER_TRANSPORT)
throw new FormatException(); throw new FormatException();
String key = r.readString(MAX_PROPERTY_LENGTH); String key = r.readString(MAX_PROPERTY_LENGTH);
String value = r.readString(MAX_PROPERTY_LENGTH); String value = r.readString(MAX_PROPERTY_LENGTH);
p.put(key, value); p.put(key, value);
} }
r.readMapEnd(); r.readDictionaryEnd();
remoteProps.put(id, new TransportProperties(p)); remoteProps.put(id, new TransportProperties(p));
} }
r.readListEnd(); r.readListEnd();

View File

@@ -5,8 +5,8 @@ import org.briarproject.api.TransportProperties;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.PseudoRandom; import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.data.ReaderFactory; import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.WriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.db.DbException; import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.AuthorFactory;
@@ -48,8 +48,8 @@ class ConnectorGroup extends Thread implements InvitationTask {
Logger.getLogger(ConnectorGroup.class.getName()); Logger.getLogger(ConnectorGroup.class.getName());
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final ReaderFactory readerFactory; private final BdfReaderFactory bdfReaderFactory;
private final WriterFactory writerFactory; private final BdfWriterFactory bdfWriterFactory;
private final StreamReaderFactory streamReaderFactory; private final StreamReaderFactory streamReaderFactory;
private final StreamWriterFactory streamWriterFactory; private final StreamWriterFactory streamWriterFactory;
private final AuthorFactory authorFactory; private final AuthorFactory authorFactory;
@@ -78,7 +78,8 @@ class ConnectorGroup extends Thread implements InvitationTask {
private String remoteName = null; private String remoteName = null;
ConnectorGroup(CryptoComponent crypto, ConnectorGroup(CryptoComponent crypto,
ReaderFactory readerFactory, WriterFactory writerFactory, BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory, StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory, StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, GroupFactory groupFactory, AuthorFactory authorFactory, GroupFactory groupFactory,
@@ -91,8 +92,8 @@ class ConnectorGroup extends Thread implements InvitationTask {
boolean reuseConnection) { boolean reuseConnection) {
super("ConnectorGroup"); super("ConnectorGroup");
this.crypto = crypto; this.crypto = crypto;
this.readerFactory = readerFactory; this.bdfReaderFactory = bdfReaderFactory;
this.writerFactory = writerFactory; this.bdfWriterFactory = bdfWriterFactory;
this.streamReaderFactory = streamReaderFactory; this.streamReaderFactory = streamReaderFactory;
this.streamWriterFactory = streamWriterFactory; this.streamWriterFactory = streamWriterFactory;
this.authorFactory = authorFactory; this.authorFactory = authorFactory;
@@ -197,7 +198,7 @@ class ConnectorGroup extends Thread implements InvitationTask {
Map<TransportId, TransportProperties> localProps) { Map<TransportId, TransportProperties> localProps) {
PseudoRandom random = crypto.getPseudoRandom(localInvitationCode, PseudoRandom random = crypto.getPseudoRandom(localInvitationCode,
remoteInvitationCode); remoteInvitationCode);
return new AliceConnector(crypto, readerFactory, writerFactory, return new AliceConnector(crypto, bdfReaderFactory, bdfWriterFactory,
streamReaderFactory, streamWriterFactory, authorFactory, streamReaderFactory, streamWriterFactory, authorFactory,
groupFactory, keyManager, connectionManager, contactManager, groupFactory, keyManager, connectionManager, contactManager,
messagingManager, transportPropertyManager, clock, messagingManager, transportPropertyManager, clock,
@@ -209,7 +210,7 @@ class ConnectorGroup extends Thread implements InvitationTask {
Map<TransportId, TransportProperties> localProps) { Map<TransportId, TransportProperties> localProps) {
PseudoRandom random = crypto.getPseudoRandom(remoteInvitationCode, PseudoRandom random = crypto.getPseudoRandom(remoteInvitationCode,
localInvitationCode); localInvitationCode);
return new BobConnector(crypto, readerFactory, writerFactory, return new BobConnector(crypto, bdfReaderFactory, bdfWriterFactory,
streamReaderFactory, streamWriterFactory, authorFactory, streamReaderFactory, streamWriterFactory, authorFactory,
groupFactory, keyManager, connectionManager, contactManager, groupFactory, keyManager, connectionManager, contactManager,
messagingManager, transportPropertyManager, clock, messagingManager, transportPropertyManager, clock,

View File

@@ -2,8 +2,8 @@ package org.briarproject.invitation;
import org.briarproject.api.contact.ContactManager; import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.data.ReaderFactory; import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.WriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.IdentityManager; import org.briarproject.api.identity.IdentityManager;
@@ -24,8 +24,8 @@ import javax.inject.Inject;
class InvitationTaskFactoryImpl implements InvitationTaskFactory { class InvitationTaskFactoryImpl implements InvitationTaskFactory {
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final ReaderFactory readerFactory; private final BdfReaderFactory bdfReaderFactory;
private final WriterFactory writerFactory; private final BdfWriterFactory bdfWriterFactory;
private final StreamReaderFactory streamReaderFactory; private final StreamReaderFactory streamReaderFactory;
private final StreamWriterFactory streamWriterFactory; private final StreamWriterFactory streamWriterFactory;
private final AuthorFactory authorFactory; private final AuthorFactory authorFactory;
@@ -41,7 +41,7 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
@Inject @Inject
InvitationTaskFactoryImpl(CryptoComponent crypto, InvitationTaskFactoryImpl(CryptoComponent crypto,
ReaderFactory readerFactory, WriterFactory writerFactory, BdfReaderFactory bdfReaderFactory, BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory, StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory, StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, GroupFactory groupFactory, AuthorFactory authorFactory, GroupFactory groupFactory,
@@ -51,8 +51,8 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
TransportPropertyManager transportPropertyManager, TransportPropertyManager transportPropertyManager,
Clock clock, PluginManager pluginManager) { Clock clock, PluginManager pluginManager) {
this.crypto = crypto; this.crypto = crypto;
this.readerFactory = readerFactory; this.bdfReaderFactory = bdfReaderFactory;
this.writerFactory = writerFactory; this.bdfWriterFactory = bdfWriterFactory;
this.streamReaderFactory = streamReaderFactory; this.streamReaderFactory = streamReaderFactory;
this.streamWriterFactory = streamWriterFactory; this.streamWriterFactory = streamWriterFactory;
this.authorFactory = authorFactory; this.authorFactory = authorFactory;
@@ -69,7 +69,7 @@ class InvitationTaskFactoryImpl implements InvitationTaskFactory {
public InvitationTask createTask(AuthorId localAuthorId, int localCode, public InvitationTask createTask(AuthorId localAuthorId, int localCode,
int remoteCode, boolean reuseConnection) { int remoteCode, boolean reuseConnection) {
return new ConnectorGroup(crypto, readerFactory, writerFactory, return new ConnectorGroup(crypto, bdfReaderFactory, bdfWriterFactory,
streamReaderFactory, streamWriterFactory, authorFactory, streamReaderFactory, streamWriterFactory, authorFactory,
groupFactory, keyManager, connectionManager, identityManager, groupFactory, keyManager, connectionManager, identityManager,
contactManager, messagingManager, transportPropertyManager, contactManager, messagingManager, transportPropertyManager,

View File

@@ -2,8 +2,8 @@ package org.briarproject.sync;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.MessageDigest; import org.briarproject.api.crypto.MessageDigest;
import org.briarproject.api.data.Writer; import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.WriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory; import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.AuthorId;
@@ -18,14 +18,14 @@ import javax.inject.Inject;
class AuthorFactoryImpl implements AuthorFactory { class AuthorFactoryImpl implements AuthorFactory {
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final WriterFactory writerFactory; private final BdfWriterFactory bdfWriterFactory;
private final Clock clock; private final Clock clock;
@Inject @Inject
AuthorFactoryImpl(CryptoComponent crypto, WriterFactory writerFactory, AuthorFactoryImpl(CryptoComponent crypto, BdfWriterFactory bdfWriterFactory,
Clock clock) { Clock clock) {
this.crypto = crypto; this.crypto = crypto;
this.writerFactory = writerFactory; this.bdfWriterFactory = bdfWriterFactory;
this.clock = clock; this.clock = clock;
} }
@@ -41,7 +41,7 @@ class AuthorFactoryImpl implements AuthorFactory {
private AuthorId getId(String name, byte[] publicKey) { private AuthorId getId(String name, byte[] publicKey) {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer w = writerFactory.createWriter(out); BdfWriter w = bdfWriterFactory.createWriter(out);
try { try {
w.writeListStart(); w.writeListStart();
w.writeString(name); w.writeString(name);

View File

@@ -3,8 +3,8 @@ package org.briarproject.sync;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.MessageDigest; import org.briarproject.api.crypto.MessageDigest;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.ObjectReader; import org.briarproject.api.data.ObjectReader;
import org.briarproject.api.data.Reader;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorId; import org.briarproject.api.identity.AuthorId;
@@ -21,7 +21,7 @@ class AuthorReader implements ObjectReader<Author> {
messageDigest = crypto.getMessageDigest(); messageDigest = crypto.getMessageDigest();
} }
public Author readObject(Reader r) throws IOException { public Author readObject(BdfReader r) throws IOException {
// Set up the reader // Set up the reader
DigestingConsumer digesting = new DigestingConsumer(messageDigest); DigestingConsumer digesting = new DigestingConsumer(messageDigest);
r.addConsumer(digesting); r.addConsumer(digesting);

View File

@@ -2,8 +2,8 @@ package org.briarproject.sync;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.MessageDigest; import org.briarproject.api.crypto.MessageDigest;
import org.briarproject.api.data.Writer; import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.WriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupFactory; import org.briarproject.api.sync.GroupFactory;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
@@ -18,12 +18,12 @@ import static org.briarproject.api.sync.MessagingConstants.GROUP_SALT_LENGTH;
class GroupFactoryImpl implements GroupFactory { class GroupFactoryImpl implements GroupFactory {
private final CryptoComponent crypto; private final CryptoComponent crypto;
private final WriterFactory writerFactory; private final BdfWriterFactory bdfWriterFactory;
@Inject @Inject
GroupFactoryImpl(CryptoComponent crypto, WriterFactory writerFactory) { GroupFactoryImpl(CryptoComponent crypto, BdfWriterFactory bdfWriterFactory) {
this.crypto = crypto; this.crypto = crypto;
this.writerFactory = writerFactory; this.bdfWriterFactory = bdfWriterFactory;
} }
public Group createGroup(String name) { public Group createGroup(String name) {
@@ -34,7 +34,7 @@ class GroupFactoryImpl implements GroupFactory {
public Group createGroup(String name, byte[] salt) { public Group createGroup(String name, byte[] salt) {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer w = writerFactory.createWriter(out); BdfWriter w = bdfWriterFactory.createWriter(out);
try { try {
w.writeListStart(); w.writeListStart();
w.writeString(name); w.writeString(name);

View File

@@ -3,8 +3,8 @@ package org.briarproject.sync;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.MessageDigest; import org.briarproject.api.crypto.MessageDigest;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.ObjectReader; import org.briarproject.api.data.ObjectReader;
import org.briarproject.api.data.Reader;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
@@ -21,7 +21,7 @@ class GroupReader implements ObjectReader<Group> {
messageDigest = crypto.getMessageDigest(); messageDigest = crypto.getMessageDigest();
} }
public Group readObject(Reader r) throws IOException { public Group readObject(BdfReader r) throws IOException {
DigestingConsumer digesting = new DigestingConsumer(messageDigest); DigestingConsumer digesting = new DigestingConsumer(messageDigest);
// Read and digest the data // Read and digest the data
r.addConsumer(digesting); r.addConsumer(digesting);

View File

@@ -4,9 +4,9 @@ import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.MessageDigest; import org.briarproject.api.crypto.MessageDigest;
import org.briarproject.api.crypto.PrivateKey; import org.briarproject.api.crypto.PrivateKey;
import org.briarproject.api.crypto.Signature; import org.briarproject.api.crypto.Signature;
import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.data.Consumer; import org.briarproject.api.data.Consumer;
import org.briarproject.api.data.Writer;
import org.briarproject.api.data.WriterFactory;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message; import org.briarproject.api.sync.Message;
@@ -32,14 +32,14 @@ class MessageFactoryImpl implements MessageFactory {
private final Signature signature; private final Signature signature;
private final SecureRandom random; private final SecureRandom random;
private final MessageDigest messageDigest; private final MessageDigest messageDigest;
private final WriterFactory writerFactory; private final BdfWriterFactory bdfWriterFactory;
@Inject @Inject
MessageFactoryImpl(CryptoComponent crypto, WriterFactory writerFactory) { MessageFactoryImpl(CryptoComponent crypto, BdfWriterFactory bdfWriterFactory) {
signature = crypto.getSignature(); signature = crypto.getSignature();
random = crypto.getSecureRandom(); random = crypto.getSecureRandom();
messageDigest = crypto.getMessageDigest(); messageDigest = crypto.getMessageDigest();
this.writerFactory = writerFactory; this.bdfWriterFactory = bdfWriterFactory;
} }
public Message createAnonymousMessage(MessageId parent, Group group, public Message createAnonymousMessage(MessageId parent, Group group,
@@ -69,7 +69,7 @@ class MessageFactoryImpl implements MessageFactory {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
// Serialise the message to a buffer // Serialise the message to a buffer
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer w = writerFactory.createWriter(out); BdfWriter w = bdfWriterFactory.createWriter(out);
// Initialise the consumers // Initialise the consumers
CountingConsumer counting = new CountingConsumer(MAX_PAYLOAD_LENGTH); CountingConsumer counting = new CountingConsumer(MAX_PAYLOAD_LENGTH);
w.addConsumer(counting); w.addConsumer(counting);
@@ -113,14 +113,14 @@ class MessageFactoryImpl implements MessageFactory {
timestamp, out.toByteArray(), bodyStart, body.length); timestamp, out.toByteArray(), bodyStart, body.length);
} }
private void writeGroup(Writer w, Group g) throws IOException { private void writeGroup(BdfWriter w, Group g) throws IOException {
w.writeListStart(); w.writeListStart();
w.writeString(g.getName()); w.writeString(g.getName());
w.writeRaw(g.getSalt()); w.writeRaw(g.getSalt());
w.writeListEnd(); w.writeListEnd();
} }
private void writeAuthor(Writer w, Author a) throws IOException { private void writeAuthor(BdfWriter w, Author a) throws IOException {
w.writeListStart(); w.writeListStart();
w.writeString(a.getName()); w.writeString(a.getName());
w.writeRaw(a.getPublicKey()); w.writeRaw(a.getPublicKey());

View File

@@ -2,8 +2,8 @@ package org.briarproject.sync;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.UniqueId; import org.briarproject.api.UniqueId;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.ObjectReader; import org.briarproject.api.data.ObjectReader;
import org.briarproject.api.data.Reader;
import org.briarproject.api.identity.Author; import org.briarproject.api.identity.Author;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
@@ -28,7 +28,7 @@ class MessageReader implements ObjectReader<UnverifiedMessage> {
this.authorReader = authorReader; this.authorReader = authorReader;
} }
public UnverifiedMessage readObject(Reader r) throws IOException { public UnverifiedMessage readObject(BdfReader r) throws IOException {
CopyingConsumer copying = new CopyingConsumer(); CopyingConsumer copying = new CopyingConsumer();
CountingConsumer counting = new CountingConsumer(MAX_PAYLOAD_LENGTH); CountingConsumer counting = new CountingConsumer(MAX_PAYLOAD_LENGTH);
r.addConsumer(copying); r.addConsumer(copying);

View File

@@ -1,7 +1,7 @@
package org.briarproject.sync; package org.briarproject.sync;
import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.ObjectReader; import org.briarproject.api.data.ObjectReader;
import org.briarproject.api.data.ReaderFactory;
import org.briarproject.api.sync.PacketReader; import org.briarproject.api.sync.PacketReader;
import org.briarproject.api.sync.PacketReaderFactory; import org.briarproject.api.sync.PacketReaderFactory;
import org.briarproject.api.sync.SubscriptionUpdate; import org.briarproject.api.sync.SubscriptionUpdate;
@@ -13,21 +13,21 @@ import javax.inject.Inject;
class PacketReaderFactoryImpl implements PacketReaderFactory { class PacketReaderFactoryImpl implements PacketReaderFactory {
private final ReaderFactory readerFactory; private final BdfReaderFactory bdfReaderFactory;
private final ObjectReader<UnverifiedMessage> messageReader; private final ObjectReader<UnverifiedMessage> messageReader;
private final ObjectReader<SubscriptionUpdate> subscriptionUpdateReader; private final ObjectReader<SubscriptionUpdate> subscriptionUpdateReader;
@Inject @Inject
PacketReaderFactoryImpl(ReaderFactory readerFactory, PacketReaderFactoryImpl(BdfReaderFactory bdfReaderFactory,
ObjectReader<UnverifiedMessage> messageReader, ObjectReader<UnverifiedMessage> messageReader,
ObjectReader<SubscriptionUpdate> subscriptionUpdateReader) { ObjectReader<SubscriptionUpdate> subscriptionUpdateReader) {
this.readerFactory = readerFactory; this.bdfReaderFactory = bdfReaderFactory;
this.messageReader = messageReader; this.messageReader = messageReader;
this.subscriptionUpdateReader = subscriptionUpdateReader; this.subscriptionUpdateReader = subscriptionUpdateReader;
} }
public PacketReader createPacketReader(InputStream in) { public PacketReader createPacketReader(InputStream in) {
return new PacketReaderImpl(readerFactory, messageReader, return new PacketReaderImpl(bdfReaderFactory, messageReader,
subscriptionUpdateReader, in); subscriptionUpdateReader, in);
} }
} }

View File

@@ -4,9 +4,9 @@ import org.briarproject.api.FormatException;
import org.briarproject.api.TransportId; import org.briarproject.api.TransportId;
import org.briarproject.api.TransportProperties; import org.briarproject.api.TransportProperties;
import org.briarproject.api.UniqueId; import org.briarproject.api.UniqueId;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.ObjectReader; import org.briarproject.api.data.ObjectReader;
import org.briarproject.api.data.Reader;
import org.briarproject.api.data.ReaderFactory;
import org.briarproject.api.sync.Ack; import org.briarproject.api.sync.Ack;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.Offer; import org.briarproject.api.sync.Offer;
@@ -48,7 +48,7 @@ class PacketReaderImpl implements PacketReader {
private enum State { BUFFER_EMPTY, BUFFER_FULL, EOF } private enum State { BUFFER_EMPTY, BUFFER_FULL, EOF }
private final ReaderFactory readerFactory; private final BdfReaderFactory bdfReaderFactory;
private final ObjectReader<UnverifiedMessage> messageReader; private final ObjectReader<UnverifiedMessage> messageReader;
private final ObjectReader<SubscriptionUpdate> subscriptionUpdateReader; private final ObjectReader<SubscriptionUpdate> subscriptionUpdateReader;
private final InputStream in; private final InputStream in;
@@ -57,11 +57,11 @@ class PacketReaderImpl implements PacketReader {
private State state = State.BUFFER_EMPTY; private State state = State.BUFFER_EMPTY;
private int payloadLength = 0; private int payloadLength = 0;
PacketReaderImpl(ReaderFactory readerFactory, PacketReaderImpl(BdfReaderFactory bdfReaderFactory,
ObjectReader<UnverifiedMessage> messageReader, ObjectReader<UnverifiedMessage> messageReader,
ObjectReader<SubscriptionUpdate> subscriptionUpdateReader, ObjectReader<SubscriptionUpdate> subscriptionUpdateReader,
InputStream in) { InputStream in) {
this.readerFactory = readerFactory; this.bdfReaderFactory = bdfReaderFactory;
this.messageReader = messageReader; this.messageReader = messageReader;
this.subscriptionUpdateReader = subscriptionUpdateReader; this.subscriptionUpdateReader = subscriptionUpdateReader;
this.in = in; this.in = in;
@@ -111,7 +111,7 @@ class PacketReaderImpl implements PacketReader {
if (!hasAck()) throw new FormatException(); if (!hasAck()) throw new FormatException();
// Set up the reader // Set up the reader
InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength); InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength);
Reader r = readerFactory.createReader(bais); BdfReader r = bdfReaderFactory.createReader(bais);
// Read the start of the payload // Read the start of the payload
r.readListStart(); r.readListStart();
// Read the message IDs // Read the message IDs
@@ -141,7 +141,7 @@ class PacketReaderImpl implements PacketReader {
if (!hasMessage()) throw new FormatException(); if (!hasMessage()) throw new FormatException();
// Set up the reader // Set up the reader
InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength); InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength);
Reader r = readerFactory.createReader(bais); BdfReader r = bdfReaderFactory.createReader(bais);
// Read and build the message // Read and build the message
UnverifiedMessage m = messageReader.readObject(r); UnverifiedMessage m = messageReader.readObject(r);
if (!r.eof()) throw new FormatException(); if (!r.eof()) throw new FormatException();
@@ -157,7 +157,7 @@ class PacketReaderImpl implements PacketReader {
if (!hasOffer()) throw new FormatException(); if (!hasOffer()) throw new FormatException();
// Set up the reader // Set up the reader
InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength); InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength);
Reader r = readerFactory.createReader(bais); BdfReader r = bdfReaderFactory.createReader(bais);
// Read the start of the payload // Read the start of the payload
r.readListStart(); r.readListStart();
// Read the message IDs // Read the message IDs
@@ -187,7 +187,7 @@ class PacketReaderImpl implements PacketReader {
if (!hasRequest()) throw new FormatException(); if (!hasRequest()) throw new FormatException();
// Set up the reader // Set up the reader
InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength); InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength);
Reader r = readerFactory.createReader(bais); BdfReader r = bdfReaderFactory.createReader(bais);
// Read the start of the payload // Read the start of the payload
r.readListStart(); r.readListStart();
// Read the message IDs // Read the message IDs
@@ -217,7 +217,7 @@ class PacketReaderImpl implements PacketReader {
if (!hasSubscriptionAck()) throw new FormatException(); if (!hasSubscriptionAck()) throw new FormatException();
// Set up the reader // Set up the reader
InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength); InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength);
Reader r = readerFactory.createReader(bais); BdfReader r = bdfReaderFactory.createReader(bais);
// Read the start of the payload // Read the start of the payload
r.readListStart(); r.readListStart();
// Read the version // Read the version
@@ -239,7 +239,7 @@ class PacketReaderImpl implements PacketReader {
if (!hasSubscriptionUpdate()) throw new FormatException(); if (!hasSubscriptionUpdate()) throw new FormatException();
// Set up the reader // Set up the reader
InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength); InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength);
Reader r = readerFactory.createReader(bais); BdfReader r = bdfReaderFactory.createReader(bais);
// Read and build the subscription update // Read and build the subscription update
SubscriptionUpdate u = subscriptionUpdateReader.readObject(r); SubscriptionUpdate u = subscriptionUpdateReader.readObject(r);
if (!r.eof()) throw new FormatException(); if (!r.eof()) throw new FormatException();
@@ -255,7 +255,7 @@ class PacketReaderImpl implements PacketReader {
if (!hasTransportAck()) throw new FormatException(); if (!hasTransportAck()) throw new FormatException();
// Set up the reader // Set up the reader
InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength); InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength);
Reader r = readerFactory.createReader(bais); BdfReader r = bdfReaderFactory.createReader(bais);
// Read the start of the payload // Read the start of the payload
r.readListStart(); r.readListStart();
// Read the transport ID and version // Read the transport ID and version
@@ -280,7 +280,7 @@ class PacketReaderImpl implements PacketReader {
if (!hasTransportUpdate()) throw new FormatException(); if (!hasTransportUpdate()) throw new FormatException();
// Set up the reader // Set up the reader
InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength); InputStream bais = new ByteArrayInputStream(payload, 0, payloadLength);
Reader r = readerFactory.createReader(bais); BdfReader r = bdfReaderFactory.createReader(bais);
// Read the start of the payload // Read the start of the payload
r.readListStart(); r.readListStart();
// Read the transport ID // Read the transport ID
@@ -289,15 +289,15 @@ class PacketReaderImpl implements PacketReader {
TransportId id = new TransportId(idString); TransportId id = new TransportId(idString);
// Read the transport properties // Read the transport properties
Map<String, String> p = new HashMap<String, String>(); Map<String, String> p = new HashMap<String, String>();
r.readMapStart(); r.readDictionaryStart();
for (int i = 0; !r.hasMapEnd(); i++) { for (int i = 0; !r.hasDictionaryEnd(); i++) {
if (i == MAX_PROPERTIES_PER_TRANSPORT) if (i == MAX_PROPERTIES_PER_TRANSPORT)
throw new FormatException(); throw new FormatException();
String key = r.readString(MAX_PROPERTY_LENGTH); String key = r.readString(MAX_PROPERTY_LENGTH);
String value = r.readString(MAX_PROPERTY_LENGTH); String value = r.readString(MAX_PROPERTY_LENGTH);
p.put(key, value); p.put(key, value);
} }
r.readMapEnd(); r.readDictionaryEnd();
// Read the version number // Read the version number
long version = r.readInteger(); long version = r.readInteger();
if (version < 0) throw new FormatException(); if (version < 0) throw new FormatException();

View File

@@ -1,6 +1,6 @@
package org.briarproject.sync; package org.briarproject.sync;
import org.briarproject.api.data.WriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.sync.PacketWriter; import org.briarproject.api.sync.PacketWriter;
import org.briarproject.api.sync.PacketWriterFactory; import org.briarproject.api.sync.PacketWriterFactory;
@@ -10,14 +10,14 @@ import javax.inject.Inject;
class PacketWriterFactoryImpl implements PacketWriterFactory { class PacketWriterFactoryImpl implements PacketWriterFactory {
private final WriterFactory writerFactory; private final BdfWriterFactory bdfWriterFactory;
@Inject @Inject
PacketWriterFactoryImpl(WriterFactory writerFactory) { PacketWriterFactoryImpl(BdfWriterFactory bdfWriterFactory) {
this.writerFactory = writerFactory; this.bdfWriterFactory = bdfWriterFactory;
} }
public PacketWriter createPacketWriter(OutputStream out) { public PacketWriter createPacketWriter(OutputStream out) {
return new PacketWriterImpl(writerFactory, out); return new PacketWriterImpl(bdfWriterFactory, out);
} }
} }

View File

@@ -1,7 +1,7 @@
package org.briarproject.sync; package org.briarproject.sync;
import org.briarproject.api.data.Writer; import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.WriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.sync.Ack; import org.briarproject.api.sync.Ack;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.MessageId; import org.briarproject.api.sync.MessageId;
@@ -36,13 +36,13 @@ import static org.briarproject.api.sync.PacketTypes.TRANSPORT_UPDATE;
// This class is not thread-safe // This class is not thread-safe
class PacketWriterImpl implements PacketWriter { class PacketWriterImpl implements PacketWriter {
private final WriterFactory writerFactory; private final BdfWriterFactory bdfWriterFactory;
private final OutputStream out; private final OutputStream out;
private final byte[] header; private final byte[] header;
private final ByteArrayOutputStream payload; private final ByteArrayOutputStream payload;
PacketWriterImpl(WriterFactory writerFactory, OutputStream out) { PacketWriterImpl(BdfWriterFactory bdfWriterFactory, OutputStream out) {
this.writerFactory = writerFactory; this.bdfWriterFactory = bdfWriterFactory;
this.out = out; this.out = out;
header = new byte[HEADER_LENGTH]; header = new byte[HEADER_LENGTH];
header[0] = PROTOCOL_VERSION; header[0] = PROTOCOL_VERSION;
@@ -78,7 +78,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeAck(Ack a) throws IOException { public void writeAck(Ack a) throws IOException {
assert payload.size() == 0; assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload); BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart(); w.writeListStart();
w.writeListStart(); w.writeListStart();
for (MessageId m : a.getMessageIds()) w.writeRaw(m.getBytes()); for (MessageId m : a.getMessageIds()) w.writeRaw(m.getBytes());
@@ -96,7 +96,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeOffer(Offer o) throws IOException { public void writeOffer(Offer o) throws IOException {
assert payload.size() == 0; assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload); BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart(); w.writeListStart();
w.writeListStart(); w.writeListStart();
for (MessageId m : o.getMessageIds()) w.writeRaw(m.getBytes()); for (MessageId m : o.getMessageIds()) w.writeRaw(m.getBytes());
@@ -107,7 +107,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeRequest(Request r) throws IOException { public void writeRequest(Request r) throws IOException {
assert payload.size() == 0; assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload); BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart(); w.writeListStart();
w.writeListStart(); w.writeListStart();
for (MessageId m : r.getMessageIds()) w.writeRaw(m.getBytes()); for (MessageId m : r.getMessageIds()) w.writeRaw(m.getBytes());
@@ -118,7 +118,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeSubscriptionAck(SubscriptionAck a) throws IOException { public void writeSubscriptionAck(SubscriptionAck a) throws IOException {
assert payload.size() == 0; assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload); BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart(); w.writeListStart();
w.writeInteger(a.getVersion()); w.writeInteger(a.getVersion());
w.writeListEnd(); w.writeListEnd();
@@ -128,7 +128,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeSubscriptionUpdate(SubscriptionUpdate u) public void writeSubscriptionUpdate(SubscriptionUpdate u)
throws IOException { throws IOException {
assert payload.size() == 0; assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload); BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart(); w.writeListStart();
w.writeListStart(); w.writeListStart();
for (Group g : u.getGroups()) { for (Group g : u.getGroups()) {
@@ -145,7 +145,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeTransportAck(TransportAck a) throws IOException { public void writeTransportAck(TransportAck a) throws IOException {
assert payload.size() == 0; assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload); BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart(); w.writeListStart();
w.writeString(a.getId().getString()); w.writeString(a.getId().getString());
w.writeInteger(a.getVersion()); w.writeInteger(a.getVersion());
@@ -155,10 +155,10 @@ class PacketWriterImpl implements PacketWriter {
public void writeTransportUpdate(TransportUpdate u) throws IOException { public void writeTransportUpdate(TransportUpdate u) throws IOException {
assert payload.size() == 0; assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload); BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart(); w.writeListStart();
w.writeString(u.getId().getString()); w.writeString(u.getId().getString());
w.writeMap(u.getProperties()); w.writeDictionary(u.getProperties());
w.writeInteger(u.getVersion()); w.writeInteger(u.getVersion());
w.writeListEnd(); w.writeListEnd();
writePacket(TRANSPORT_UPDATE); writePacket(TRANSPORT_UPDATE);

View File

@@ -1,9 +1,9 @@
package org.briarproject.sync; package org.briarproject.sync;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.Consumer; import org.briarproject.api.data.Consumer;
import org.briarproject.api.data.ObjectReader; import org.briarproject.api.data.ObjectReader;
import org.briarproject.api.data.Reader;
import org.briarproject.api.sync.Group; import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.SubscriptionUpdate; import org.briarproject.api.sync.SubscriptionUpdate;
@@ -26,7 +26,7 @@ class SubscriptionUpdateReader implements ObjectReader<SubscriptionUpdate> {
this.groupReader = groupReader; this.groupReader = groupReader;
} }
public SubscriptionUpdate readObject(Reader r) throws IOException { public SubscriptionUpdate readObject(BdfReader r) throws IOException {
// Set up the reader // Set up the reader
Consumer counting = new CountingConsumer(MAX_PAYLOAD_LENGTH); Consumer counting = new CountingConsumer(MAX_PAYLOAD_LENGTH);
r.addConsumer(counting); r.addConsumer(counting);

View File

@@ -39,6 +39,14 @@ public class StringUtils {
} }
} }
public static String fromUtf8(byte[] bytes, int off, int len) {
try {
return new String(bytes, off, len, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
/** Converts the given byte array to a hex character array. */ /** Converts the given byte array to a hex character array. */
public static char[] toHexChars(byte[] bytes) { public static char[] toHexChars(byte[] bytes) {
char[] hex = new char[bytes.length * 2]; char[] hex = new char[bytes.length * 2];

View File

@@ -105,8 +105,10 @@
<test name='org.briarproject.crypto.StreamDecrypterImplTest'/> <test name='org.briarproject.crypto.StreamDecrypterImplTest'/>
<test name='org.briarproject.crypto.StreamEncrypterImplTest'/> <test name='org.briarproject.crypto.StreamEncrypterImplTest'/>
<test name='org.briarproject.crypto.XSalsa20Poly1305AuthenticatedCipherTest'/> <test name='org.briarproject.crypto.XSalsa20Poly1305AuthenticatedCipherTest'/>
<test name='org.briarproject.data.ReaderImplTest'/> <test name='org.briarproject.data.BdfReaderImplTest'/>
<test name='org.briarproject.data.WriterImplTest'/> <test name='org.briarproject.data.BdfWriterImplTest'/>
<test name='org.briarproject.data.MetadataEncoderImplTest'/>
<test name='org.briarproject.data.MetadataParserImplTest'/>
<test name='org.briarproject.db.BasicH2Test'/> <test name='org.briarproject.db.BasicH2Test'/>
<test name='org.briarproject.db.DatabaseComponentImplTest'/> <test name='org.briarproject.db.DatabaseComponentImplTest'/>
<test name='org.briarproject.db.ExponentialBackoffTest'/> <test name='org.briarproject.db.ExponentialBackoffTest'/>

View File

@@ -14,10 +14,9 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
public class ReaderImplTest extends BriarTestCase { public class BdfReaderImplTest extends BriarTestCase {
private ByteArrayInputStream in = null; private BdfReaderImpl r = null;
private ReaderImpl r = null;
@Test @Test
public void testReadEmptyInput() throws Exception { public void testReadEmptyInput() throws Exception {
@@ -127,49 +126,6 @@ public class ReaderImplTest extends BriarTestCase {
assertTrue(r.eof()); assertTrue(r.eof());
} }
@Test
public void testIntegersMustHaveMinimalLength() throws Exception {
// INTEGER_16 could be encoded as INTEGER_8
setContents("21" + "7F" + "22" + "007F");
assertEquals(Byte.MAX_VALUE, r.readInteger());
try {
r.readInteger();
fail();
} catch (FormatException expected) {}
setContents("21" + "80" + "22" + "FF80");
assertEquals(Byte.MIN_VALUE, r.readInteger());
try {
r.readInteger();
fail();
} catch (FormatException expected) {}
// INTEGER_32 could be encoded as INTEGER_16
setContents("22" + "7FFF" + "24" + "00007FFF");
assertEquals(Short.MAX_VALUE, r.readInteger());
try {
r.readInteger();
fail();
} catch (FormatException expected) {}
setContents("22" + "8000" + "24" + "FFFF8000");
assertEquals(Short.MIN_VALUE, r.readInteger());
try {
r.readInteger();
fail();
} catch (FormatException expected) {}
// INTEGER_64 could be encoded as INTEGER_32
setContents("24" + "7FFFFFFF" + "28" + "000000007FFFFFFF");
assertEquals(Integer.MAX_VALUE, r.readInteger());
try {
r.readInteger();
fail();
} catch (FormatException expected) {}
setContents("24" + "80000000" + "28" + "FFFFFFFF80000000");
assertEquals(Integer.MIN_VALUE, r.readInteger());
try {
r.readInteger();
fail();
} catch (FormatException expected) {}
}
@Test @Test
public void testReadFloat() throws Exception { public void testReadFloat() throws Exception {
// http://babbage.cs.qc.edu/IEEE-754/Decimal.html // http://babbage.cs.qc.edu/IEEE-754/Decimal.html
@@ -218,7 +174,9 @@ public class ReaderImplTest extends BriarTestCase {
try { try {
r.readString(2); r.readString(2);
fail(); fail();
} catch (FormatException expected) {} } catch (FormatException expected) {
// Expected
}
} }
@Test @Test
@@ -258,7 +216,9 @@ public class ReaderImplTest extends BriarTestCase {
try { try {
r.readString(Byte.MAX_VALUE); r.readString(Byte.MAX_VALUE);
fail(); fail();
} catch (FormatException expected) {} } catch (FormatException expected) {
// Expected
}
} }
@Test @Test
@@ -296,7 +256,9 @@ public class ReaderImplTest extends BriarTestCase {
try { try {
r.readString(Short.MAX_VALUE); r.readString(Short.MAX_VALUE);
fail(); fail();
} catch (FormatException expected) {} } catch (FormatException expected) {
// Expected
}
} }
@Test @Test
@@ -311,28 +273,6 @@ public class ReaderImplTest extends BriarTestCase {
assertTrue(r.eof()); assertTrue(r.eof());
} }
@Test
public void testStringsMustHaveMinimalLength() throws Exception {
// STRING_16 could be encoded as STRING_8
String longest8 = TestUtils.createRandomString(Byte.MAX_VALUE);
String long8Hex = StringUtils.toHexString(longest8.getBytes("UTF-8"));
setContents("41" + "7F" + long8Hex + "42" + "007F" + long8Hex);
assertEquals(longest8, r.readString(Integer.MAX_VALUE));
try {
r.readString(Integer.MAX_VALUE);
fail();
} catch (FormatException expected) {}
// STRING_32 could be encoded as STRING_16
String longest16 = TestUtils.createRandomString(Short.MAX_VALUE);
String long16Hex = StringUtils.toHexString(longest16.getBytes("UTF-8"));
setContents("42" + "7FFF" + long16Hex + "44" + "00007FFF" + long16Hex);
assertEquals(longest16, r.readString(Integer.MAX_VALUE));
try {
r.readString(Integer.MAX_VALUE);
fail();
} catch (FormatException expected) {}
}
@Test @Test
public void testReadRaw8() throws Exception { public void testReadRaw8() throws Exception {
byte[] longest = new byte[Byte.MAX_VALUE]; byte[] longest = new byte[Byte.MAX_VALUE];
@@ -355,7 +295,9 @@ public class ReaderImplTest extends BriarTestCase {
try { try {
r.readRaw(2); r.readRaw(2);
fail(); fail();
} catch (FormatException expected) {} } catch (FormatException expected) {
// Expected
}
} }
@Test @Test
@@ -395,7 +337,9 @@ public class ReaderImplTest extends BriarTestCase {
try { try {
r.readRaw(Byte.MAX_VALUE); r.readRaw(Byte.MAX_VALUE);
fail(); fail();
} catch (FormatException expected) {} } catch (FormatException expected) {
// Expected
}
} }
@Test @Test
@@ -433,7 +377,9 @@ public class ReaderImplTest extends BriarTestCase {
try { try {
r.readRaw(Short.MAX_VALUE); r.readRaw(Short.MAX_VALUE);
fail(); fail();
} catch (FormatException expected) {} } catch (FormatException expected) {
// Expected
}
} }
@Test @Test
@@ -448,28 +394,6 @@ public class ReaderImplTest extends BriarTestCase {
assertTrue(r.eof()); assertTrue(r.eof());
} }
@Test
public void testRawMustHaveMinimalLength() throws Exception {
// RAW_16 could be encoded as RAW_8
byte[] longest8 = new byte[Byte.MAX_VALUE];
String long8Hex = StringUtils.toHexString(longest8);
setContents("51" + "7F" + long8Hex + "52" + "007F" + long8Hex);
assertArrayEquals(longest8, r.readRaw(Integer.MAX_VALUE));
try {
r.readRaw(Integer.MAX_VALUE);
fail();
} catch (FormatException expected) {}
// RAW_32 could be encoded as RAW_16
byte[] longest16 = new byte[Short.MAX_VALUE];
String long16Hex = StringUtils.toHexString(longest16);
setContents("52" + "7FFF" + long16Hex + "54" + "00007FFF" + long16Hex);
assertArrayEquals(longest16, r.readRaw(Integer.MAX_VALUE));
try {
r.readRaw(Integer.MAX_VALUE);
fail();
} catch (FormatException expected) {}
}
@Test @Test
public void testReadList() throws Exception { public void testReadList() throws Exception {
// A list containing 1, "foo", and 128 // A list containing 1, "foo", and 128
@@ -499,44 +423,45 @@ public class ReaderImplTest extends BriarTestCase {
} }
@Test @Test
public void testReadMap() throws Exception { public void testReadDictionary() throws Exception {
// A map containing "foo" -> 123 and "bar" -> null // A dictionary containing "foo" -> 123 and "bar" -> null
setContents("70" + "41" + "03" + "666F6F" + "21" + "7B" + setContents("70" + "41" + "03" + "666F6F" + "21" + "7B" +
"41" + "03" + "626172" + "00" + "80"); "41" + "03" + "626172" + "00" + "80");
r.readMapStart(); r.readDictionaryStart();
assertFalse(r.hasMapEnd()); assertFalse(r.hasDictionaryEnd());
assertEquals("foo", r.readString(1000)); assertEquals("foo", r.readString(1000));
assertFalse(r.hasMapEnd()); assertFalse(r.hasDictionaryEnd());
assertEquals(123, r.readInteger()); assertEquals(123, r.readInteger());
assertFalse(r.hasMapEnd()); assertFalse(r.hasDictionaryEnd());
assertEquals("bar", r.readString(1000)); assertEquals("bar", r.readString(1000));
assertFalse(r.hasMapEnd()); assertFalse(r.hasDictionaryEnd());
assertTrue(r.hasNull()); assertTrue(r.hasNull());
r.readNull(); r.readNull();
assertTrue(r.hasMapEnd()); assertTrue(r.hasDictionaryEnd());
r.readMapEnd(); r.readDictionaryEnd();
assertTrue(r.eof()); assertTrue(r.eof());
} }
@Test @Test
public void testSkipMap() throws Exception { public void testSkipDictionary() throws Exception {
// A map containing "foo" -> 123 and "bar" -> null // A map containing "foo" -> 123 and "bar" -> null
setContents("70" + "41" + "03" + "666F6F" + "21" + "7B" + setContents("70" + "41" + "03" + "666F6F" + "21" + "7B" +
"41" + "03" + "626172" + "00" + "80"); "41" + "03" + "626172" + "00" + "80");
r.skipMap(); r.skipDictionary();
assertTrue(r.eof()); assertTrue(r.eof());
} }
@Test @Test
public void testSkipNestedListsAndMaps() throws Exception { public void testSkipNestedListsAndDictionaries() throws Exception {
// A list containing a map containing two empty lists // A list containing a dictionary containing "" -> an empty list
setContents("60" + "70" + "60" + "80" + "60" + "80" + "80" + "80"); setContents("60" + "70" + "4100" + "60" + "80" + "80" + "80");
r.skipList(); r.skipList();
assertTrue(r.eof()); assertTrue(r.eof());
} }
private void setContents(String hex) { private void setContents(String hex) {
in = new ByteArrayInputStream(StringUtils.fromHexString(hex)); ByteArrayInputStream in = new ByteArrayInputStream(
r = new ReaderImpl(in); StringUtils.fromHexString(hex));
r = new BdfReaderImpl(in);
} }
} }

View File

@@ -16,15 +16,15 @@ import java.util.Map;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
public class WriterImplTest extends BriarTestCase { public class BdfWriterImplTest extends BriarTestCase {
private ByteArrayOutputStream out = null; private ByteArrayOutputStream out = null;
private WriterImpl w = null; private BdfWriterImpl w = null;
@Before @Before
public void setUp() { public void setUp() {
out = new ByteArrayOutputStream(); out = new ByteArrayOutputStream();
w = new WriterImpl(out); w = new BdfWriterImpl(out);
} }
@Test @Test
@@ -165,12 +165,12 @@ public class WriterImplTest extends BriarTestCase {
} }
@Test @Test
public void testWriteMap() throws IOException { public void testWriteDictionary() throws IOException {
// Use LinkedHashMap to get predictable iteration order // Use LinkedHashMap to get predictable iteration order
Map<String, Object> m = new LinkedHashMap<String, Object>(); Map<String, Object> m = new LinkedHashMap<String, Object>();
for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i); for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i);
w.writeMap(m); w.writeDictionary(m);
// MAP tag, keys as strings and values as integers, END tag // DICTIONARY tag, keys as strings and values as integers, END tag
checkContents("70" + "41" + "01" + "30" + "21" + "00" + checkContents("70" + "41" + "01" + "30" + "21" + "00" +
"41" + "01" + "31" + "21" + "01" + "41" + "01" + "31" + "21" + "01" +
"41" + "01" + "32" + "21" + "02" + "41" + "01" + "32" + "21" + "02" +
@@ -191,21 +191,21 @@ public class WriterImplTest extends BriarTestCase {
} }
@Test @Test
public void testWriteDelimitedMap() throws IOException { public void testWriteDelimitedDictionary() throws IOException {
w.writeMapStart(); w.writeDictionaryStart();
w.writeString("foo"); w.writeString("foo");
w.writeInteger(123); w.writeInteger(123);
w.writeString("bar"); w.writeString("bar");
w.writeNull(); w.writeNull();
w.writeMapEnd(); w.writeDictionaryEnd();
// MAP tag, "foo" as string, 123 as integer, "bar" as string, // DICTIONARY tag, "foo" as string, 123 as integer, "bar" as string,
// NULL tag, END tag // NULL tag, END tag
checkContents("70" + "41" + "03" + "666F6F" + checkContents("70" + "41" + "03" + "666F6F" +
"21" + "7B" + "41" + "03" + "626172" + "00" + "80"); "21" + "7B" + "41" + "03" + "626172" + "00" + "80");
} }
@Test @Test
public void testWriteNestedMapsAndLists() throws IOException { public void testWriteNestedDictionariesAndLists() throws IOException {
Map<String, Object> inner = new LinkedHashMap<String, Object>(); Map<String, Object> inner = new LinkedHashMap<String, Object>();
inner.put("bar", new byte[0]); inner.put("bar", new byte[0]);
List<Object> list = new ArrayList<Object>(); List<Object> list = new ArrayList<Object>();
@@ -213,9 +213,9 @@ public class WriterImplTest extends BriarTestCase {
list.add(inner); list.add(inner);
Map<String, Object> outer = new LinkedHashMap<String, Object>(); Map<String, Object> outer = new LinkedHashMap<String, Object>();
outer.put("foo", list); outer.put("foo", list);
w.writeMap(outer); w.writeDictionary(outer);
// MAP tag, "foo" as string, LIST tag, 1 as integer, MAP tag, // DICTIONARY tag, "foo" as string, LIST tag, 1 as integer,
// "bar" as string, {} as raw, END tag, END tag, END tag // DICTIONARY tag, "bar" as string, {} as raw, END tag, END tag, END tag
checkContents("70" + "41" + "03" + "666F6F" + "60" + checkContents("70" + "41" + "03" + "666F6F" + "60" +
"21" + "01" + "70" + "41" + "03" + "626172" + "51" + "00" + "21" + "01" + "70" + "41" + "03" + "626172" + "51" + "00" +
"80" + "80" + "80"); "80" + "80" + "80");

View File

@@ -0,0 +1,14 @@
package org.briarproject.data;
import org.briarproject.BriarTestCase;
import org.junit.Test;
import static org.junit.Assert.fail;
public class MetadataEncoderImplTest extends BriarTestCase {
@Test
public void testUnitTestsExist() {
fail(); // FIXME: Write tests
}
}

View File

@@ -0,0 +1,14 @@
package org.briarproject.data;
import org.briarproject.BriarTestCase;
import org.junit.Test;
import static org.junit.Assert.fail;
public class MetadataParserImplTest extends BriarTestCase {
@Test
public void testUnitTestsExist() {
fail(); // FIXME: Write tests
}
}

View File

@@ -23,8 +23,7 @@ public class ConsumersTest extends BriarTestCase {
messageDigest.update(data); messageDigest.update(data);
byte[] dig = messageDigest.digest(); byte[] dig = messageDigest.digest();
// Check that feeding a DigestingConsumer generates the same digest // Check that feeding a DigestingConsumer generates the same digest
org.briarproject.sync.DigestingConsumer DigestingConsumer dc = new DigestingConsumer(messageDigest);
dc = new org.briarproject.sync.DigestingConsumer(messageDigest);
dc.write(data[0]); dc.write(data[0]);
dc.write(data, 1, data.length - 2); dc.write(data, 1, data.length - 2);
dc.write(data[data.length - 1]); dc.write(data[data.length - 1]);
@@ -35,8 +34,7 @@ public class ConsumersTest extends BriarTestCase {
@Test @Test
public void testCountingConsumer() throws Exception { public void testCountingConsumer() throws Exception {
byte[] data = new byte[1234]; byte[] data = new byte[1234];
org.briarproject.sync.CountingConsumer CountingConsumer cc = new CountingConsumer(data.length);
cc = new org.briarproject.sync.CountingConsumer(data.length);
cc.write(data[0]); cc.write(data[0]);
cc.write(data, 1, data.length - 2); cc.write(data, 1, data.length - 2);
cc.write(data[data.length - 1]); cc.write(data[data.length - 1]);
@@ -54,8 +52,7 @@ public class ConsumersTest extends BriarTestCase {
byte[] data = new byte[1234]; byte[] data = new byte[1234];
new Random().nextBytes(data); new Random().nextBytes(data);
// Check that a CopyingConsumer creates a faithful copy // Check that a CopyingConsumer creates a faithful copy
org.briarproject.sync.CopyingConsumer CopyingConsumer cc = new CopyingConsumer();
cc = new org.briarproject.sync.CopyingConsumer();
cc.write(data[0]); cc.write(data[0]);
cc.write(data, 1, data.length - 2); cc.write(data, 1, data.length - 2);
cc.write(data[data.length - 1]); cc.write(data[data.length - 1]);

View File

@@ -6,9 +6,9 @@ import com.google.inject.Injector;
import org.briarproject.BriarTestCase; import org.briarproject.BriarTestCase;
import org.briarproject.TestUtils; import org.briarproject.TestUtils;
import org.briarproject.api.FormatException; import org.briarproject.api.FormatException;
import org.briarproject.api.data.ReaderFactory; import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.Writer; import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.WriterFactory; import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.data.DataModule; import org.briarproject.data.DataModule;
import org.briarproject.util.ByteUtils; import org.briarproject.util.ByteUtils;
import org.junit.Test; import org.junit.Test;
@@ -30,21 +30,20 @@ public class PacketReaderImplTest extends BriarTestCase {
// FIXME: This is an integration test, not a unit test // FIXME: This is an integration test, not a unit test
private final ReaderFactory readerFactory; private final BdfReaderFactory bdfReaderFactory;
private final WriterFactory writerFactory; private final BdfWriterFactory bdfWriterFactory;
public PacketReaderImplTest() throws Exception { public PacketReaderImplTest() throws Exception {
Injector i = Guice.createInjector(new DataModule()); Injector i = Guice.createInjector(new DataModule());
readerFactory = i.getInstance(ReaderFactory.class); bdfReaderFactory = i.getInstance(BdfReaderFactory.class);
writerFactory = i.getInstance(WriterFactory.class); bdfWriterFactory = i.getInstance(BdfWriterFactory.class);
} }
@Test @Test
public void testFormatExceptionIfAckIsTooLarge() throws Exception { public void testFormatExceptionIfAckIsTooLarge() throws Exception {
byte[] b = createAck(true); byte[] b = createAck(true);
ByteArrayInputStream in = new ByteArrayInputStream(b); ByteArrayInputStream in = new ByteArrayInputStream(b);
org.briarproject.sync.PacketReaderImpl PacketReaderImpl reader = new PacketReaderImpl(bdfReaderFactory, null,
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
null, in); null, in);
try { try {
reader.readAck(); reader.readAck();
@@ -58,8 +57,7 @@ public class PacketReaderImplTest extends BriarTestCase {
public void testNoFormatExceptionIfAckIsMaximumSize() throws Exception { public void testNoFormatExceptionIfAckIsMaximumSize() throws Exception {
byte[] b = createAck(false); byte[] b = createAck(false);
ByteArrayInputStream in = new ByteArrayInputStream(b); ByteArrayInputStream in = new ByteArrayInputStream(b);
org.briarproject.sync.PacketReaderImpl PacketReaderImpl reader = new PacketReaderImpl(bdfReaderFactory, null,
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
null, in); null, in);
reader.readAck(); reader.readAck();
} }
@@ -68,8 +66,7 @@ public class PacketReaderImplTest extends BriarTestCase {
public void testEmptyAck() throws Exception { public void testEmptyAck() throws Exception {
byte[] b = createEmptyAck(); byte[] b = createEmptyAck();
ByteArrayInputStream in = new ByteArrayInputStream(b); ByteArrayInputStream in = new ByteArrayInputStream(b);
org.briarproject.sync.PacketReaderImpl PacketReaderImpl reader = new PacketReaderImpl(bdfReaderFactory, null,
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
null, in); null, in);
try { try {
reader.readAck(); reader.readAck();
@@ -83,8 +80,7 @@ public class PacketReaderImplTest extends BriarTestCase {
public void testFormatExceptionIfOfferIsTooLarge() throws Exception { public void testFormatExceptionIfOfferIsTooLarge() throws Exception {
byte[] b = createOffer(true); byte[] b = createOffer(true);
ByteArrayInputStream in = new ByteArrayInputStream(b); ByteArrayInputStream in = new ByteArrayInputStream(b);
org.briarproject.sync.PacketReaderImpl PacketReaderImpl reader = new PacketReaderImpl(bdfReaderFactory, null,
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
null, in); null, in);
try { try {
reader.readOffer(); reader.readOffer();
@@ -98,8 +94,9 @@ public class PacketReaderImplTest extends BriarTestCase {
public void testNoFormatExceptionIfOfferIsMaximumSize() throws Exception { public void testNoFormatExceptionIfOfferIsMaximumSize() throws Exception {
byte[] b = createOffer(false); byte[] b = createOffer(false);
ByteArrayInputStream in = new ByteArrayInputStream(b); ByteArrayInputStream in = new ByteArrayInputStream(b);
org.briarproject.sync.PacketReaderImpl PacketReaderImpl
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null, reader = new PacketReaderImpl(
bdfReaderFactory, null,
null, in); null, in);
reader.readOffer(); reader.readOffer();
} }
@@ -108,8 +105,7 @@ public class PacketReaderImplTest extends BriarTestCase {
public void testEmptyOffer() throws Exception { public void testEmptyOffer() throws Exception {
byte[] b = createEmptyOffer(); byte[] b = createEmptyOffer();
ByteArrayInputStream in = new ByteArrayInputStream(b); ByteArrayInputStream in = new ByteArrayInputStream(b);
org.briarproject.sync.PacketReaderImpl PacketReaderImpl reader = new PacketReaderImpl(bdfReaderFactory, null,
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
null, in); null, in);
try { try {
reader.readOffer(); reader.readOffer();
@@ -123,8 +119,7 @@ public class PacketReaderImplTest extends BriarTestCase {
public void testFormatExceptionIfRequestIsTooLarge() throws Exception { public void testFormatExceptionIfRequestIsTooLarge() throws Exception {
byte[] b = createRequest(true); byte[] b = createRequest(true);
ByteArrayInputStream in = new ByteArrayInputStream(b); ByteArrayInputStream in = new ByteArrayInputStream(b);
org.briarproject.sync.PacketReaderImpl PacketReaderImpl reader = new PacketReaderImpl(bdfReaderFactory, null,
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
null, in); null, in);
try { try {
reader.readRequest(); reader.readRequest();
@@ -138,8 +133,7 @@ public class PacketReaderImplTest extends BriarTestCase {
public void testNoFormatExceptionIfRequestIsMaximumSize() throws Exception { public void testNoFormatExceptionIfRequestIsMaximumSize() throws Exception {
byte[] b = createRequest(false); byte[] b = createRequest(false);
ByteArrayInputStream in = new ByteArrayInputStream(b); ByteArrayInputStream in = new ByteArrayInputStream(b);
org.briarproject.sync.PacketReaderImpl PacketReaderImpl reader = new PacketReaderImpl(bdfReaderFactory, null,
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
null, in); null, in);
reader.readRequest(); reader.readRequest();
} }
@@ -148,8 +142,7 @@ public class PacketReaderImplTest extends BriarTestCase {
public void testEmptyRequest() throws Exception { public void testEmptyRequest() throws Exception {
byte[] b = createEmptyRequest(); byte[] b = createEmptyRequest();
ByteArrayInputStream in = new ByteArrayInputStream(b); ByteArrayInputStream in = new ByteArrayInputStream(b);
org.briarproject.sync.PacketReaderImpl PacketReaderImpl reader = new PacketReaderImpl(bdfReaderFactory, null,
reader = new org.briarproject.sync.PacketReaderImpl(readerFactory, null,
null, in); null, in);
try { try {
reader.readRequest(); reader.readRequest();
@@ -162,7 +155,7 @@ public class PacketReaderImplTest extends BriarTestCase {
private byte[] createAck(boolean tooBig) throws Exception { private byte[] createAck(boolean tooBig) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(new byte[HEADER_LENGTH]); out.write(new byte[HEADER_LENGTH]);
Writer w = writerFactory.createWriter(out); BdfWriter w = bdfWriterFactory.createWriter(out);
w.writeListStart(); w.writeListStart();
w.writeListStart(); w.writeListStart();
while (out.size() + UNIQUE_ID_LENGTH + LIST_END_LENGTH * 2 while (out.size() + UNIQUE_ID_LENGTH + LIST_END_LENGTH * 2
@@ -182,7 +175,7 @@ public class PacketReaderImplTest extends BriarTestCase {
private byte[] createEmptyAck() throws Exception { private byte[] createEmptyAck() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(new byte[HEADER_LENGTH]); out.write(new byte[HEADER_LENGTH]);
Writer w = writerFactory.createWriter(out); BdfWriter w = bdfWriterFactory.createWriter(out);
w.writeListStart(); w.writeListStart();
w.writeListStart(); w.writeListStart();
w.writeListEnd(); w.writeListEnd();
@@ -196,7 +189,7 @@ public class PacketReaderImplTest extends BriarTestCase {
private byte[] createOffer(boolean tooBig) throws Exception { private byte[] createOffer(boolean tooBig) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(new byte[HEADER_LENGTH]); out.write(new byte[HEADER_LENGTH]);
Writer w = writerFactory.createWriter(out); BdfWriter w = bdfWriterFactory.createWriter(out);
w.writeListStart(); w.writeListStart();
w.writeListStart(); w.writeListStart();
while (out.size() + UNIQUE_ID_LENGTH + LIST_END_LENGTH * 2 while (out.size() + UNIQUE_ID_LENGTH + LIST_END_LENGTH * 2
@@ -216,7 +209,7 @@ public class PacketReaderImplTest extends BriarTestCase {
private byte[] createEmptyOffer() throws Exception { private byte[] createEmptyOffer() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(new byte[HEADER_LENGTH]); out.write(new byte[HEADER_LENGTH]);
Writer w = writerFactory.createWriter(out); BdfWriter w = bdfWriterFactory.createWriter(out);
w.writeListStart(); w.writeListStart();
w.writeListStart(); w.writeListStart();
w.writeListEnd(); w.writeListEnd();
@@ -230,7 +223,7 @@ public class PacketReaderImplTest extends BriarTestCase {
private byte[] createRequest(boolean tooBig) throws Exception { private byte[] createRequest(boolean tooBig) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(new byte[HEADER_LENGTH]); out.write(new byte[HEADER_LENGTH]);
Writer w = writerFactory.createWriter(out); BdfWriter w = bdfWriterFactory.createWriter(out);
w.writeListStart(); w.writeListStart();
w.writeListStart(); w.writeListStart();
while (out.size() + UNIQUE_ID_LENGTH + LIST_END_LENGTH * 2 while (out.size() + UNIQUE_ID_LENGTH + LIST_END_LENGTH * 2
@@ -250,7 +243,7 @@ public class PacketReaderImplTest extends BriarTestCase {
private byte[] createEmptyRequest() throws Exception { private byte[] createEmptyRequest() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write(new byte[HEADER_LENGTH]); out.write(new byte[HEADER_LENGTH]);
Writer w = writerFactory.createWriter(out); BdfWriter w = bdfWriterFactory.createWriter(out);
w.writeListStart(); w.writeListStart();
w.writeListStart(); w.writeListStart();
w.writeListEnd(); w.writeListEnd();

View File

@@ -46,8 +46,7 @@ public class SimplexOutgoingSessionTest extends BriarTestCase {
@Test @Test
public void testNothingToSend() throws Exception { public void testNothingToSend() throws Exception {
final org.briarproject.sync.SimplexOutgoingSession final SimplexOutgoingSession session = new SimplexOutgoingSession(db,
session = new org.briarproject.sync.SimplexOutgoingSession(db,
dbExecutor, eventBus, contactId, transportId, maxLatency, dbExecutor, eventBus, contactId, transportId, maxLatency,
packetWriter); packetWriter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -87,8 +86,7 @@ public class SimplexOutgoingSessionTest extends BriarTestCase {
public void testSomethingToSend() throws Exception { public void testSomethingToSend() throws Exception {
final Ack ack = new Ack(Collections.singletonList(messageId)); final Ack ack = new Ack(Collections.singletonList(messageId));
final byte[] raw = new byte[1234]; final byte[] raw = new byte[1234];
final org.briarproject.sync.SimplexOutgoingSession final SimplexOutgoingSession session = new SimplexOutgoingSession(db,
session = new org.briarproject.sync.SimplexOutgoingSession(db,
dbExecutor, eventBus, contactId, transportId, maxLatency, dbExecutor, eventBus, contactId, transportId, maxLatency,
packetWriter); packetWriter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{