mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 05:39:53 +01:00
Implemented PacketReader, renamed Packet{Reader,Writer}Factory in the
protocol component to Protocol{Reader,Writer}Factory.
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
package net.sf.briar.api.protocol.writers;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import net.sf.briar.api.protocol.Ack;
|
||||||
|
import net.sf.briar.api.protocol.Batch;
|
||||||
|
import net.sf.briar.api.protocol.Offer;
|
||||||
|
import net.sf.briar.api.protocol.Request;
|
||||||
|
import net.sf.briar.api.protocol.SubscriptionUpdate;
|
||||||
|
import net.sf.briar.api.protocol.TransportUpdate;
|
||||||
|
import net.sf.briar.api.serial.ObjectReader;
|
||||||
|
|
||||||
|
public interface ProtocolReaderFactory {
|
||||||
|
|
||||||
|
ObjectReader<Ack> createAckReader(InputStream in);
|
||||||
|
|
||||||
|
ObjectReader<Batch> createBatchReader(InputStream in);
|
||||||
|
|
||||||
|
ObjectReader<Offer> createOfferReader(InputStream in);
|
||||||
|
|
||||||
|
ObjectReader<Request> createRequestReader(InputStream in);
|
||||||
|
|
||||||
|
ObjectReader<SubscriptionUpdate> createSubscriptionReader(InputStream in);
|
||||||
|
|
||||||
|
ObjectReader<TransportUpdate> createTransportReader(InputStream in);
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package net.sf.briar.api.protocol.writers;
|
|||||||
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
public interface PacketWriterFactory {
|
public interface ProtocolWriterFactory {
|
||||||
|
|
||||||
AckWriter createAckWriter(OutputStream out);
|
AckWriter createAckWriter(OutputStream out);
|
||||||
|
|
||||||
@@ -8,9 +8,9 @@ public interface ConnectionWindow {
|
|||||||
|
|
||||||
int getBitmap();
|
int getBitmap();
|
||||||
|
|
||||||
boolean isSeen(long connectionNumber);
|
boolean isSeen(long connection);
|
||||||
|
|
||||||
void setSeen(long connectionNumber);
|
void setSeen(long connection);
|
||||||
|
|
||||||
Collection<Long> getUnseenConnectionNumbers();
|
Collection<Long> getUnseenConnectionNumbers();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import javax.crypto.SecretKey;
|
|||||||
|
|
||||||
public interface PacketWriterFactory {
|
public interface PacketWriterFactory {
|
||||||
|
|
||||||
PacketWriter createPacketWriter(OutputStream out, int transportIdentifier,
|
PacketWriter createPacketWriter(OutputStream out, int transportId,
|
||||||
long connectionNumber, SecretKey macKey, SecretKey tagKey,
|
long connection, SecretKey macKey, SecretKey tagKey,
|
||||||
SecretKey packetKey);
|
SecretKey packetKey);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import net.sf.briar.api.crypto.CryptoComponent;
|
|||||||
import net.sf.briar.api.protocol.writers.AckWriter;
|
import net.sf.briar.api.protocol.writers.AckWriter;
|
||||||
import net.sf.briar.api.protocol.writers.BatchWriter;
|
import net.sf.briar.api.protocol.writers.BatchWriter;
|
||||||
import net.sf.briar.api.protocol.writers.OfferWriter;
|
import net.sf.briar.api.protocol.writers.OfferWriter;
|
||||||
import net.sf.briar.api.protocol.writers.PacketWriterFactory;
|
import net.sf.briar.api.protocol.writers.ProtocolWriterFactory;
|
||||||
import net.sf.briar.api.protocol.writers.RequestWriter;
|
import net.sf.briar.api.protocol.writers.RequestWriter;
|
||||||
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
||||||
import net.sf.briar.api.protocol.writers.TransportWriter;
|
import net.sf.briar.api.protocol.writers.TransportWriter;
|
||||||
@@ -15,13 +15,13 @@ import net.sf.briar.api.serial.WriterFactory;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
class PacketWriterFactoryImpl implements PacketWriterFactory {
|
class ProtocolWriterFactoryImpl implements ProtocolWriterFactory {
|
||||||
|
|
||||||
private final MessageDigest messageDigest;
|
private final MessageDigest messageDigest;
|
||||||
private final WriterFactory writerFactory;
|
private final WriterFactory writerFactory;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
PacketWriterFactoryImpl(CryptoComponent crypto,
|
ProtocolWriterFactoryImpl(CryptoComponent crypto,
|
||||||
WriterFactory writerFactory) {
|
WriterFactory writerFactory) {
|
||||||
messageDigest = crypto.getMessageDigest();
|
messageDigest = crypto.getMessageDigest();
|
||||||
this.writerFactory = writerFactory;
|
this.writerFactory = writerFactory;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package net.sf.briar.protocol.writers;
|
package net.sf.briar.protocol.writers;
|
||||||
|
|
||||||
import net.sf.briar.api.protocol.writers.PacketWriterFactory;
|
import net.sf.briar.api.protocol.writers.ProtocolWriterFactory;
|
||||||
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
|
|
||||||
@@ -8,6 +8,6 @@ public class WritersModule extends AbstractModule {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(PacketWriterFactory.class).to(PacketWriterFactoryImpl.class);
|
bind(ProtocolWriterFactory.class).to(ProtocolWriterFactoryImpl.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,9 +76,8 @@ DatabaseListener {
|
|||||||
initialised = true;
|
initialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized byte[] calculateTag(ContactId c,
|
private synchronized byte[] calculateTag(ContactId c, long connection) {
|
||||||
long connectionNumber) {
|
byte[] tag = TagEncoder.encodeTag(transportId, connection, 0L);
|
||||||
byte[] tag = TagEncoder.encodeTag(transportId, connectionNumber, 0L);
|
|
||||||
Cipher cipher = contactToCipher.get(c);
|
Cipher cipher = contactToCipher.get(c);
|
||||||
assert cipher != null;
|
assert cipher != null;
|
||||||
try {
|
try {
|
||||||
@@ -97,25 +96,25 @@ DatabaseListener {
|
|||||||
if(!initialised) initialise();
|
if(!initialised) initialise();
|
||||||
Bytes b = new Bytes(tag);
|
Bytes b = new Bytes(tag);
|
||||||
ContactId contactId = tagToContact.remove(b);
|
ContactId contactId = tagToContact.remove(b);
|
||||||
Long connectionNumber = tagToConnectionNumber.remove(b);
|
Long connection = tagToConnectionNumber.remove(b);
|
||||||
assert (contactId == null) == (connectionNumber == null);
|
assert (contactId == null) == (connection == null);
|
||||||
if(contactId == null) return null;
|
if(contactId == null) return null;
|
||||||
// The tag was expected - update and save the connection window
|
// The tag was expected - update and save the connection window
|
||||||
ConnectionWindow w = contactToWindow.get(contactId);
|
ConnectionWindow w = contactToWindow.get(contactId);
|
||||||
assert w != null;
|
assert w != null;
|
||||||
w.setSeen(connectionNumber);
|
w.setSeen(connection);
|
||||||
db.setConnectionWindow(contactId, transportId, w);
|
db.setConnectionWindow(contactId, transportId, w);
|
||||||
// Update the set of expected tags
|
// Update the set of expected tags
|
||||||
Map<Long, Bytes> oldTags = contactToTags.remove(contactId);
|
Map<Long, Bytes> oldTags = contactToTags.remove(contactId);
|
||||||
assert oldTags != null;
|
assert oldTags != null;
|
||||||
assert oldTags.containsKey(connectionNumber);
|
assert oldTags.containsKey(connection);
|
||||||
Map<Long, Bytes> newTags = new HashMap<Long, Bytes>();
|
Map<Long, Bytes> newTags = new HashMap<Long, Bytes>();
|
||||||
for(Long unseen : w.getUnseenConnectionNumbers()) {
|
for(Long unseen : w.getUnseenConnectionNumbers()) {
|
||||||
Bytes expectedTag = oldTags.get(unseen);
|
Bytes expectedTag = oldTags.get(unseen);
|
||||||
if(expectedTag == null) {
|
if(expectedTag == null) {
|
||||||
expectedTag = new Bytes(calculateTag(contactId, unseen));
|
expectedTag = new Bytes(calculateTag(contactId, unseen));
|
||||||
tagToContact.put(expectedTag, contactId);
|
tagToContact.put(expectedTag, contactId);
|
||||||
tagToConnectionNumber.put(expectedTag, connectionNumber);
|
tagToConnectionNumber.put(expectedTag, connection);
|
||||||
}
|
}
|
||||||
newTags.put(unseen, expectedTag);
|
newTags.put(unseen, expectedTag);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,29 +23,29 @@ class ConnectionWindowImpl implements ConnectionWindow {
|
|||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSeen(long connectionNumber) {
|
public boolean isSeen(long connection) {
|
||||||
int offset = getOffset(connectionNumber);
|
int offset = getOffset(connection);
|
||||||
int mask = 0x80000000 >>> offset;
|
int mask = 0x80000000 >>> offset;
|
||||||
return (bitmap & mask) != 0;
|
return (bitmap & mask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getOffset(long connectionNumber) {
|
private int getOffset(long connection) {
|
||||||
if(connectionNumber < 0L) throw new IllegalArgumentException();
|
if(connection < 0L) throw new IllegalArgumentException();
|
||||||
if(connectionNumber > Constants.MAX_32_BIT_UNSIGNED)
|
if(connection > Constants.MAX_32_BIT_UNSIGNED)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
int offset = (int) (connectionNumber - centre) + 16;
|
int offset = (int) (connection - centre) + 16;
|
||||||
if(offset < 0 || offset > 31) throw new IllegalArgumentException();
|
if(offset < 0 || offset > 31) throw new IllegalArgumentException();
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSeen(long connectionNumber) {
|
public void setSeen(long connection) {
|
||||||
int offset = getOffset(connectionNumber);
|
int offset = getOffset(connection);
|
||||||
int mask = 0x80000000 >>> offset;
|
int mask = 0x80000000 >>> offset;
|
||||||
if((bitmap & mask) != 0) throw new IllegalArgumentException();
|
if((bitmap & mask) != 0) throw new IllegalArgumentException();
|
||||||
bitmap |= mask;
|
bitmap |= mask;
|
||||||
// If the new connection number is above the centre, slide the window
|
// If the new connection number is above the centre, slide the window
|
||||||
if(connectionNumber >= centre) {
|
if(connection >= centre) {
|
||||||
centre = connectionNumber + 1;
|
centre = connection + 1;
|
||||||
bitmap <<= offset - 16 + 1;
|
bitmap <<= offset - 16 + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
126
components/net/sf/briar/transport/PacketReaderImpl.java
Normal file
126
components/net/sf/briar/transport/PacketReaderImpl.java
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
package net.sf.briar.transport;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
|
||||||
|
import net.sf.briar.api.protocol.Ack;
|
||||||
|
import net.sf.briar.api.protocol.Batch;
|
||||||
|
import net.sf.briar.api.protocol.Offer;
|
||||||
|
import net.sf.briar.api.protocol.Request;
|
||||||
|
import net.sf.briar.api.protocol.SubscriptionUpdate;
|
||||||
|
import net.sf.briar.api.protocol.Tags;
|
||||||
|
import net.sf.briar.api.protocol.TransportUpdate;
|
||||||
|
import net.sf.briar.api.protocol.writers.ProtocolReaderFactory;
|
||||||
|
import net.sf.briar.api.serial.Reader;
|
||||||
|
import net.sf.briar.api.serial.ReaderFactory;
|
||||||
|
import net.sf.briar.api.transport.PacketReader;
|
||||||
|
|
||||||
|
class PacketReaderImpl implements PacketReader {
|
||||||
|
|
||||||
|
private final Reader reader;
|
||||||
|
private final PacketDecrypter decrypter;
|
||||||
|
private final Mac mac;
|
||||||
|
private final int transportId;
|
||||||
|
private final long connection;
|
||||||
|
|
||||||
|
private long packet = 0L;
|
||||||
|
private boolean betweenPackets = true;
|
||||||
|
|
||||||
|
PacketReaderImpl(byte[] firstTag, ReaderFactory readerFactory,
|
||||||
|
ProtocolReaderFactory protocol, PacketDecrypter decrypter, Mac mac,
|
||||||
|
int transportId, long connection) {
|
||||||
|
InputStream in = decrypter.getInputStream();
|
||||||
|
reader = readerFactory.createReader(in);
|
||||||
|
reader.addObjectReader(Tags.ACK, protocol.createAckReader(in));
|
||||||
|
reader.addObjectReader(Tags.BATCH, protocol.createBatchReader(in));
|
||||||
|
reader.addObjectReader(Tags.OFFER, protocol.createOfferReader(in));
|
||||||
|
reader.addObjectReader(Tags.REQUEST, protocol.createRequestReader(in));
|
||||||
|
reader.addObjectReader(Tags.SUBSCRIPTIONS,
|
||||||
|
protocol.createSubscriptionReader(in));
|
||||||
|
reader.addObjectReader(Tags.TRANSPORTS,
|
||||||
|
protocol.createTransportReader(in));
|
||||||
|
this.decrypter = decrypter;
|
||||||
|
this.mac = mac;
|
||||||
|
this.transportId = transportId;
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean eof() throws IOException {
|
||||||
|
return reader.eof();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasAck() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.hasUserDefined(Tags.ACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readTag() throws IOException {
|
||||||
|
assert betweenPackets;
|
||||||
|
if(packet > Constants.MAX_32_BIT_UNSIGNED)
|
||||||
|
throw new IllegalStateException();
|
||||||
|
byte[] tag = decrypter.readTag();
|
||||||
|
if(!TagDecoder.decodeTag(tag, transportId, connection, packet))
|
||||||
|
throw new IOException();
|
||||||
|
mac.update(tag);
|
||||||
|
packet++;
|
||||||
|
betweenPackets = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ack readAck() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.readUserDefined(Tags.ACK, Ack.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasBatch() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.hasUserDefined(Tags.BATCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Batch readBatch() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.readUserDefined(Tags.BATCH, Batch.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasOffer() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.hasUserDefined(Tags.OFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Offer readOffer() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.readUserDefined(Tags.OFFER, Offer.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasRequest() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.hasUserDefined(Tags.REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request readRequest() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.readUserDefined(Tags.REQUEST, Request.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSubscriptionUpdate() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.hasUserDefined(Tags.SUBSCRIPTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscriptionUpdate readSubscriptionUpdate() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.readUserDefined(Tags.SUBSCRIPTIONS,
|
||||||
|
SubscriptionUpdate.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasTransportUpdate() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.hasUserDefined(Tags.TRANSPORTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransportUpdate readTransportUpdate() throws IOException {
|
||||||
|
if(betweenPackets) readTag();
|
||||||
|
return reader.readUserDefined(Tags.TRANSPORTS, TransportUpdate.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,9 +21,9 @@ class PacketWriterFactoryImpl implements PacketWriterFactory {
|
|||||||
this.crypto = crypto;
|
this.crypto = crypto;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PacketWriter createPacketWriter(OutputStream out,
|
public PacketWriter createPacketWriter(OutputStream out, int transportId,
|
||||||
int transportIdentifier, long connectionNumber, SecretKey macKey,
|
long connection, SecretKey macKey, SecretKey tagKey,
|
||||||
SecretKey tagKey, SecretKey packetKey) {
|
SecretKey packetKey) {
|
||||||
Mac mac = crypto.getMac();
|
Mac mac = crypto.getMac();
|
||||||
try {
|
try {
|
||||||
mac.init(macKey);
|
mac.init(macKey);
|
||||||
@@ -32,7 +32,7 @@ class PacketWriterFactoryImpl implements PacketWriterFactory {
|
|||||||
}
|
}
|
||||||
PacketEncrypter e = new PacketEncrypterImpl(out, crypto.getTagCipher(),
|
PacketEncrypter e = new PacketEncrypterImpl(out, crypto.getTagCipher(),
|
||||||
crypto.getPacketCipher(), tagKey, packetKey);
|
crypto.getPacketCipher(), tagKey, packetKey);
|
||||||
return new PacketWriterImpl(e, mac, transportIdentifier,
|
return new PacketWriterImpl(e, mac, transportId,
|
||||||
connectionNumber);
|
connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,25 +12,25 @@ class PacketWriterImpl extends FilterOutputStream implements PacketWriter {
|
|||||||
|
|
||||||
private final PacketEncrypter encrypter;
|
private final PacketEncrypter encrypter;
|
||||||
private final Mac mac;
|
private final Mac mac;
|
||||||
private final int transportIdentifier;
|
private final int transportId;
|
||||||
private final long connectionNumber;
|
private final long connection;
|
||||||
|
|
||||||
private long packetNumber = 0L;
|
private long packet = 0L;
|
||||||
private boolean betweenPackets = true;
|
private boolean betweenPackets = true;
|
||||||
|
|
||||||
PacketWriterImpl(PacketEncrypter encrypter, Mac mac,
|
PacketWriterImpl(PacketEncrypter encrypter, Mac mac, int transportId,
|
||||||
int transportIdentifier, long connectionNumber) {
|
long connection) {
|
||||||
super(encrypter.getOutputStream());
|
super(encrypter.getOutputStream());
|
||||||
this.encrypter = encrypter;
|
this.encrypter = encrypter;
|
||||||
this.mac = mac;
|
this.mac = mac;
|
||||||
if(transportIdentifier < 0) throw new IllegalArgumentException();
|
if(transportId < 0) throw new IllegalArgumentException();
|
||||||
if(transportIdentifier > Constants.MAX_16_BIT_UNSIGNED)
|
if(transportId > Constants.MAX_16_BIT_UNSIGNED)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
this.transportIdentifier = transportIdentifier;
|
this.transportId = transportId;
|
||||||
if(connectionNumber < 0L) throw new IllegalArgumentException();
|
if(connection < 0L) throw new IllegalArgumentException();
|
||||||
if(connectionNumber > Constants.MAX_32_BIT_UNSIGNED)
|
if(connection > Constants.MAX_32_BIT_UNSIGNED)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
this.connectionNumber = connectionNumber;
|
this.connection = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutputStream getOutputStream() {
|
public OutputStream getOutputStream() {
|
||||||
@@ -69,14 +69,15 @@ class PacketWriterImpl extends FilterOutputStream implements PacketWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeTag() throws IOException {
|
private void writeTag() throws IOException {
|
||||||
if(packetNumber > Constants.MAX_32_BIT_UNSIGNED)
|
assert betweenPackets;
|
||||||
|
if(packet > Constants.MAX_32_BIT_UNSIGNED)
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
byte[] tag = TagEncoder.encodeTag(transportIdentifier, connectionNumber,
|
byte[] tag = TagEncoder.encodeTag(transportId, connection,
|
||||||
packetNumber);
|
packet);
|
||||||
// Write the tag to the encrypter and start calculating the MAC
|
// Write the tag to the encrypter and start calculating the MAC
|
||||||
encrypter.writeTag(tag);
|
encrypter.writeTag(tag);
|
||||||
mac.update(tag);
|
mac.update(tag);
|
||||||
packetNumber++;
|
packet++;
|
||||||
betweenPackets = false;
|
betweenPackets = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
33
components/net/sf/briar/transport/TagDecoder.java
Normal file
33
components/net/sf/briar/transport/TagDecoder.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package net.sf.briar.transport;
|
||||||
|
|
||||||
|
class TagDecoder {
|
||||||
|
|
||||||
|
static boolean decodeTag(byte[] tag, int transportId, long connection,
|
||||||
|
long packet) {
|
||||||
|
if(tag.length != Constants.TAG_BYTES) return false;
|
||||||
|
// First 16 bits must be zero
|
||||||
|
if(readUint16(tag, 0) != 0) return false;
|
||||||
|
// Transport identifier is encoded as an unsigned 16-bit integer
|
||||||
|
if(readUint16(tag, 2) != transportId) return false;
|
||||||
|
// Connection number is encoded as an unsigned 32-bit integer
|
||||||
|
if(readUint32(tag, 4) != connection) return false;
|
||||||
|
// Packet number is encoded as an unsigned 32-bit integer
|
||||||
|
if(readUint32(tag, 8) != packet) return false;
|
||||||
|
// Last 32 bits must be zero
|
||||||
|
if(readUint32(tag, 12) != 0L) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Package access for testing
|
||||||
|
static int readUint16(byte[] b, int offset) {
|
||||||
|
assert b.length >= offset + 2;
|
||||||
|
return ((b[offset] & 0xFF) << 8) | (b[offset + 1] & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Package access for testing
|
||||||
|
static long readUint32(byte[] b, int offset) {
|
||||||
|
assert b.length >= offset + 4;
|
||||||
|
return ((b[offset] & 0xFFL) << 24) | ((b[offset + 1] & 0xFFL) << 16)
|
||||||
|
| ((b[offset + 2] & 0xFFL) << 8) | (b[offset + 3] & 0xFFL);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
package net.sf.briar.transport;
|
package net.sf.briar.transport;
|
||||||
|
|
||||||
public class TagEncoder {
|
class TagEncoder {
|
||||||
|
|
||||||
static byte[] encodeTag(int transportIdentifier, long connectionNumber,
|
static byte[] encodeTag(int transportId, long connection,
|
||||||
long packetNumber) {
|
long packet) {
|
||||||
byte[] tag = new byte[Constants.TAG_BYTES];
|
byte[] tag = new byte[Constants.TAG_BYTES];
|
||||||
// Encode the transport identifier as an unsigned 16-bit integer
|
// Encode the transport identifier as an unsigned 16-bit integer
|
||||||
writeUint16(transportIdentifier, tag, 2);
|
writeUint16(transportId, tag, 2);
|
||||||
// Encode the connection number as an unsigned 32-bit integer
|
// Encode the connection number as an unsigned 32-bit integer
|
||||||
writeUint32(connectionNumber, tag, 4);
|
writeUint32(connection, tag, 4);
|
||||||
// Encode the packet number as an unsigned 32-bit integer
|
// Encode the packet number as an unsigned 32-bit integer
|
||||||
writeUint32(packetNumber, tag, 8);
|
writeUint32(packet, tag, 8);
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
<test name='net.sf.briar.transport.PacketDecrypterImplTest'/>
|
<test name='net.sf.briar.transport.PacketDecrypterImplTest'/>
|
||||||
<test name='net.sf.briar.transport.PacketEncrypterImplTest'/>
|
<test name='net.sf.briar.transport.PacketEncrypterImplTest'/>
|
||||||
<test name='net.sf.briar.transport.PacketWriterImplTest'/>
|
<test name='net.sf.briar.transport.PacketWriterImplTest'/>
|
||||||
|
<test name='net.sf.briar.transport.TagDecoderTest'/>
|
||||||
<test name='net.sf.briar.transport.TagEncoderTest'/>
|
<test name='net.sf.briar.transport.TagEncoderTest'/>
|
||||||
<test name='net.sf.briar.util.FileUtilsTest'/>
|
<test name='net.sf.briar.util.FileUtilsTest'/>
|
||||||
<test name='net.sf.briar.util.StringUtilsTest'/>
|
<test name='net.sf.briar.util.StringUtilsTest'/>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import net.sf.briar.api.protocol.UniqueId;
|
|||||||
import net.sf.briar.api.protocol.writers.AckWriter;
|
import net.sf.briar.api.protocol.writers.AckWriter;
|
||||||
import net.sf.briar.api.protocol.writers.BatchWriter;
|
import net.sf.briar.api.protocol.writers.BatchWriter;
|
||||||
import net.sf.briar.api.protocol.writers.OfferWriter;
|
import net.sf.briar.api.protocol.writers.OfferWriter;
|
||||||
import net.sf.briar.api.protocol.writers.PacketWriterFactory;
|
import net.sf.briar.api.protocol.writers.ProtocolWriterFactory;
|
||||||
import net.sf.briar.api.protocol.writers.RequestWriter;
|
import net.sf.briar.api.protocol.writers.RequestWriter;
|
||||||
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
import net.sf.briar.api.protocol.writers.SubscriptionWriter;
|
||||||
import net.sf.briar.api.protocol.writers.TransportWriter;
|
import net.sf.briar.api.protocol.writers.TransportWriter;
|
||||||
@@ -60,7 +60,7 @@ public class FileReadWriteTest extends TestCase {
|
|||||||
private final long start = System.currentTimeMillis();
|
private final long start = System.currentTimeMillis();
|
||||||
|
|
||||||
private final ReaderFactory readerFactory;
|
private final ReaderFactory readerFactory;
|
||||||
private final PacketWriterFactory packetWriterFactory;
|
private final ProtocolWriterFactory protocolWriterFactory;
|
||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
private final AckReader ackReader;
|
private final AckReader ackReader;
|
||||||
private final BatchReader batchReader;
|
private final BatchReader batchReader;
|
||||||
@@ -81,7 +81,7 @@ public class FileReadWriteTest extends TestCase {
|
|||||||
new ProtocolModule(), new SerialModule(),
|
new ProtocolModule(), new SerialModule(),
|
||||||
new WritersModule());
|
new WritersModule());
|
||||||
readerFactory = i.getInstance(ReaderFactory.class);
|
readerFactory = i.getInstance(ReaderFactory.class);
|
||||||
packetWriterFactory = i.getInstance(PacketWriterFactory.class);
|
protocolWriterFactory = i.getInstance(ProtocolWriterFactory.class);
|
||||||
crypto = i.getInstance(CryptoComponent.class);
|
crypto = i.getInstance(CryptoComponent.class);
|
||||||
assertEquals(crypto.getMessageDigest().getDigestLength(),
|
assertEquals(crypto.getMessageDigest().getDigestLength(),
|
||||||
UniqueId.LENGTH);
|
UniqueId.LENGTH);
|
||||||
@@ -126,39 +126,39 @@ public class FileReadWriteTest extends TestCase {
|
|||||||
public void testWriteFile() throws Exception {
|
public void testWriteFile() throws Exception {
|
||||||
FileOutputStream out = new FileOutputStream(file);
|
FileOutputStream out = new FileOutputStream(file);
|
||||||
|
|
||||||
AckWriter a = packetWriterFactory.createAckWriter(out);
|
AckWriter a = protocolWriterFactory.createAckWriter(out);
|
||||||
assertTrue(a.writeBatchId(ack));
|
assertTrue(a.writeBatchId(ack));
|
||||||
a.finish();
|
a.finish();
|
||||||
|
|
||||||
BatchWriter b = packetWriterFactory.createBatchWriter(out);
|
BatchWriter b = protocolWriterFactory.createBatchWriter(out);
|
||||||
assertTrue(b.writeMessage(message.getBytes()));
|
assertTrue(b.writeMessage(message.getBytes()));
|
||||||
assertTrue(b.writeMessage(message1.getBytes()));
|
assertTrue(b.writeMessage(message1.getBytes()));
|
||||||
assertTrue(b.writeMessage(message2.getBytes()));
|
assertTrue(b.writeMessage(message2.getBytes()));
|
||||||
assertTrue(b.writeMessage(message3.getBytes()));
|
assertTrue(b.writeMessage(message3.getBytes()));
|
||||||
b.finish();
|
b.finish();
|
||||||
|
|
||||||
OfferWriter o = packetWriterFactory.createOfferWriter(out);
|
OfferWriter o = protocolWriterFactory.createOfferWriter(out);
|
||||||
assertTrue(o.writeMessageId(message.getId()));
|
assertTrue(o.writeMessageId(message.getId()));
|
||||||
assertTrue(o.writeMessageId(message1.getId()));
|
assertTrue(o.writeMessageId(message1.getId()));
|
||||||
assertTrue(o.writeMessageId(message2.getId()));
|
assertTrue(o.writeMessageId(message2.getId()));
|
||||||
assertTrue(o.writeMessageId(message3.getId()));
|
assertTrue(o.writeMessageId(message3.getId()));
|
||||||
o.finish();
|
o.finish();
|
||||||
|
|
||||||
RequestWriter r = packetWriterFactory.createRequestWriter(out);
|
RequestWriter r = protocolWriterFactory.createRequestWriter(out);
|
||||||
BitSet requested = new BitSet(4);
|
BitSet requested = new BitSet(4);
|
||||||
requested.set(1);
|
requested.set(1);
|
||||||
requested.set(3);
|
requested.set(3);
|
||||||
r.writeBitmap(requested, 4);
|
r.writeBitmap(requested, 4);
|
||||||
|
|
||||||
SubscriptionWriter s =
|
SubscriptionWriter s =
|
||||||
packetWriterFactory.createSubscriptionWriter(out);
|
protocolWriterFactory.createSubscriptionWriter(out);
|
||||||
// Use a LinkedHashMap for predictable iteration order
|
// Use a LinkedHashMap for predictable iteration order
|
||||||
Map<Group, Long> subs = new LinkedHashMap<Group, Long>();
|
Map<Group, Long> subs = new LinkedHashMap<Group, Long>();
|
||||||
subs.put(group, 0L);
|
subs.put(group, 0L);
|
||||||
subs.put(group1, 0L);
|
subs.put(group1, 0L);
|
||||||
s.writeSubscriptions(subs);
|
s.writeSubscriptions(subs);
|
||||||
|
|
||||||
TransportWriter t = packetWriterFactory.createTransportWriter(out);
|
TransportWriter t = protocolWriterFactory.createTransportWriter(out);
|
||||||
t.writeTransports(transports);
|
t.writeTransports(transports);
|
||||||
|
|
||||||
out.close();
|
out.close();
|
||||||
|
|||||||
30
test/net/sf/briar/transport/TagDecoderTest.java
Normal file
30
test/net/sf/briar/transport/TagDecoderTest.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package net.sf.briar.transport;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import net.sf.briar.util.StringUtils;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TagDecoderTest extends TestCase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadUint16() {
|
||||||
|
byte[] b = StringUtils.fromHexString("000000");
|
||||||
|
assertEquals(0, TagDecoder.readUint16(b, 1));
|
||||||
|
b = StringUtils.fromHexString("000001");
|
||||||
|
assertEquals(1, TagDecoder.readUint16(b, 1));
|
||||||
|
b = StringUtils.fromHexString("00FFFF");
|
||||||
|
assertEquals(65535, TagDecoder.readUint16(b, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadUint32() {
|
||||||
|
byte[] b = StringUtils.fromHexString("0000000000");
|
||||||
|
assertEquals(0L, TagDecoder.readUint32(b, 1));
|
||||||
|
b = StringUtils.fromHexString("0000000001");
|
||||||
|
assertEquals(1L, TagDecoder.readUint32(b, 1));
|
||||||
|
b = StringUtils.fromHexString("00FFFFFFFF");
|
||||||
|
assertEquals(4294967295L, TagDecoder.readUint32(b, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ import junit.framework.TestCase;
|
|||||||
public class TagEncoderTest extends TestCase {
|
public class TagEncoderTest extends TestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteUint16() throws Exception {
|
public void testWriteUint16() {
|
||||||
byte[] b = new byte[3];
|
byte[] b = new byte[3];
|
||||||
TagEncoder.writeUint16(0, b, 1);
|
TagEncoder.writeUint16(0, b, 1);
|
||||||
assertEquals("000000", StringUtils.toHexString(b));
|
assertEquals("000000", StringUtils.toHexString(b));
|
||||||
@@ -20,7 +20,7 @@ public class TagEncoderTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteUint32() throws Exception {
|
public void testWriteUint32() {
|
||||||
byte[] b = new byte[5];
|
byte[] b = new byte[5];
|
||||||
TagEncoder.writeUint32(0L, b, 1);
|
TagEncoder.writeUint32(0L, b, 1);
|
||||||
assertEquals("0000000000", StringUtils.toHexString(b));
|
assertEquals("0000000000", StringUtils.toHexString(b));
|
||||||
|
|||||||
Reference in New Issue
Block a user