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;
public interface Reader {
public interface BdfReader {
boolean eof() throws IOException;
void close() throws IOException;
@@ -40,9 +40,9 @@ public interface Reader {
void readListEnd() throws IOException;
void skipList() throws IOException;
boolean hasMap() throws IOException;
void readMapStart() throws IOException;
boolean hasMapEnd() throws IOException;
void readMapEnd() throws IOException;
void skipMap() throws IOException;
boolean hasDictionary() throws IOException;
void readDictionaryStart() throws IOException;
boolean hasDictionaryEnd() throws IOException;
void readDictionaryEnd() 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.Map;
public interface Writer {
public interface BdfWriter {
void flush() throws IOException;
void close() throws IOException;
@@ -23,7 +23,7 @@ public interface Writer {
void writeListStart() throws IOException;
void writeListEnd() throws IOException;
void writeMap(Map<?, ?> m) throws IOException;
void writeMapStart() throws IOException;
void writeMapEnd() throws IOException;
void writeDictionary(Map<?, ?> m) throws IOException;
void writeDictionaryStart() 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> {
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;
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.FALSE;
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_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;
@@ -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.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
class ReaderImpl implements Reader {
class BdfReaderImpl implements BdfReader {
private static final byte[] EMPTY_BUFFER = new byte[] {};
@@ -39,7 +39,7 @@ class ReaderImpl implements Reader {
private byte next;
private byte[] buf = new byte[8];
ReaderImpl(InputStream in) {
BdfReaderImpl(InputStream in) {
this.in = in;
}
@@ -88,14 +88,14 @@ class ReaderImpl implements Reader {
}
private void skipObject() throws IOException {
if (hasBoolean()) skipBoolean();
if (hasNull()) skipNull();
else if (hasBoolean()) skipBoolean();
else if (hasInteger()) skipInteger();
else if (hasFloat()) skipFloat();
else if (hasString()) skipString();
else if (hasRaw()) skipRaw();
else if (hasList()) skipList();
else if (hasMap()) skipMap();
else if (hasNull()) skipNull();
else if (hasDictionary()) skipDictionary();
else throw new FormatException();
}
@@ -173,18 +173,13 @@ class ReaderImpl implements Reader {
private short readInt16(boolean consume) throws IOException {
readIntoBuffer(2, consume);
short value = (short) (((buf[0] & 0xFF) << 8) + (buf[1] & 0xFF));
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
throw new FormatException();
return value;
return (short) (((buf[0] & 0xFF) << 8) + (buf[1] & 0xFF));
}
private int readInt32(boolean consume) throws IOException {
readIntoBuffer(4, consume);
int value = 0;
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;
}
@@ -192,8 +187,6 @@ class ReaderImpl implements Reader {
readIntoBuffer(8, consume);
long value = 0;
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;
}
@@ -327,30 +320,30 @@ class ReaderImpl implements Reader {
hasLookahead = false;
}
public boolean hasMap() throws IOException {
public boolean hasDictionary() throws IOException {
if (!hasLookahead) readLookahead();
if (eof) return false;
return next == MAP;
return next == DICTIONARY;
}
public void readMapStart() throws IOException {
if (!hasMap()) throw new FormatException();
public void readDictionaryStart() throws IOException {
if (!hasDictionary()) throw new FormatException();
consumeLookahead();
}
public boolean hasMapEnd() throws IOException {
public boolean hasDictionaryEnd() throws IOException {
return hasEnd();
}
public void readMapEnd() throws IOException {
public void readDictionaryEnd() throws IOException {
readEnd();
}
public void skipMap() throws IOException {
if (!hasMap()) throw new FormatException();
public void skipDictionary() throws IOException {
if (!hasDictionary()) throw new FormatException();
hasLookahead = false;
while (!hasMapEnd()) {
skipObject();
while (!hasDictionaryEnd()) {
skipString();
skipObject();
}
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;
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.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 org.briarproject.api.Bytes;
import org.briarproject.api.FormatException;
import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.Consumer;
import java.io.IOException;
import java.io.OutputStream;
@@ -26,17 +13,31 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.briarproject.api.Bytes;
import org.briarproject.api.data.Consumer;
import org.briarproject.api.data.Writer;
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;
// This class is not thread-safe
class WriterImpl implements Writer {
class BdfWriterImpl implements BdfWriter {
private final OutputStream out;
private final Collection<Consumer> consumers = new ArrayList<Consumer>(0);
WriterImpl(OutputStream out) {
BdfWriterImpl(OutputStream out) {
this.out = out;
}
@@ -145,7 +146,8 @@ class WriterImpl implements Writer {
}
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 Short) writeInteger((Short) 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 byte[]) writeRaw((byte[]) o);
else if (o instanceof Bytes) writeRaw(((Bytes) o).getBytes());
else if (o instanceof List<?>) writeList((List<?>) o);
else if (o instanceof Map<?, ?>) writeMap((Map<?, ?>) o);
else if (o == null) writeNull();
else throw new IllegalStateException();
else if (o instanceof List) writeList((List) o);
else if (o instanceof Map) writeDictionary((Map) o);
else throw new FormatException();
}
public void writeListStart() throws IOException {
@@ -169,20 +170,21 @@ class WriterImpl implements Writer {
write(END);
}
public void writeMap(Map<?, ?> m) throws IOException {
write(MAP);
public void writeDictionary(Map<?, ?> m) throws IOException {
write(DICTIONARY);
for (Entry<?, ?> e : m.entrySet()) {
writeObject(e.getKey());
if (!(e.getKey() instanceof String)) throw new FormatException();
writeString((String) e.getKey());
writeObject(e.getValue());
}
write(END);
}
public void writeMapStart() throws IOException {
write(MAP);
public void writeDictionaryStart() throws IOException {
write(DICTIONARY);
}
public void writeMapEnd() throws IOException {
public void writeDictionaryEnd() throws IOException {
write(END);
}

View File

@@ -1,15 +1,19 @@
package org.briarproject.data;
import org.briarproject.api.data.ReaderFactory;
import org.briarproject.api.data.WriterFactory;
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 {
@Override
protected void configure() {
bind(ReaderFactory.class).to(ReaderFactoryImpl.class);
bind(WriterFactory.class).to(WriterFactoryImpl.class);
bind(BdfReaderFactory.class).to(BdfReaderFactoryImpl.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_32 = 0x54;
byte LIST = 0x60;
byte MAP = 0x70;
byte DICTIONARY = 0x70;
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.PseudoRandom;
import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.data.Reader;
import org.briarproject.api.data.ReaderFactory;
import org.briarproject.api.data.Writer;
import org.briarproject.api.data.WriterFactory;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
@@ -42,7 +42,8 @@ class AliceConnector extends Connector {
Logger.getLogger(AliceConnector.class.getName());
AliceConnector(CryptoComponent crypto,
ReaderFactory readerFactory, WriterFactory writerFactory,
BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, GroupFactory groupFactory,
@@ -53,7 +54,7 @@ class AliceConnector extends Connector {
LocalAuthor localAuthor,
Map<TransportId, TransportProperties> localProps,
PseudoRandom random) {
super(crypto, readerFactory, writerFactory, streamReaderFactory,
super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory,
streamWriterFactory, authorFactory, groupFactory,
keyManager, connectionManager, contactManager,
messagingManager, transportPropertyManager, clock,
@@ -76,14 +77,14 @@ class AliceConnector extends Connector {
// Carry out the key agreement protocol
InputStream in;
OutputStream out;
Reader r;
Writer w;
BdfReader r;
BdfWriter w;
SecretKey master;
try {
in = conn.getReader().getInputStream();
out = conn.getWriter().getOutputStream();
r = readerFactory.createReader(in);
w = writerFactory.createWriter(out);
r = bdfReaderFactory.createReader(in);
w = bdfWriterFactory.createWriter(out);
// Alice goes first
sendPublicKeyHash(w);
byte[] hash = receivePublicKeyHash(r);
@@ -144,12 +145,12 @@ class AliceConnector extends Connector {
InputStream streamReader =
streamReaderFactory.createInvitationStreamReader(in,
bobHeaderKey);
r = readerFactory.createReader(streamReader);
r = bdfReaderFactory.createReader(streamReader);
// Create the writers
OutputStream streamWriter =
streamWriterFactory.createInvitationStreamWriter(out,
aliceHeaderKey);
w = writerFactory.createWriter(streamWriter);
w = bdfWriterFactory.createWriter(streamWriter);
// Derive the invitation nonces
byte[] aliceNonce = crypto.deriveSignatureNonce(master, true);
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.PseudoRandom;
import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.data.Reader;
import org.briarproject.api.data.ReaderFactory;
import org.briarproject.api.data.Writer;
import org.briarproject.api.data.WriterFactory;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
@@ -42,7 +42,8 @@ class BobConnector extends Connector {
Logger.getLogger(BobConnector.class.getName());
BobConnector(CryptoComponent crypto,
ReaderFactory readerFactory, WriterFactory writerFactory,
BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, GroupFactory groupFactory,
@@ -53,7 +54,7 @@ class BobConnector extends Connector {
LocalAuthor localAuthor,
Map<TransportId, TransportProperties> localProps,
PseudoRandom random) {
super(crypto, readerFactory, writerFactory, streamReaderFactory,
super(crypto, bdfReaderFactory, bdfWriterFactory, streamReaderFactory,
streamWriterFactory, authorFactory, groupFactory,
keyManager, connectionManager, contactManager,
messagingManager, transportPropertyManager, clock,
@@ -70,14 +71,14 @@ class BobConnector extends Connector {
// Carry out the key agreement protocol
InputStream in;
OutputStream out;
Reader r;
Writer w;
BdfReader r;
BdfWriter w;
SecretKey master;
try {
in = conn.getReader().getInputStream();
out = conn.getWriter().getOutputStream();
r = readerFactory.createReader(in);
w = writerFactory.createWriter(out);
r = bdfReaderFactory.createReader(in);
w = bdfWriterFactory.createWriter(out);
// Alice goes first
byte[] hash = receivePublicKeyHash(r);
// Don't proceed with more than one connection
@@ -144,12 +145,12 @@ class BobConnector extends Connector {
InputStream streamReader =
streamReaderFactory.createInvitationStreamReader(in,
aliceHeaderKey);
r = readerFactory.createReader(streamReader);
r = bdfReaderFactory.createReader(streamReader);
// Create the writers
OutputStream streamWriter =
streamWriterFactory.createInvitationStreamWriter(out,
bobHeaderKey);
w = writerFactory.createWriter(streamWriter);
w = bdfWriterFactory.createWriter(streamWriter);
// Derive the nonces
byte[] aliceNonce = crypto.deriveSignatureNonce(master, true);
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.SecretKey;
import org.briarproject.api.crypto.Signature;
import org.briarproject.api.data.Reader;
import org.briarproject.api.data.ReaderFactory;
import org.briarproject.api.data.Writer;
import org.briarproject.api.data.WriterFactory;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.BdfReaderFactory;
import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
@@ -56,8 +56,8 @@ abstract class Connector extends Thread {
Logger.getLogger(Connector.class.getName());
protected final CryptoComponent crypto;
protected final ReaderFactory readerFactory;
protected final WriterFactory writerFactory;
protected final BdfReaderFactory bdfReaderFactory;
protected final BdfWriterFactory bdfWriterFactory;
protected final StreamReaderFactory streamReaderFactory;
protected final StreamWriterFactory streamWriterFactory;
protected final AuthorFactory authorFactory;
@@ -83,7 +83,8 @@ abstract class Connector extends Thread {
private volatile ContactId contactId = null;
Connector(CryptoComponent crypto,
ReaderFactory readerFactory, WriterFactory writerFactory,
BdfReaderFactory bdfReaderFactory,
BdfWriterFactory bdfWriterFactory,
StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory,
AuthorFactory authorFactory, GroupFactory groupFactory,
@@ -96,8 +97,8 @@ abstract class Connector extends Thread {
PseudoRandom random) {
super("Connector");
this.crypto = crypto;
this.readerFactory = readerFactory;
this.writerFactory = writerFactory;
this.bdfReaderFactory = bdfReaderFactory;
this.bdfWriterFactory = bdfWriterFactory;
this.streamReaderFactory = streamReaderFactory;
this.streamWriterFactory = streamWriterFactory;
this.authorFactory = authorFactory;
@@ -126,13 +127,13 @@ abstract class Connector extends Thread {
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.flush();
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();
byte[] b = r.readRaw(hashLength);
if (b.length < hashLength) throw new FormatException();
@@ -140,15 +141,15 @@ abstract class Connector extends Thread {
return b;
}
protected void sendPublicKey(Writer w) throws IOException {
protected void sendPublicKey(BdfWriter w) throws IOException {
byte[] key = keyPair.getPublic().getEncoded();
w.writeRaw(key);
w.flush();
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " sent key");
}
protected byte[] receivePublicKey(Reader r) throws GeneralSecurityException,
IOException {
protected byte[] receivePublicKey(BdfReader r)
throws GeneralSecurityException, IOException {
byte[] b = r.readRaw(MAX_PUBLIC_KEY_LENGTH);
keyParser.parsePublicKey(b);
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " received key");
@@ -169,7 +170,7 @@ abstract class Connector extends Thread {
return crypto.deriveMasterSecret(key, keyPair, alice);
}
protected void sendConfirmation(Writer w, boolean confirmed)
protected void sendConfirmation(BdfWriter w, boolean confirmed)
throws IOException {
w.writeBoolean(confirmed);
w.flush();
@@ -177,14 +178,14 @@ abstract class Connector extends Thread {
LOG.info(pluginName + " sent confirmation: " + confirmed);
}
protected boolean receiveConfirmation(Reader r) throws IOException {
protected boolean receiveConfirmation(BdfReader r) throws IOException {
boolean confirmed = r.readBoolean();
if (LOG.isLoggable(INFO))
LOG.info(pluginName + " received confirmation: " + confirmed);
return confirmed;
}
protected void sendPseudonym(Writer w, byte[] nonce)
protected void sendPseudonym(BdfWriter w, byte[] nonce)
throws GeneralSecurityException, IOException {
// Sign the nonce
Signature signature = crypto.getSignature();
@@ -201,7 +202,7 @@ abstract class Connector extends Thread {
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 {
// Read the name, public key and signature
String name = r.readString(MAX_AUTHOR_NAME_LENGTH);
@@ -221,24 +222,26 @@ abstract class Connector extends Thread {
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.flush();
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();
if (timestamp < 0) throw new FormatException();
if (LOG.isLoggable(INFO)) LOG.info(pluginName + " received timestamp");
return timestamp;
}
protected void sendTransportProperties(Writer w) throws IOException {
protected void sendTransportProperties(BdfWriter w) throws IOException {
w.writeListStart();
for (Entry<TransportId, TransportProperties> e : localProps.entrySet()) {
for (Entry<TransportId, TransportProperties> e :
localProps.entrySet()) {
w.writeString(e.getKey().getString());
w.writeMap(e.getValue());
w.writeDictionary(e.getValue());
}
w.writeListEnd();
w.flush();
@@ -247,7 +250,7 @@ abstract class Connector extends Thread {
}
protected Map<TransportId, TransportProperties> receiveTransportProperties(
Reader r) throws IOException {
BdfReader r) throws IOException {
Map<TransportId, TransportProperties> remoteProps =
new HashMap<TransportId, TransportProperties>();
r.readListStart();
@@ -256,15 +259,15 @@ abstract class Connector extends Thread {
if (idString.length() == 0) throw new FormatException();
TransportId id = new TransportId(idString);
Map<String, String> p = new HashMap<String, String>();
r.readMapStart();
for (int i = 0; !r.hasMapEnd(); i++) {
r.readDictionaryStart();
for (int i = 0; !r.hasDictionaryEnd(); i++) {
if (i == MAX_PROPERTIES_PER_TRANSPORT)
throw new FormatException();
String key = r.readString(MAX_PROPERTY_LENGTH);
String value = r.readString(MAX_PROPERTY_LENGTH);
p.put(key, value);
}
r.readMapEnd();
r.readDictionaryEnd();
remoteProps.put(id, new TransportProperties(p));
}
r.readListEnd();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,8 +3,8 @@ package org.briarproject.sync;
import org.briarproject.api.FormatException;
import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.MessageDigest;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.ObjectReader;
import org.briarproject.api.data.Reader;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
@@ -21,7 +21,7 @@ class GroupReader implements ObjectReader<Group> {
messageDigest = crypto.getMessageDigest();
}
public Group readObject(Reader r) throws IOException {
public Group readObject(BdfReader r) throws IOException {
DigestingConsumer digesting = new DigestingConsumer(messageDigest);
// Read and digest the data
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.PrivateKey;
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.Writer;
import org.briarproject.api.data.WriterFactory;
import org.briarproject.api.identity.Author;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Message;
@@ -32,14 +32,14 @@ class MessageFactoryImpl implements MessageFactory {
private final Signature signature;
private final SecureRandom random;
private final MessageDigest messageDigest;
private final WriterFactory writerFactory;
private final BdfWriterFactory bdfWriterFactory;
@Inject
MessageFactoryImpl(CryptoComponent crypto, WriterFactory writerFactory) {
MessageFactoryImpl(CryptoComponent crypto, BdfWriterFactory bdfWriterFactory) {
signature = crypto.getSignature();
random = crypto.getSecureRandom();
messageDigest = crypto.getMessageDigest();
this.writerFactory = writerFactory;
this.bdfWriterFactory = bdfWriterFactory;
}
public Message createAnonymousMessage(MessageId parent, Group group,
@@ -69,7 +69,7 @@ class MessageFactoryImpl implements MessageFactory {
throw new IllegalArgumentException();
// Serialise the message to a buffer
ByteArrayOutputStream out = new ByteArrayOutputStream();
Writer w = writerFactory.createWriter(out);
BdfWriter w = bdfWriterFactory.createWriter(out);
// Initialise the consumers
CountingConsumer counting = new CountingConsumer(MAX_PAYLOAD_LENGTH);
w.addConsumer(counting);
@@ -113,14 +113,14 @@ class MessageFactoryImpl implements MessageFactory {
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.writeString(g.getName());
w.writeRaw(g.getSalt());
w.writeListEnd();
}
private void writeAuthor(Writer w, Author a) throws IOException {
private void writeAuthor(BdfWriter w, Author a) throws IOException {
w.writeListStart();
w.writeString(a.getName());
w.writeRaw(a.getPublicKey());

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
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.PacketWriterFactory;
@@ -10,14 +10,14 @@ import javax.inject.Inject;
class PacketWriterFactoryImpl implements PacketWriterFactory {
private final WriterFactory writerFactory;
private final BdfWriterFactory bdfWriterFactory;
@Inject
PacketWriterFactoryImpl(WriterFactory writerFactory) {
this.writerFactory = writerFactory;
PacketWriterFactoryImpl(BdfWriterFactory bdfWriterFactory) {
this.bdfWriterFactory = bdfWriterFactory;
}
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;
import org.briarproject.api.data.Writer;
import org.briarproject.api.data.WriterFactory;
import org.briarproject.api.data.BdfWriter;
import org.briarproject.api.data.BdfWriterFactory;
import org.briarproject.api.sync.Ack;
import org.briarproject.api.sync.Group;
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
class PacketWriterImpl implements PacketWriter {
private final WriterFactory writerFactory;
private final BdfWriterFactory bdfWriterFactory;
private final OutputStream out;
private final byte[] header;
private final ByteArrayOutputStream payload;
PacketWriterImpl(WriterFactory writerFactory, OutputStream out) {
this.writerFactory = writerFactory;
PacketWriterImpl(BdfWriterFactory bdfWriterFactory, OutputStream out) {
this.bdfWriterFactory = bdfWriterFactory;
this.out = out;
header = new byte[HEADER_LENGTH];
header[0] = PROTOCOL_VERSION;
@@ -78,7 +78,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeAck(Ack a) throws IOException {
assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload);
BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart();
w.writeListStart();
for (MessageId m : a.getMessageIds()) w.writeRaw(m.getBytes());
@@ -96,7 +96,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeOffer(Offer o) throws IOException {
assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload);
BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart();
w.writeListStart();
for (MessageId m : o.getMessageIds()) w.writeRaw(m.getBytes());
@@ -107,7 +107,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeRequest(Request r) throws IOException {
assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload);
BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart();
w.writeListStart();
for (MessageId m : r.getMessageIds()) w.writeRaw(m.getBytes());
@@ -118,7 +118,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeSubscriptionAck(SubscriptionAck a) throws IOException {
assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload);
BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart();
w.writeInteger(a.getVersion());
w.writeListEnd();
@@ -128,7 +128,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeSubscriptionUpdate(SubscriptionUpdate u)
throws IOException {
assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload);
BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart();
w.writeListStart();
for (Group g : u.getGroups()) {
@@ -145,7 +145,7 @@ class PacketWriterImpl implements PacketWriter {
public void writeTransportAck(TransportAck a) throws IOException {
assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload);
BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart();
w.writeString(a.getId().getString());
w.writeInteger(a.getVersion());
@@ -155,10 +155,10 @@ class PacketWriterImpl implements PacketWriter {
public void writeTransportUpdate(TransportUpdate u) throws IOException {
assert payload.size() == 0;
Writer w = writerFactory.createWriter(payload);
BdfWriter w = bdfWriterFactory.createWriter(payload);
w.writeListStart();
w.writeString(u.getId().getString());
w.writeMap(u.getProperties());
w.writeDictionary(u.getProperties());
w.writeInteger(u.getVersion());
w.writeListEnd();
writePacket(TRANSPORT_UPDATE);

View File

@@ -1,9 +1,9 @@
package org.briarproject.sync;
import org.briarproject.api.FormatException;
import org.briarproject.api.data.BdfReader;
import org.briarproject.api.data.Consumer;
import org.briarproject.api.data.ObjectReader;
import org.briarproject.api.data.Reader;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.SubscriptionUpdate;
@@ -26,7 +26,7 @@ class SubscriptionUpdateReader implements ObjectReader<SubscriptionUpdate> {
this.groupReader = groupReader;
}
public SubscriptionUpdate readObject(Reader r) throws IOException {
public SubscriptionUpdate readObject(BdfReader r) throws IOException {
// Set up the reader
Consumer counting = new CountingConsumer(MAX_PAYLOAD_LENGTH);
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. */
public static char[] toHexChars(byte[] bytes) {
char[] hex = new char[bytes.length * 2];

View File

@@ -105,8 +105,10 @@
<test name='org.briarproject.crypto.StreamDecrypterImplTest'/>
<test name='org.briarproject.crypto.StreamEncrypterImplTest'/>
<test name='org.briarproject.crypto.XSalsa20Poly1305AuthenticatedCipherTest'/>
<test name='org.briarproject.data.ReaderImplTest'/>
<test name='org.briarproject.data.WriterImplTest'/>
<test name='org.briarproject.data.BdfReaderImplTest'/>
<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.DatabaseComponentImplTest'/>
<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.fail;
public class ReaderImplTest extends BriarTestCase {
public class BdfReaderImplTest extends BriarTestCase {
private ByteArrayInputStream in = null;
private ReaderImpl r = null;
private BdfReaderImpl r = null;
@Test
public void testReadEmptyInput() throws Exception {
@@ -127,49 +126,6 @@ public class ReaderImplTest extends BriarTestCase {
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
public void testReadFloat() throws Exception {
// http://babbage.cs.qc.edu/IEEE-754/Decimal.html
@@ -218,7 +174,9 @@ public class ReaderImplTest extends BriarTestCase {
try {
r.readString(2);
fail();
} catch (FormatException expected) {}
} catch (FormatException expected) {
// Expected
}
}
@Test
@@ -258,7 +216,9 @@ public class ReaderImplTest extends BriarTestCase {
try {
r.readString(Byte.MAX_VALUE);
fail();
} catch (FormatException expected) {}
} catch (FormatException expected) {
// Expected
}
}
@Test
@@ -296,7 +256,9 @@ public class ReaderImplTest extends BriarTestCase {
try {
r.readString(Short.MAX_VALUE);
fail();
} catch (FormatException expected) {}
} catch (FormatException expected) {
// Expected
}
}
@Test
@@ -311,28 +273,6 @@ public class ReaderImplTest extends BriarTestCase {
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
public void testReadRaw8() throws Exception {
byte[] longest = new byte[Byte.MAX_VALUE];
@@ -355,7 +295,9 @@ public class ReaderImplTest extends BriarTestCase {
try {
r.readRaw(2);
fail();
} catch (FormatException expected) {}
} catch (FormatException expected) {
// Expected
}
}
@Test
@@ -395,7 +337,9 @@ public class ReaderImplTest extends BriarTestCase {
try {
r.readRaw(Byte.MAX_VALUE);
fail();
} catch (FormatException expected) {}
} catch (FormatException expected) {
// Expected
}
}
@Test
@@ -433,7 +377,9 @@ public class ReaderImplTest extends BriarTestCase {
try {
r.readRaw(Short.MAX_VALUE);
fail();
} catch (FormatException expected) {}
} catch (FormatException expected) {
// Expected
}
}
@Test
@@ -448,28 +394,6 @@ public class ReaderImplTest extends BriarTestCase {
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
public void testReadList() throws Exception {
// A list containing 1, "foo", and 128
@@ -499,44 +423,45 @@ public class ReaderImplTest extends BriarTestCase {
}
@Test
public void testReadMap() throws Exception {
// A map containing "foo" -> 123 and "bar" -> null
public void testReadDictionary() throws Exception {
// A dictionary containing "foo" -> 123 and "bar" -> null
setContents("70" + "41" + "03" + "666F6F" + "21" + "7B" +
"41" + "03" + "626172" + "00" + "80");
r.readMapStart();
assertFalse(r.hasMapEnd());
r.readDictionaryStart();
assertFalse(r.hasDictionaryEnd());
assertEquals("foo", r.readString(1000));
assertFalse(r.hasMapEnd());
assertFalse(r.hasDictionaryEnd());
assertEquals(123, r.readInteger());
assertFalse(r.hasMapEnd());
assertFalse(r.hasDictionaryEnd());
assertEquals("bar", r.readString(1000));
assertFalse(r.hasMapEnd());
assertFalse(r.hasDictionaryEnd());
assertTrue(r.hasNull());
r.readNull();
assertTrue(r.hasMapEnd());
r.readMapEnd();
assertTrue(r.hasDictionaryEnd());
r.readDictionaryEnd();
assertTrue(r.eof());
}
@Test
public void testSkipMap() throws Exception {
public void testSkipDictionary() throws Exception {
// A map containing "foo" -> 123 and "bar" -> null
setContents("70" + "41" + "03" + "666F6F" + "21" + "7B" +
"41" + "03" + "626172" + "00" + "80");
r.skipMap();
r.skipDictionary();
assertTrue(r.eof());
}
@Test
public void testSkipNestedListsAndMaps() throws Exception {
// A list containing a map containing two empty lists
setContents("60" + "70" + "60" + "80" + "60" + "80" + "80" + "80");
public void testSkipNestedListsAndDictionaries() throws Exception {
// A list containing a dictionary containing "" -> an empty list
setContents("60" + "70" + "4100" + "60" + "80" + "80" + "80");
r.skipList();
assertTrue(r.eof());
}
private void setContents(String hex) {
in = new ByteArrayInputStream(StringUtils.fromHexString(hex));
r = new ReaderImpl(in);
ByteArrayInputStream in = new ByteArrayInputStream(
StringUtils.fromHexString(hex));
r = new BdfReaderImpl(in);
}
}

View File

@@ -16,15 +16,15 @@ import java.util.Map;
import static org.junit.Assert.assertTrue;
public class WriterImplTest extends BriarTestCase {
public class BdfWriterImplTest extends BriarTestCase {
private ByteArrayOutputStream out = null;
private WriterImpl w = null;
private BdfWriterImpl w = null;
@Before
public void setUp() {
out = new ByteArrayOutputStream();
w = new WriterImpl(out);
w = new BdfWriterImpl(out);
}
@Test
@@ -165,12 +165,12 @@ public class WriterImplTest extends BriarTestCase {
}
@Test
public void testWriteMap() throws IOException {
public void testWriteDictionary() throws IOException {
// Use LinkedHashMap to get predictable iteration order
Map<String, Object> m = new LinkedHashMap<String, Object>();
for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i);
w.writeMap(m);
// MAP tag, keys as strings and values as integers, END tag
w.writeDictionary(m);
// DICTIONARY tag, keys as strings and values as integers, END tag
checkContents("70" + "41" + "01" + "30" + "21" + "00" +
"41" + "01" + "31" + "21" + "01" +
"41" + "01" + "32" + "21" + "02" +
@@ -191,21 +191,21 @@ public class WriterImplTest extends BriarTestCase {
}
@Test
public void testWriteDelimitedMap() throws IOException {
w.writeMapStart();
public void testWriteDelimitedDictionary() throws IOException {
w.writeDictionaryStart();
w.writeString("foo");
w.writeInteger(123);
w.writeString("bar");
w.writeNull();
w.writeMapEnd();
// MAP tag, "foo" as string, 123 as integer, "bar" as string,
w.writeDictionaryEnd();
// DICTIONARY tag, "foo" as string, 123 as integer, "bar" as string,
// NULL tag, END tag
checkContents("70" + "41" + "03" + "666F6F" +
"21" + "7B" + "41" + "03" + "626172" + "00" + "80");
}
@Test
public void testWriteNestedMapsAndLists() throws IOException {
public void testWriteNestedDictionariesAndLists() throws IOException {
Map<String, Object> inner = new LinkedHashMap<String, Object>();
inner.put("bar", new byte[0]);
List<Object> list = new ArrayList<Object>();
@@ -213,9 +213,9 @@ public class WriterImplTest extends BriarTestCase {
list.add(inner);
Map<String, Object> outer = new LinkedHashMap<String, Object>();
outer.put("foo", list);
w.writeMap(outer);
// MAP tag, "foo" as string, LIST tag, 1 as integer, MAP tag,
// "bar" as string, {} as raw, END tag, END tag, END tag
w.writeDictionary(outer);
// DICTIONARY tag, "foo" as string, LIST tag, 1 as integer,
// DICTIONARY tag, "bar" as string, {} as raw, END tag, END tag, END tag
checkContents("70" + "41" + "03" + "666F6F" + "60" +
"21" + "01" + "70" + "41" + "03" + "626172" + "51" + "00" +
"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);
byte[] dig = messageDigest.digest();
// Check that feeding a DigestingConsumer generates the same digest
org.briarproject.sync.DigestingConsumer
dc = new org.briarproject.sync.DigestingConsumer(messageDigest);
DigestingConsumer dc = new DigestingConsumer(messageDigest);
dc.write(data[0]);
dc.write(data, 1, data.length - 2);
dc.write(data[data.length - 1]);
@@ -35,8 +34,7 @@ public class ConsumersTest extends BriarTestCase {
@Test
public void testCountingConsumer() throws Exception {
byte[] data = new byte[1234];
org.briarproject.sync.CountingConsumer
cc = new org.briarproject.sync.CountingConsumer(data.length);
CountingConsumer cc = new CountingConsumer(data.length);
cc.write(data[0]);
cc.write(data, 1, data.length - 2);
cc.write(data[data.length - 1]);
@@ -54,8 +52,7 @@ public class ConsumersTest extends BriarTestCase {
byte[] data = new byte[1234];
new Random().nextBytes(data);
// Check that a CopyingConsumer creates a faithful copy
org.briarproject.sync.CopyingConsumer
cc = new org.briarproject.sync.CopyingConsumer();
CopyingConsumer cc = new CopyingConsumer();
cc.write(data[0]);
cc.write(data, 1, data.length - 2);
cc.write(data[data.length - 1]);

View File

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

View File

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