Defined some user-defined tags for protocol elements. Currently they're just adding redundancy, but in future they'll be used for parsing nested elements.

This commit is contained in:
akwizgran
2011-07-18 17:44:18 +01:00
parent 427142ae51
commit 30fc6c1a92
14 changed files with 146 additions and 52 deletions

View File

@@ -1,7 +1,10 @@
package net.sf.briar.api.protocol; package net.sf.briar.api.protocol;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import net.sf.briar.api.serial.Writer;
/** Type-safe wrapper for a byte array that uniquely identifies an author. */ /** Type-safe wrapper for a byte array that uniquely identifies an author. */
public class AuthorId extends UniqueId { public class AuthorId extends UniqueId {
@@ -9,6 +12,11 @@ public class AuthorId extends UniqueId {
super(id); super(id);
} }
public void writeTo(Writer w) throws IOException {
w.writeUserDefinedTag(Tags.AUTHOR_ID);
w.writeRaw(id);
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if(o instanceof AuthorId) if(o instanceof AuthorId)

View File

@@ -1,7 +1,10 @@
package net.sf.briar.api.protocol; package net.sf.briar.api.protocol;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import net.sf.briar.api.serial.Writer;
/** /**
* Type-safe wrapper for a byte array that uniquely identifies a batch of * Type-safe wrapper for a byte array that uniquely identifies a batch of
* messages. * messages.
@@ -12,6 +15,11 @@ public class BatchId extends UniqueId {
super(id); super(id);
} }
public void writeTo(Writer w) throws IOException {
w.writeUserDefinedTag(Tags.BATCH_ID);
w.writeRaw(id);
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if(o instanceof BatchId) if(o instanceof BatchId)

View File

@@ -1,7 +1,10 @@
package net.sf.briar.api.protocol; package net.sf.briar.api.protocol;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import net.sf.briar.api.serial.Writer;
/** /**
* Type-safe wrapper for a byte array that uniquely identifies a group to which * Type-safe wrapper for a byte array that uniquely identifies a group to which
* users may subscribe. * users may subscribe.
@@ -12,6 +15,11 @@ public class GroupId extends UniqueId {
super(id); super(id);
} }
public void writeTo(Writer w) throws IOException {
w.writeUserDefinedTag(Tags.GROUP_ID);
w.writeRaw(id);
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if(o instanceof GroupId) if(o instanceof GroupId)

View File

@@ -1,7 +1,10 @@
package net.sf.briar.api.protocol; package net.sf.briar.api.protocol;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import net.sf.briar.api.serial.Writer;
/** Type-safe wrapper for a byte array that uniquely identifies a message. */ /** Type-safe wrapper for a byte array that uniquely identifies a message. */
public class MessageId extends UniqueId { public class MessageId extends UniqueId {
@@ -15,6 +18,11 @@ public class MessageId extends UniqueId {
super(id); super(id);
} }
public void writeTo(Writer w) throws IOException {
w.writeUserDefinedTag(Tags.MESSAGE_ID);
w.writeRaw(id);
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if(o instanceof MessageId) if(o instanceof MessageId)

View File

@@ -0,0 +1,16 @@
package net.sf.briar.api.protocol;
public interface Tags {
static final int HEADER = 0;
static final int BATCH_ID = 1;
static final int GROUP_ID = 2;
static final int TIMESTAMP = 3;
static final int SIGNATURE = 4;
static final int BATCH = 5;
static final int MESSAGE = 6;
static final int MESSAGE_ID = 7;
static final int AUTHOR = 8;
static final int MESSAGE_BODY = 9;
static final int AUTHOR_ID = 10;
}

View File

@@ -3,8 +3,9 @@ package net.sf.briar.api.protocol;
import java.util.Arrays; import java.util.Arrays;
import net.sf.briar.api.serial.Raw; import net.sf.briar.api.serial.Raw;
import net.sf.briar.api.serial.Writable;
public abstract class UniqueId implements Raw { public abstract class UniqueId implements Raw, Writable {
public static final int LENGTH = 32; public static final int LENGTH = 32;

View File

@@ -59,4 +59,5 @@ public interface Reader {
boolean hasUserDefinedTag() throws IOException; boolean hasUserDefinedTag() throws IOException;
int readUserDefinedTag() throws IOException; int readUserDefinedTag() throws IOException;
void readUserDefinedTag(int i) throws IOException;
} }

View File

@@ -2,30 +2,30 @@ package net.sf.briar.api.serial;
public interface Tag { public interface Tag {
public static final byte FALSE = -1; // 1111 1111 static final byte FALSE = -1; // 1111 1111
public static final byte TRUE = -2; // 1111 1110 static final byte TRUE = -2; // 1111 1110
public static final byte INT8 = -3; // 1111 1101 static final byte INT8 = -3; // 1111 1101
public static final byte INT16 = -4; // 1111 1100 static final byte INT16 = -4; // 1111 1100
public static final byte INT32 = -5; // 1111 1011 static final byte INT32 = -5; // 1111 1011
public static final byte INT64 = -6; // 1111 1010 static final byte INT64 = -6; // 1111 1010
public static final byte FLOAT32 = -7; // 1111 1001 static final byte FLOAT32 = -7; // 1111 1001
public static final byte FLOAT64 = -8; // 1111 1000 static final byte FLOAT64 = -8; // 1111 1000
public static final byte STRING = -9; // 1111 0111 static final byte STRING = -9; // 1111 0111
public static final byte RAW = -10; // 1111 0110 static final byte RAW = -10; // 1111 0110
public static final byte LIST = -11; // 1111 0101 static final byte LIST = -11; // 1111 0101
public static final byte MAP = -12; // 1111 0100 static final byte MAP = -12; // 1111 0100
public static final byte LIST_START = -13; // 1111 0011 static final byte LIST_START = -13; // 1111 0011
public static final byte MAP_START = -14; // 1111 0010 static final byte MAP_START = -14; // 1111 0010
public static final byte END = -15; // 1111 0001 static final byte END = -15; // 1111 0001
public static final byte NULL = -16; // 1111 0000 static final byte NULL = -16; // 1111 0000
static final byte USER = -17; // 1110 1111
public static final byte USER = -32; // 1110 0000 static final int SHORT_MASK = 0xF0; // Match first four bits
static final int SHORT_STRING = 0x80; // 1000 xxxx
static final int SHORT_RAW = 0x90; // 1001 xxxx
static final int SHORT_LIST = 0xA0; // 1010 xxxx
static final int SHORT_MAP = 0xB0; // 1011 xxxx
public static final int SHORT_MASK = 0xF0; // Match first four bits static final int SHORT_USER_MASK = 0xE0; // Match first three bits
public static final int SHORT_STRING = 0x80; // 1000 xxxx static final int SHORT_USER = 0xC0; // 110x xxxx
public static final int SHORT_RAW = 0x90; // 1001 xxxx
public static final int SHORT_LIST = 0xA0; // 1010 xxxx
public static final int SHORT_MAP = 0xB0; // 1011 xxxx
public static final int SHORT_USER_MASK = 0xE0; // Match first three bits
public static final int SHORT_USER = 0xC0; // 110x xxxx
} }

View File

@@ -0,0 +1,8 @@
package net.sf.briar.api.serial;
import java.io.IOException;
public interface Writable {
void writeTo(Writer w) throws IOException;
}

View File

@@ -20,8 +20,10 @@ import net.sf.briar.api.protocol.Header;
import net.sf.briar.api.protocol.Message; import net.sf.briar.api.protocol.Message;
import net.sf.briar.api.protocol.MessageParser; import net.sf.briar.api.protocol.MessageParser;
import net.sf.briar.api.protocol.UniqueId; import net.sf.briar.api.protocol.UniqueId;
import net.sf.briar.api.protocol.Tags;
import net.sf.briar.api.serial.FormatException; import net.sf.briar.api.serial.FormatException;
import net.sf.briar.api.serial.Raw; import net.sf.briar.api.serial.Raw;
import net.sf.briar.api.serial.RawByteArray;
import net.sf.briar.api.serial.Reader; import net.sf.briar.api.serial.Reader;
class BundleReaderImpl implements BundleReader { class BundleReaderImpl implements BundleReader {
@@ -59,23 +61,36 @@ class BundleReaderImpl implements BundleReader {
// Read the signed data // Read the signed data
reader.addConsumer(counting); reader.addConsumer(counting);
reader.addConsumer(signing); reader.addConsumer(signing);
reader.readUserDefinedTag(Tags.HEADER);
// Acks
Set<BatchId> acks = new HashSet<BatchId>(); Set<BatchId> acks = new HashSet<BatchId>();
for(Raw raw : reader.readList(Raw.class)) { reader.readListStart();
byte[] b = raw.getBytes(); while(!reader.hasListEnd()) {
reader.readUserDefinedTag(Tags.BATCH_ID);
byte[] b = reader.readRaw();
if(b.length != UniqueId.LENGTH) throw new FormatException(); if(b.length != UniqueId.LENGTH) throw new FormatException();
acks.add(new BatchId(b)); acks.add(new BatchId(b));
} }
reader.readListEnd();
// Subs
Set<GroupId> subs = new HashSet<GroupId>(); Set<GroupId> subs = new HashSet<GroupId>();
for(Raw raw : reader.readList(Raw.class)) { reader.readListStart();
byte[] b = raw.getBytes(); while(!reader.hasListEnd()) {
reader.readUserDefinedTag(Tags.GROUP_ID);
byte[] b = reader.readRaw();
if(b.length != UniqueId.LENGTH) throw new FormatException(); if(b.length != UniqueId.LENGTH) throw new FormatException();
subs.add(new GroupId(b)); subs.add(new GroupId(b));
} }
reader.readListEnd();
// Transports
Map<String, String> transports = Map<String, String> transports =
reader.readMap(String.class, String.class); reader.readMap(String.class, String.class);
// Timestamp
reader.readUserDefinedTag(Tags.TIMESTAMP);
long timestamp = reader.readInt64(); long timestamp = reader.readInt64();
reader.removeConsumer(signing); reader.removeConsumer(signing);
// Read and verify the signature // Read and verify the signature
reader.readUserDefinedTag(Tags.SIGNATURE);
byte[] sig = reader.readRaw(); byte[] sig = reader.readRaw();
reader.removeConsumer(counting); reader.removeConsumer(counting);
if(!signature.verify(sig)) throw new SignatureException(); if(!signature.verify(sig)) throw new SignatureException();
@@ -106,9 +121,17 @@ class BundleReaderImpl implements BundleReader {
reader.addConsumer(counting); reader.addConsumer(counting);
reader.addConsumer(digesting); reader.addConsumer(digesting);
reader.addConsumer(signing); reader.addConsumer(signing);
List<Raw> rawMessages = reader.readList(Raw.class); reader.readUserDefinedTag(Tags.BATCH);
List<Raw> rawMessages = new ArrayList<Raw>();
reader.readListStart();
while(!reader.hasListEnd()) {
reader.readUserDefinedTag(Tags.MESSAGE);
rawMessages.add(new RawByteArray(reader.readRaw()));
}
reader.readListEnd();
reader.removeConsumer(signing); reader.removeConsumer(signing);
// Read and verify the signature // Read and verify the signature
reader.readUserDefinedTag(Tags.SIGNATURE);
byte[] sig = reader.readRaw(); byte[] sig = reader.readRaw();
reader.removeConsumer(digesting); reader.removeConsumer(digesting);
reader.removeConsumer(counting); reader.removeConsumer(counting);

View File

@@ -11,6 +11,7 @@ import java.util.Map;
import net.sf.briar.api.protocol.BatchId; import net.sf.briar.api.protocol.BatchId;
import net.sf.briar.api.protocol.BundleWriter; import net.sf.briar.api.protocol.BundleWriter;
import net.sf.briar.api.protocol.GroupId; import net.sf.briar.api.protocol.GroupId;
import net.sf.briar.api.protocol.Tags;
import net.sf.briar.api.serial.Raw; import net.sf.briar.api.serial.Raw;
import net.sf.briar.api.serial.Writer; import net.sf.briar.api.serial.Writer;
import net.sf.briar.api.serial.WriterFactory; import net.sf.briar.api.serial.WriterFactory;
@@ -20,7 +21,7 @@ class BundleWriterImpl implements BundleWriter {
private static enum State { START, FIRST_BATCH, MORE_BATCHES, END }; private static enum State { START, FIRST_BATCH, MORE_BATCHES, END };
private final SigningDigestingOutputStream out; private final SigningDigestingOutputStream out;
private final Writer w; private final Writer writer;
private final PrivateKey privateKey; private final PrivateKey privateKey;
private final Signature signature; private final Signature signature;
private final MessageDigest messageDigest; private final MessageDigest messageDigest;
@@ -32,7 +33,7 @@ class BundleWriterImpl implements BundleWriter {
MessageDigest messageDigest, long capacity) { MessageDigest messageDigest, long capacity) {
this.out = this.out =
new SigningDigestingOutputStream(out, signature, messageDigest); new SigningDigestingOutputStream(out, signature, messageDigest);
w = writerFactory.createWriter(this.out); writer = writerFactory.createWriter(this.out);
this.privateKey = privateKey; this.privateKey = privateKey;
this.signature = signature; this.signature = signature;
this.messageDigest = messageDigest; this.messageDigest = messageDigest;
@@ -40,7 +41,7 @@ class BundleWriterImpl implements BundleWriter {
} }
public long getRemainingCapacity() { public long getRemainingCapacity() {
return capacity - w.getBytesWritten(); return capacity - writer.getBytesWritten();
} }
public void addHeader(Iterable<BatchId> acks, Iterable<GroupId> subs, public void addHeader(Iterable<BatchId> acks, Iterable<GroupId> subs,
@@ -51,18 +52,21 @@ class BundleWriterImpl implements BundleWriter {
signature.initSign(privateKey); signature.initSign(privateKey);
// Write the data to be signed // Write the data to be signed
out.setSigning(true); out.setSigning(true);
w.writeListStart(); writer.writeUserDefinedTag(Tags.HEADER);
for(BatchId ack : acks) w.writeRaw(ack); writer.writeListStart();
w.writeListEnd(); for(BatchId ack : acks) ack.writeTo(writer);
w.writeListStart(); writer.writeListEnd();
for(GroupId sub : subs) w.writeRaw(sub); writer.writeListStart();
w.writeListEnd(); for(GroupId sub : subs) sub.writeTo(writer);
w.writeMap(transports); writer.writeListEnd();
w.writeInt64(System.currentTimeMillis()); writer.writeMap(transports);
writer.writeUserDefinedTag(Tags.TIMESTAMP);
writer.writeInt64(System.currentTimeMillis());
out.setSigning(false); out.setSigning(false);
// Create and write the signature // Create and write the signature
byte[] sig = signature.sign(); byte[] sig = signature.sign();
w.writeRaw(sig); writer.writeUserDefinedTag(Tags.SIGNATURE);
writer.writeRaw(sig);
// Expect a (possibly empty) list of batches // Expect a (possibly empty) list of batches
state = State.FIRST_BATCH; state = State.FIRST_BATCH;
} }
@@ -70,7 +74,7 @@ class BundleWriterImpl implements BundleWriter {
public BatchId addBatch(Iterable<Raw> messages) throws IOException, public BatchId addBatch(Iterable<Raw> messages) throws IOException,
GeneralSecurityException { GeneralSecurityException {
if(state == State.FIRST_BATCH) { if(state == State.FIRST_BATCH) {
w.writeListStart(); writer.writeListStart();
state = State.MORE_BATCHES; state = State.MORE_BATCHES;
} }
if(state != State.MORE_BATCHES) throw new IllegalStateException(); if(state != State.MORE_BATCHES) throw new IllegalStateException();
@@ -80,13 +84,18 @@ class BundleWriterImpl implements BundleWriter {
// Write the data to be signed // Write the data to be signed
out.setDigesting(true); out.setDigesting(true);
out.setSigning(true); out.setSigning(true);
w.writeListStart(); writer.writeUserDefinedTag(Tags.BATCH);
for(Raw message : messages) w.writeRaw(message); writer.writeListStart();
w.writeListEnd(); for(Raw message : messages) {
writer.writeUserDefinedTag(Tags.MESSAGE);
writer.writeRaw(message);
}
writer.writeListEnd();
out.setSigning(false); out.setSigning(false);
// Create and write the signature // Create and write the signature
byte[] sig = signature.sign(); byte[] sig = signature.sign();
w.writeRaw(sig); writer.writeUserDefinedTag(Tags.SIGNATURE);
writer.writeRaw(sig);
out.setDigesting(false); out.setDigesting(false);
// Calculate and return the ID // Calculate and return the ID
return new BatchId(messageDigest.digest()); return new BatchId(messageDigest.digest());
@@ -94,12 +103,12 @@ class BundleWriterImpl implements BundleWriter {
public void finish() throws IOException { public void finish() throws IOException {
if(state == State.FIRST_BATCH) { if(state == State.FIRST_BATCH) {
w.writeListStart(); writer.writeListStart();
state = State.MORE_BATCHES; state = State.MORE_BATCHES;
} }
if(state != State.MORE_BATCHES) throw new IllegalStateException(); if(state != State.MORE_BATCHES) throw new IllegalStateException();
w.writeListEnd(); writer.writeListEnd();
w.close(); writer.close();
state = State.END; state = State.END;
} }
} }

View File

@@ -478,4 +478,8 @@ class ReaderImpl implements Reader {
return tag; return tag;
} }
} }
public void readUserDefinedTag(int i) throws IOException {
if(readUserDefinedTag() != i) throw new FormatException();
}
} }

View File

@@ -318,7 +318,7 @@ public class ReaderImplTest extends TestCase {
@Test @Test
public void testReadUserDefinedTag() throws IOException { public void testReadUserDefinedTag() throws IOException {
setContents("C0" + "DF" + "E0" + "20" + "E0" + "FB7FFFFFFF"); setContents("C0" + "DF" + "EF" + "20" + "EF" + "FB7FFFFFFF");
assertEquals(0, r.readUserDefinedTag()); assertEquals(0, r.readUserDefinedTag());
assertEquals(31, r.readUserDefinedTag()); assertEquals(31, r.readUserDefinedTag());
assertEquals(32, r.readUserDefinedTag()); assertEquals(32, r.readUserDefinedTag());

View File

@@ -297,7 +297,7 @@ public class WriterImplTest extends TestCase {
w.writeUserDefinedTag(32); w.writeUserDefinedTag(32);
w.writeUserDefinedTag(Integer.MAX_VALUE); w.writeUserDefinedTag(Integer.MAX_VALUE);
// USER tag, 32 as uint7, USER tag, 2147483647 as int32 // USER tag, 32 as uint7, USER tag, 2147483647 as int32
checkContents("E0" + "20" + "E0" + "FB7FFFFFFF"); checkContents("EF" + "20" + "EF" + "FB7FFFFFFF");
} }
private void checkContents(String hex) throws IOException { private void checkContents(String hex) throws IOException {