mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Builders for incoming and outgoing headers and batches. The protocol and serial components can now be used to serialise, sign, deserialise and verify real bundles (except for message parsing).
This commit is contained in:
@@ -1,15 +1,15 @@
|
|||||||
package net.sf.briar.api.db;
|
package net.sf.briar.api.db;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SignatureException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.sf.briar.api.ContactId;
|
import net.sf.briar.api.ContactId;
|
||||||
import net.sf.briar.api.Rating;
|
import net.sf.briar.api.Rating;
|
||||||
import net.sf.briar.api.protocol.AuthorId;
|
import net.sf.briar.api.protocol.AuthorId;
|
||||||
import net.sf.briar.api.protocol.Bundle;
|
import net.sf.briar.api.protocol.BundleReader;
|
||||||
import net.sf.briar.api.protocol.BundleBuilder;
|
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.Message;
|
import net.sf.briar.api.protocol.Message;
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ public interface DatabaseComponent {
|
|||||||
* Generates a bundle of acknowledgements, subscriptions, and batches of
|
* Generates a bundle of acknowledgements, subscriptions, and batches of
|
||||||
* messages for the given contact.
|
* messages for the given contact.
|
||||||
*/
|
*/
|
||||||
Bundle generateBundle(ContactId c, BundleBuilder bundleBuilder) throws DbException, IOException, SignatureException;
|
void generateBundle(ContactId c, BundleWriter bundleBuilder) throws DbException, IOException, GeneralSecurityException;
|
||||||
|
|
||||||
/** Returns the IDs of all contacts. */
|
/** Returns the IDs of all contacts. */
|
||||||
Set<ContactId> getContacts() throws DbException;
|
Set<ContactId> getContacts() throws DbException;
|
||||||
@@ -73,7 +73,7 @@ public interface DatabaseComponent {
|
|||||||
* messages received from the given contact. Some or all of the messages
|
* messages received from the given contact. Some or all of the messages
|
||||||
* in the bundle may be stored.
|
* in the bundle may be stored.
|
||||||
*/
|
*/
|
||||||
void receiveBundle(ContactId c, Bundle b) throws DbException, IOException, SignatureException;
|
void receiveBundle(ContactId c, BundleReader b) throws DbException, IOException, GeneralSecurityException;
|
||||||
|
|
||||||
/** Removes a contact (and all associated state) from the database. */
|
/** Removes a contact (and all associated state) from the database. */
|
||||||
void removeContact(ContactId c) throws DbException;
|
void removeContact(ContactId c) throws DbException;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package net.sf.briar.api.protocol;
|
package net.sf.briar.api.protocol;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
|
|
||||||
public interface BatchBuilder {
|
public interface BatchBuilder {
|
||||||
@@ -11,5 +13,5 @@ public interface BatchBuilder {
|
|||||||
void setSignature(byte[] sig);
|
void setSignature(byte[] sig);
|
||||||
|
|
||||||
/** Builds and returns the batch. */
|
/** Builds and returns the batch. */
|
||||||
Batch build() throws SignatureException;
|
Batch build() throws IOException, SignatureException, InvalidKeyException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
package net.sf.briar.api.protocol;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.SignatureException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A bundle of acknowledgements, subscriptions, transport details and batches.
|
|
||||||
*/
|
|
||||||
public interface Bundle {
|
|
||||||
|
|
||||||
/** Returns the size of the serialised bundle in bytes. */
|
|
||||||
long getSize() throws IOException;
|
|
||||||
|
|
||||||
/** Returns the bundle's header. */
|
|
||||||
Header getHeader() throws IOException, SignatureException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the next batch of messages, or null if there are no more batches.
|
|
||||||
*/
|
|
||||||
Batch getNextBatch() throws IOException, SignatureException;
|
|
||||||
}
|
|
||||||
25
api/net/sf/briar/api/protocol/BundleReader.java
Normal file
25
api/net/sf/briar/api/protocol/BundleReader.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package net.sf.briar.api.protocol;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for reading a bundle of acknowledgements, subscriptions,
|
||||||
|
* transport details and batches.
|
||||||
|
*/
|
||||||
|
public interface BundleReader {
|
||||||
|
|
||||||
|
/** Returns the size of the serialised bundle in bytes. */
|
||||||
|
long getSize() throws IOException;
|
||||||
|
|
||||||
|
/** Returns the bundle's header. */
|
||||||
|
Header getHeader() throws IOException, GeneralSecurityException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next batch of messages, or null if there are no more batches.
|
||||||
|
*/
|
||||||
|
Batch getNextBatch() throws IOException, GeneralSecurityException;
|
||||||
|
|
||||||
|
/** Finishes reading the bundle. */
|
||||||
|
void close() throws IOException;
|
||||||
|
}
|
||||||
@@ -2,7 +2,11 @@ package net.sf.briar.api.protocol;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public interface BundleBuilder {
|
/**
|
||||||
|
* An interface for writing a bundle of acknowledgements, subscriptions,
|
||||||
|
* transport details and batches.
|
||||||
|
*/
|
||||||
|
public interface BundleWriter {
|
||||||
|
|
||||||
/** Returns the bundle's capacity in bytes. */
|
/** Returns the bundle's capacity in bytes. */
|
||||||
long getCapacity() throws IOException;
|
long getCapacity() throws IOException;
|
||||||
@@ -13,6 +17,6 @@ public interface BundleBuilder {
|
|||||||
/** Adds a batch of messages to the bundle. */
|
/** Adds a batch of messages to the bundle. */
|
||||||
void addBatch(Batch b) throws IOException;
|
void addBatch(Batch b) throws IOException;
|
||||||
|
|
||||||
/** Builds and returns the bundle. */
|
/** Finishes writing the bundle. */
|
||||||
Bundle build() throws IOException;
|
void close() throws IOException;
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,24 @@
|
|||||||
package net.sf.briar.api.protocol;
|
package net.sf.briar.api.protocol;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public interface HeaderBuilder {
|
public interface HeaderBuilder {
|
||||||
|
|
||||||
/** Adds acknowledgements to the header. */
|
/** Adds acknowledgements to the header. */
|
||||||
void addAcks(Set<BatchId> acks) throws IOException;
|
void addAcks(Iterable<BatchId> acks);
|
||||||
|
|
||||||
/** Adds subscriptions to the header. */
|
/** Adds subscriptions to the header. */
|
||||||
void addSubscriptions(Set<GroupId> subs) throws IOException;
|
void addSubscriptions(Iterable<GroupId> subs);
|
||||||
|
|
||||||
/** Adds transport details to the header. */
|
/** Adds transport details to the header. */
|
||||||
void addTransports(Map<String, String> transports) throws IOException;
|
void addTransports(Map<String, String> transports);
|
||||||
|
|
||||||
/** Sets the sender's signature over the contents of the header. */
|
/** Sets the sender's signature over the contents of the header. */
|
||||||
void setSignature(byte[] sig) throws IOException;
|
void setSignature(byte[] sig);
|
||||||
|
|
||||||
/** Builds and returns the header. */
|
/** Builds and returns the header. */
|
||||||
Header build() throws SignatureException;
|
Header build() throws IOException, SignatureException, InvalidKeyException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package net.sf.briar.api.protocol;
|
package net.sf.briar.api.protocol;
|
||||||
|
|
||||||
public interface Message {
|
import net.sf.briar.api.serial.Raw;
|
||||||
|
|
||||||
|
public interface Message extends Raw {
|
||||||
|
|
||||||
/** Returns the message's unique identifier. */
|
/** Returns the message's unique identifier. */
|
||||||
MessageId getId();
|
MessageId getId();
|
||||||
@@ -22,7 +24,4 @@ public interface Message {
|
|||||||
|
|
||||||
/** Returns the size of the message in bytes. */
|
/** Returns the size of the message in bytes. */
|
||||||
int getSize();
|
int getSize();
|
||||||
|
|
||||||
/** Returns the message in wire format. */
|
|
||||||
byte[] getBody();
|
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ public interface Reader {
|
|||||||
boolean eof() throws IOException;
|
boolean eof() throws IOException;
|
||||||
void setReadLimit(long limit);
|
void setReadLimit(long limit);
|
||||||
void resetReadLimit();
|
void resetReadLimit();
|
||||||
|
void close() throws IOException;
|
||||||
|
|
||||||
boolean hasBoolean() throws IOException;
|
boolean hasBoolean() throws IOException;
|
||||||
boolean readBoolean() throws IOException;
|
boolean readBoolean() throws IOException;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import java.util.Map;
|
|||||||
|
|
||||||
public interface Writer {
|
public interface Writer {
|
||||||
|
|
||||||
|
void close() throws IOException;
|
||||||
|
|
||||||
void writeBoolean(boolean b) throws IOException;
|
void writeBoolean(boolean b) throws IOException;
|
||||||
|
|
||||||
void writeUint7(byte b) throws IOException;
|
void writeUint7(byte b) throws IOException;
|
||||||
@@ -31,6 +33,4 @@ public interface Writer {
|
|||||||
void writeMapEnd() throws IOException;
|
void writeMapEnd() throws IOException;
|
||||||
|
|
||||||
void writeNull() throws IOException;
|
void writeNull() throws IOException;
|
||||||
|
|
||||||
void close() throws IOException;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -467,7 +467,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setBytes(4, m.getAuthor().getBytes());
|
ps.setBytes(4, m.getAuthor().getBytes());
|
||||||
ps.setLong(5, m.getTimestamp());
|
ps.setLong(5, m.getTimestamp());
|
||||||
ps.setInt(6, m.getSize());
|
ps.setInt(6, m.getSize());
|
||||||
ps.setBlob(7, new ByteArrayInputStream(m.getBody()));
|
ps.setBlob(7, new ByteArrayInputStream(m.getBytes()));
|
||||||
ps.setInt(8, 0);
|
ps.setInt(8, 0);
|
||||||
int rowsAffected = ps.executeUpdate();
|
int rowsAffected = ps.executeUpdate();
|
||||||
assert rowsAffected == 1;
|
assert rowsAffected == 1;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.sf.briar.db;
|
package net.sf.briar.db;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -18,8 +19,9 @@ import net.sf.briar.api.protocol.AuthorId;
|
|||||||
import net.sf.briar.api.protocol.Batch;
|
import net.sf.briar.api.protocol.Batch;
|
||||||
import net.sf.briar.api.protocol.BatchBuilder;
|
import net.sf.briar.api.protocol.BatchBuilder;
|
||||||
import net.sf.briar.api.protocol.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
import net.sf.briar.api.protocol.Bundle;
|
import net.sf.briar.api.protocol.BundleId;
|
||||||
import net.sf.briar.api.protocol.BundleBuilder;
|
import net.sf.briar.api.protocol.BundleReader;
|
||||||
|
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.Header;
|
import net.sf.briar.api.protocol.Header;
|
||||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||||
@@ -190,8 +192,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bundle generateBundle(ContactId c, BundleBuilder b)
|
public void generateBundle(ContactId c, BundleWriter b) throws DbException,
|
||||||
throws DbException, IOException, SignatureException {
|
IOException, GeneralSecurityException {
|
||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c);
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c);
|
||||||
HeaderBuilder h;
|
HeaderBuilder h;
|
||||||
// Add acks
|
// Add acks
|
||||||
@@ -280,15 +282,13 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
// more messages trickling in but we can't wait forever
|
// more messages trickling in but we can't wait forever
|
||||||
if(size * 2 < Batch.MAX_SIZE) break;
|
if(size * 2 < Batch.MAX_SIZE) break;
|
||||||
}
|
}
|
||||||
Bundle bundle = b.build();
|
b.close();
|
||||||
if(LOG.isLoggable(Level.FINE))
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Bundle generated");
|
||||||
LOG.fine("Bundle generated, " + bundle.getSize() + " bytes");
|
|
||||||
System.gc();
|
System.gc();
|
||||||
return bundle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Batch fillBatch(ContactId c, long capacity) throws DbException,
|
private Batch fillBatch(ContactId c, long capacity) throws DbException,
|
||||||
SignatureException {
|
IOException, GeneralSecurityException {
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
if(!containsContact(c)) throw new NoSuchContactException();
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
@@ -441,8 +441,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void receiveBundle(ContactId c, Bundle b) throws DbException,
|
public void receiveBundle(ContactId c, BundleReader b) throws DbException,
|
||||||
IOException, SignatureException {
|
IOException, GeneralSecurityException {
|
||||||
if(LOG.isLoggable(Level.FINE))
|
if(LOG.isLoggable(Level.FINE))
|
||||||
LOG.fine("Received bundle from " + c + ", "
|
LOG.fine("Received bundle from " + c + ", "
|
||||||
+ b.getSize() + " bytes");
|
+ b.getSize() + " bytes");
|
||||||
@@ -529,52 +529,64 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
// Store the messages
|
// Store the messages
|
||||||
int batches = 0;
|
int batches = 0;
|
||||||
for(Batch batch = b.getNextBatch(); batch != null; batch = b.getNextBatch()) {
|
Batch batch = null;
|
||||||
|
while((batch = b.getNextBatch()) != null) {
|
||||||
|
storeBatch(c, batch);
|
||||||
batches++;
|
batches++;
|
||||||
waitForPermissionToWrite();
|
|
||||||
contactLock.readLock().lock();
|
|
||||||
try {
|
|
||||||
if(!containsContact(c)) throw new NoSuchContactException();
|
|
||||||
messageLock.writeLock().lock();
|
|
||||||
try {
|
|
||||||
messageStatusLock.writeLock().lock();
|
|
||||||
try {
|
|
||||||
subscriptionLock.readLock().lock();
|
|
||||||
try {
|
|
||||||
Txn txn = db.startTransaction();
|
|
||||||
try {
|
|
||||||
int received = 0, stored = 0;
|
|
||||||
for(Message m : batch.getMessages()) {
|
|
||||||
received++;
|
|
||||||
GroupId g = m.getGroup();
|
|
||||||
if(db.containsSubscription(txn, g)) {
|
|
||||||
if(storeMessage(txn, m, c)) stored++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(LOG.isLoggable(Level.FINE))
|
|
||||||
LOG.fine("Received " + received
|
|
||||||
+ " messages, stored " + stored);
|
|
||||||
db.addBatchToAck(txn, c, batch.getId());
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
} catch(DbException e) {
|
|
||||||
db.abortTransaction(txn);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
subscriptionLock.readLock().unlock();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
messageStatusLock.writeLock().unlock();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
messageLock.writeLock().unlock();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
contactLock.readLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(LOG.isLoggable(Level.FINE))
|
if(LOG.isLoggable(Level.FINE))
|
||||||
LOG.fine("Received " + batches + " batches");
|
LOG.fine("Received " + batches + " batches");
|
||||||
|
b.close();
|
||||||
|
retransmitLostBatches(c, h.getId());
|
||||||
|
System.gc();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void storeBatch(ContactId c, Batch b) throws DbException {
|
||||||
|
waitForPermissionToWrite();
|
||||||
|
contactLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
|
messageLock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
messageStatusLock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
subscriptionLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
Txn txn = db.startTransaction();
|
||||||
|
try {
|
||||||
|
int received = 0, stored = 0;
|
||||||
|
for(Message m : b.getMessages()) {
|
||||||
|
received++;
|
||||||
|
GroupId g = m.getGroup();
|
||||||
|
if(db.containsSubscription(txn, g)) {
|
||||||
|
if(storeMessage(txn, m, c)) stored++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(LOG.isLoggable(Level.FINE))
|
||||||
|
LOG.fine("Received " + received
|
||||||
|
+ " messages, stored " + stored);
|
||||||
|
db.addBatchToAck(txn, c, b.getId());
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
subscriptionLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
messageStatusLock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
messageLock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
contactLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void retransmitLostBatches(ContactId c, BundleId b)
|
||||||
|
throws DbException {
|
||||||
// Find any lost batches that need to be retransmitted
|
// Find any lost batches that need to be retransmitted
|
||||||
Set<BatchId> lost;
|
Set<BatchId> lost;
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
@@ -586,7 +598,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
try {
|
try {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
lost = db.addReceivedBundle(txn, c, h.getId());
|
lost = db.addReceivedBundle(txn, c, b);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
db.abortTransaction(txn);
|
db.abortTransaction(txn);
|
||||||
@@ -629,7 +641,6 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
contactLock.readLock().unlock();
|
contactLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.gc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeContact(ContactId c) throws DbException {
|
public void removeContact(ContactId c) throws DbException {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.sf.briar.db;
|
package net.sf.briar.db;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -17,8 +18,9 @@ import net.sf.briar.api.protocol.AuthorId;
|
|||||||
import net.sf.briar.api.protocol.Batch;
|
import net.sf.briar.api.protocol.Batch;
|
||||||
import net.sf.briar.api.protocol.BatchBuilder;
|
import net.sf.briar.api.protocol.BatchBuilder;
|
||||||
import net.sf.briar.api.protocol.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
import net.sf.briar.api.protocol.Bundle;
|
import net.sf.briar.api.protocol.BundleId;
|
||||||
import net.sf.briar.api.protocol.BundleBuilder;
|
import net.sf.briar.api.protocol.BundleReader;
|
||||||
|
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.Header;
|
import net.sf.briar.api.protocol.Header;
|
||||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||||
@@ -143,8 +145,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Bundle generateBundle(ContactId c, BundleBuilder b)
|
public void generateBundle(ContactId c, BundleWriter b) throws DbException,
|
||||||
throws DbException, IOException, SignatureException {
|
IOException, GeneralSecurityException {
|
||||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c);
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c);
|
||||||
HeaderBuilder h;
|
HeaderBuilder h;
|
||||||
// Add acks
|
// Add acks
|
||||||
@@ -215,15 +217,13 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
// more messages trickling in but we can't wait forever
|
// more messages trickling in but we can't wait forever
|
||||||
if(size * 2 < Batch.MAX_SIZE) break;
|
if(size * 2 < Batch.MAX_SIZE) break;
|
||||||
}
|
}
|
||||||
Bundle bundle = b.build();
|
b.close();
|
||||||
if(LOG.isLoggable(Level.FINE))
|
if(LOG.isLoggable(Level.FINE)) LOG.fine("Bundle generated");
|
||||||
LOG.fine("Bundle generated, " + bundle.getSize() + " bytes");
|
|
||||||
System.gc();
|
System.gc();
|
||||||
return bundle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Batch fillBatch(ContactId c, long capacity) throws DbException,
|
private Batch fillBatch(ContactId c, long capacity) throws DbException,
|
||||||
SignatureException {
|
IOException, GeneralSecurityException {
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
if(!containsContact(c)) throw new NoSuchContactException();
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
synchronized(messageLock) {
|
synchronized(messageLock) {
|
||||||
@@ -335,8 +335,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void receiveBundle(ContactId c, Bundle b) throws DbException,
|
public void receiveBundle(ContactId c, BundleReader b) throws DbException,
|
||||||
IOException, SignatureException {
|
IOException, GeneralSecurityException {
|
||||||
if(LOG.isLoggable(Level.FINE))
|
if(LOG.isLoggable(Level.FINE))
|
||||||
LOG.fine("Received bundle from " + c + ", "
|
LOG.fine("Received bundle from " + c + ", "
|
||||||
+ b.getSize() + " bytes");
|
+ b.getSize() + " bytes");
|
||||||
@@ -402,40 +402,52 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
// Store the messages
|
// Store the messages
|
||||||
int batches = 0;
|
int batches = 0;
|
||||||
for(Batch batch = b.getNextBatch(); batch != null; batch = b.getNextBatch()) {
|
Batch batch = null;
|
||||||
|
while((batch = b.getNextBatch()) != null) {
|
||||||
|
storeBatch(c, batch);
|
||||||
batches++;
|
batches++;
|
||||||
waitForPermissionToWrite();
|
}
|
||||||
synchronized(contactLock) {
|
if(LOG.isLoggable(Level.FINE))
|
||||||
if(!containsContact(c)) throw new NoSuchContactException();
|
LOG.fine("Received " + batches + " batches");
|
||||||
synchronized(messageLock) {
|
b.close();
|
||||||
synchronized(messageStatusLock) {
|
retransmitLostBatches(c, h.getId());
|
||||||
synchronized(subscriptionLock) {
|
System.gc();
|
||||||
Txn txn = db.startTransaction();
|
}
|
||||||
try {
|
|
||||||
int received = 0, stored = 0;
|
private void storeBatch(ContactId c, Batch b) throws DbException {
|
||||||
for(Message m : batch.getMessages()) {
|
waitForPermissionToWrite();
|
||||||
received++;
|
synchronized(contactLock) {
|
||||||
GroupId g = m.getGroup();
|
if(!containsContact(c)) throw new NoSuchContactException();
|
||||||
if(db.containsSubscription(txn, g)) {
|
synchronized(messageLock) {
|
||||||
if(storeMessage(txn, m, c)) stored++;
|
synchronized(messageStatusLock) {
|
||||||
}
|
synchronized(subscriptionLock) {
|
||||||
|
Txn txn = db.startTransaction();
|
||||||
|
try {
|
||||||
|
int received = 0, stored = 0;
|
||||||
|
for(Message m : b.getMessages()) {
|
||||||
|
received++;
|
||||||
|
GroupId g = m.getGroup();
|
||||||
|
if(db.containsSubscription(txn, g)) {
|
||||||
|
if(storeMessage(txn, m, c)) stored++;
|
||||||
}
|
}
|
||||||
if(LOG.isLoggable(Level.FINE))
|
|
||||||
LOG.fine("Received " + received
|
|
||||||
+ " messages, stored " + stored);
|
|
||||||
db.addBatchToAck(txn, c, batch.getId());
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
} catch(DbException e) {
|
|
||||||
db.abortTransaction(txn);
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
|
if(LOG.isLoggable(Level.FINE))
|
||||||
|
LOG.fine("Received " + received
|
||||||
|
+ " messages, stored " + stored);
|
||||||
|
db.addBatchToAck(txn, c, b.getId());
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} catch(DbException e) {
|
||||||
|
db.abortTransaction(txn);
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(LOG.isLoggable(Level.FINE))
|
}
|
||||||
LOG.fine("Received " + batches + " batches");
|
|
||||||
|
private void retransmitLostBatches(ContactId c, BundleId b)
|
||||||
|
throws DbException {
|
||||||
// Find any lost batches that need to be retransmitted
|
// Find any lost batches that need to be retransmitted
|
||||||
Set<BatchId> lost;
|
Set<BatchId> lost;
|
||||||
synchronized(contactLock) {
|
synchronized(contactLock) {
|
||||||
@@ -444,7 +456,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
synchronized(messageStatusLock) {
|
synchronized(messageStatusLock) {
|
||||||
Txn txn = db.startTransaction();
|
Txn txn = db.startTransaction();
|
||||||
try {
|
try {
|
||||||
lost = db.addReceivedBundle(txn, c, h.getId());
|
lost = db.addReceivedBundle(txn, c, b);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
db.abortTransaction(txn);
|
db.abortTransaction(txn);
|
||||||
@@ -472,7 +484,6 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.gc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeContact(ContactId c) throws DbException {
|
public void removeContact(ContactId c) throws DbException {
|
||||||
|
|||||||
44
components/net/sf/briar/protocol/BatchBuilderImpl.java
Normal file
44
components/net/sf/briar/protocol/BatchBuilderImpl.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package net.sf.briar.protocol;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.Signature;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.sf.briar.api.protocol.BatchBuilder;
|
||||||
|
import net.sf.briar.api.protocol.Message;
|
||||||
|
import net.sf.briar.api.serial.Writer;
|
||||||
|
import net.sf.briar.api.serial.WriterFactory;
|
||||||
|
|
||||||
|
abstract class BatchBuilderImpl implements BatchBuilder {
|
||||||
|
|
||||||
|
protected final List<Message> messages = new ArrayList<Message>();
|
||||||
|
protected final KeyPair keyPair;
|
||||||
|
protected final Signature signature;
|
||||||
|
protected final MessageDigest messageDigest;
|
||||||
|
|
||||||
|
private final WriterFactory writerFactory;
|
||||||
|
|
||||||
|
protected BatchBuilderImpl(KeyPair keyPair, Signature signature,
|
||||||
|
MessageDigest messageDigest, WriterFactory writerFactory) {
|
||||||
|
this.keyPair = keyPair;
|
||||||
|
this.signature = signature;
|
||||||
|
this.messageDigest = messageDigest;
|
||||||
|
this.writerFactory = writerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMessage(Message m) {
|
||||||
|
messages.add(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] getSignableRepresentation() throws IOException {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
Writer w = writerFactory.createWriter(out);
|
||||||
|
w.writeList(messages);
|
||||||
|
w.close();
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package net.sf.briar.protocol;
|
package net.sf.briar.protocol;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SignatureException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -10,7 +10,7 @@ import java.util.Set;
|
|||||||
import net.sf.briar.api.protocol.Batch;
|
import net.sf.briar.api.protocol.Batch;
|
||||||
import net.sf.briar.api.protocol.BatchBuilder;
|
import net.sf.briar.api.protocol.BatchBuilder;
|
||||||
import net.sf.briar.api.protocol.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
import net.sf.briar.api.protocol.Bundle;
|
import net.sf.briar.api.protocol.BundleReader;
|
||||||
import net.sf.briar.api.protocol.GroupId;
|
import net.sf.briar.api.protocol.GroupId;
|
||||||
import net.sf.briar.api.protocol.Header;
|
import net.sf.briar.api.protocol.Header;
|
||||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||||
@@ -24,26 +24,32 @@ import net.sf.briar.api.serial.Reader;
|
|||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
/** A bundle that deserialises its contents on demand using a reader. */
|
/** A bundle that deserialises its contents on demand using a reader. */
|
||||||
abstract class BundleReader implements Bundle {
|
class BundleReaderImpl implements BundleReader {
|
||||||
|
|
||||||
private static enum State { START, FIRST_BATCH, MORE_BATCHES, END };
|
private static enum State { START, FIRST_BATCH, MORE_BATCHES, END };
|
||||||
|
|
||||||
private final Reader r;
|
private final Reader r;
|
||||||
|
private final long size;
|
||||||
private final MessageParser messageParser;
|
private final MessageParser messageParser;
|
||||||
private final Provider<HeaderBuilder> headerBuilderProvider;
|
private final Provider<HeaderBuilder> headerBuilderProvider;
|
||||||
private final Provider<BatchBuilder> batchBuilderProvider;
|
private final Provider<BatchBuilder> batchBuilderProvider;
|
||||||
private State state = State.START;
|
private State state = State.START;
|
||||||
|
|
||||||
BundleReader(Reader r, MessageParser messageParser,
|
BundleReaderImpl(Reader r, long size, MessageParser messageParser,
|
||||||
Provider<HeaderBuilder> headerBuilderProvider,
|
Provider<HeaderBuilder> headerBuilderProvider,
|
||||||
Provider<BatchBuilder> batchBuilderProvider) {
|
Provider<BatchBuilder> batchBuilderProvider) {
|
||||||
this.r = r;
|
this.r = r;
|
||||||
|
this.size = size;
|
||||||
this.messageParser = messageParser;
|
this.messageParser = messageParser;
|
||||||
this.headerBuilderProvider = headerBuilderProvider;
|
this.headerBuilderProvider = headerBuilderProvider;
|
||||||
this.batchBuilderProvider = batchBuilderProvider;
|
this.batchBuilderProvider = batchBuilderProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Header getHeader() throws IOException, SignatureException {
|
public long getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Header getHeader() throws IOException, GeneralSecurityException {
|
||||||
if(state != State.START) throw new IllegalStateException();
|
if(state != State.START) throw new IllegalStateException();
|
||||||
r.setReadLimit(Header.MAX_SIZE);
|
r.setReadLimit(Header.MAX_SIZE);
|
||||||
Set<BatchId> acks = new HashSet<BatchId>();
|
Set<BatchId> acks = new HashSet<BatchId>();
|
||||||
@@ -69,7 +75,7 @@ abstract class BundleReader implements Bundle {
|
|||||||
return h.build();
|
return h.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Batch getNextBatch() throws IOException, SignatureException {
|
public Batch getNextBatch() throws IOException, GeneralSecurityException {
|
||||||
if(state == State.FIRST_BATCH) {
|
if(state == State.FIRST_BATCH) {
|
||||||
r.readListStart();
|
r.readListStart();
|
||||||
state = State.MORE_BATCHES;
|
state = State.MORE_BATCHES;
|
||||||
@@ -91,4 +97,8 @@ abstract class BundleReader implements Bundle {
|
|||||||
b.setSignature(sig);
|
b.setSignature(sig);
|
||||||
return b.build();
|
return b.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
r.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,14 +4,14 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import net.sf.briar.api.protocol.Batch;
|
import net.sf.briar.api.protocol.Batch;
|
||||||
import net.sf.briar.api.protocol.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
import net.sf.briar.api.protocol.BundleBuilder;
|
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.Header;
|
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.serial.Writer;
|
import net.sf.briar.api.serial.Writer;
|
||||||
|
|
||||||
/** A bundle builder that serialises its contents using a writer. */
|
/** A bundle builder that serialises its contents using a writer. */
|
||||||
abstract class BundleWriter implements BundleBuilder {
|
class BundleWriterImpl implements BundleWriter {
|
||||||
|
|
||||||
private static enum State { START, FIRST_BATCH, MORE_BATCHES, END };
|
private static enum State { START, FIRST_BATCH, MORE_BATCHES, END };
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ abstract class BundleWriter implements BundleBuilder {
|
|||||||
private final long capacity;
|
private final long capacity;
|
||||||
private State state = State.START;
|
private State state = State.START;
|
||||||
|
|
||||||
BundleWriter(Writer w, long capacity) {
|
BundleWriterImpl(Writer w, long capacity) {
|
||||||
this.w = w;
|
this.w = w;
|
||||||
this.capacity = capacity;
|
this.capacity = capacity;
|
||||||
}
|
}
|
||||||
@@ -48,12 +48,12 @@ abstract class BundleWriter implements BundleBuilder {
|
|||||||
}
|
}
|
||||||
if(state != State.MORE_BATCHES) throw new IllegalStateException();
|
if(state != State.MORE_BATCHES) throw new IllegalStateException();
|
||||||
w.writeListStart();
|
w.writeListStart();
|
||||||
for(Message m : b.getMessages()) w.writeRaw(m.getBody());
|
for(Message m : b.getMessages()) w.writeRaw(m.getBytes());
|
||||||
w.writeListEnd();
|
w.writeListEnd();
|
||||||
w.writeRaw(b.getSignature());
|
w.writeRaw(b.getSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
void close() throws IOException {
|
public void close() throws IOException {
|
||||||
if(state == State.FIRST_BATCH) {
|
if(state == State.FIRST_BATCH) {
|
||||||
w.writeListStart();
|
w.writeListStart();
|
||||||
state = State.MORE_BATCHES;
|
state = State.MORE_BATCHES;
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package net.sf.briar.protocol;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import net.sf.briar.api.protocol.BatchBuilder;
|
|
||||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
|
||||||
import net.sf.briar.api.protocol.MessageParser;
|
|
||||||
import net.sf.briar.api.serial.ReaderFactory;
|
|
||||||
|
|
||||||
import com.google.inject.Provider;
|
|
||||||
|
|
||||||
class FileBundle extends BundleReader {
|
|
||||||
|
|
||||||
private final File file;
|
|
||||||
|
|
||||||
FileBundle(File file, ReaderFactory readerFactory,
|
|
||||||
MessageParser messageParser,
|
|
||||||
Provider<HeaderBuilder> headerBuilderProvider,
|
|
||||||
Provider<BatchBuilder> batchBuilderProvider) throws IOException {
|
|
||||||
super(readerFactory.createReader(new FileInputStream(file)),
|
|
||||||
messageParser, headerBuilderProvider, batchBuilderProvider);
|
|
||||||
this.file = file;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getSize() throws IOException {
|
|
||||||
return file.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package net.sf.briar.protocol;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import net.sf.briar.api.protocol.BatchBuilder;
|
|
||||||
import net.sf.briar.api.protocol.Bundle;
|
|
||||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
|
||||||
import net.sf.briar.api.protocol.MessageParser;
|
|
||||||
import net.sf.briar.api.serial.ReaderFactory;
|
|
||||||
import net.sf.briar.api.serial.WriterFactory;
|
|
||||||
|
|
||||||
import com.google.inject.Provider;
|
|
||||||
|
|
||||||
public class FileBundleBuilder extends BundleWriter {
|
|
||||||
|
|
||||||
private final File file;
|
|
||||||
private final ReaderFactory readerFactory;
|
|
||||||
private final MessageParser messageParser;
|
|
||||||
private final Provider<HeaderBuilder> headerBuilderProvider;
|
|
||||||
private final Provider<BatchBuilder> batchBuilderProvider;
|
|
||||||
|
|
||||||
FileBundleBuilder(File file, long capacity, WriterFactory writerFactory,
|
|
||||||
ReaderFactory readerFactory, MessageParser messageParser,
|
|
||||||
Provider<HeaderBuilder> headerBuilderProvider,
|
|
||||||
Provider<BatchBuilder> batchBuilderProvider) throws IOException {
|
|
||||||
super(writerFactory.createWriter(new FileOutputStream(file)), capacity);
|
|
||||||
this.file = file;
|
|
||||||
this.readerFactory = readerFactory;
|
|
||||||
this.messageParser = messageParser;
|
|
||||||
this.headerBuilderProvider = headerBuilderProvider;
|
|
||||||
this.batchBuilderProvider = batchBuilderProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bundle build() throws IOException {
|
|
||||||
super.close();
|
|
||||||
return new FileBundle(file, readerFactory, messageParser,
|
|
||||||
headerBuilderProvider, batchBuilderProvider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
63
components/net/sf/briar/protocol/HeaderBuilderImpl.java
Normal file
63
components/net/sf/briar/protocol/HeaderBuilderImpl.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package net.sf.briar.protocol;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.Signature;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
|
import net.sf.briar.api.protocol.GroupId;
|
||||||
|
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||||
|
import net.sf.briar.api.serial.Writer;
|
||||||
|
import net.sf.briar.api.serial.WriterFactory;
|
||||||
|
|
||||||
|
abstract class HeaderBuilderImpl implements HeaderBuilder {
|
||||||
|
|
||||||
|
protected final List<BatchId> acks = new ArrayList<BatchId>();
|
||||||
|
protected final List<GroupId> subs = new ArrayList<GroupId>();
|
||||||
|
protected final Map<String, String> transports =
|
||||||
|
new LinkedHashMap<String, String>();
|
||||||
|
|
||||||
|
protected final KeyPair keyPair;
|
||||||
|
protected final Signature signature;
|
||||||
|
protected final MessageDigest messageDigest;
|
||||||
|
|
||||||
|
private final WriterFactory writerFactory;
|
||||||
|
|
||||||
|
protected HeaderBuilderImpl(KeyPair keyPair, Signature signature,
|
||||||
|
MessageDigest messageDigest, WriterFactory writerFactory) {
|
||||||
|
this.keyPair = keyPair;
|
||||||
|
this.signature = signature;
|
||||||
|
this.messageDigest = messageDigest;
|
||||||
|
this.writerFactory = writerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAcks(Iterable<BatchId> acks) {
|
||||||
|
for(BatchId ack : acks) this.acks.add(ack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSubscriptions(Iterable<GroupId> subs) {
|
||||||
|
for(GroupId sub : subs) this.subs.add(sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTransports(Map<String, String> transports) {
|
||||||
|
for(String key : transports.keySet()) {
|
||||||
|
this.transports.put(key, transports.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected byte[] getSignableRepresentation() throws IOException {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
Writer w = writerFactory.createWriter(out);
|
||||||
|
w.writeList(acks);
|
||||||
|
w.writeList(subs);
|
||||||
|
w.writeMap(transports);
|
||||||
|
w.close();
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
40
components/net/sf/briar/protocol/IncomingBatchBuilder.java
Normal file
40
components/net/sf/briar/protocol/IncomingBatchBuilder.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package net.sf.briar.protocol;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.Signature;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
|
||||||
|
import net.sf.briar.api.protocol.Batch;
|
||||||
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
|
import net.sf.briar.api.serial.WriterFactory;
|
||||||
|
|
||||||
|
public class IncomingBatchBuilder extends BatchBuilderImpl {
|
||||||
|
|
||||||
|
IncomingBatchBuilder(KeyPair keyPair, Signature signature,
|
||||||
|
MessageDigest messageDigest, WriterFactory writerFactory) {
|
||||||
|
super(keyPair, signature, messageDigest, writerFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] sig = null;
|
||||||
|
|
||||||
|
public void setSignature(byte[] sig) {
|
||||||
|
this.sig = sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Batch build() throws IOException, SignatureException,
|
||||||
|
InvalidKeyException {
|
||||||
|
if(sig == null) throw new IllegalStateException();
|
||||||
|
byte[] raw = getSignableRepresentation();
|
||||||
|
signature.initVerify(keyPair.getPublic());
|
||||||
|
signature.update(raw);
|
||||||
|
signature.verify(sig);
|
||||||
|
messageDigest.reset();
|
||||||
|
messageDigest.update(raw);
|
||||||
|
messageDigest.update(sig);
|
||||||
|
byte[] hash = messageDigest.digest();
|
||||||
|
return new BatchImpl(new BatchId(hash), raw.length, messages, sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
47
components/net/sf/briar/protocol/IncomingHeaderBuilder.java
Normal file
47
components/net/sf/briar/protocol/IncomingHeaderBuilder.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package net.sf.briar.protocol;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.Signature;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
|
import net.sf.briar.api.protocol.BundleId;
|
||||||
|
import net.sf.briar.api.protocol.GroupId;
|
||||||
|
import net.sf.briar.api.protocol.Header;
|
||||||
|
import net.sf.briar.api.serial.WriterFactory;
|
||||||
|
|
||||||
|
class IncomingHeaderBuilder extends HeaderBuilderImpl {
|
||||||
|
|
||||||
|
private byte[] sig = null;
|
||||||
|
|
||||||
|
IncomingHeaderBuilder(KeyPair keyPair, Signature signature,
|
||||||
|
MessageDigest messageDigest, WriterFactory writerFactory) {
|
||||||
|
super(keyPair, signature, messageDigest, writerFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignature(byte[] sig) {
|
||||||
|
this.sig = sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Header build() throws IOException, SignatureException,
|
||||||
|
InvalidKeyException {
|
||||||
|
if(sig == null) throw new IllegalStateException();
|
||||||
|
byte[] raw = getSignableRepresentation();
|
||||||
|
signature.initVerify(keyPair.getPublic());
|
||||||
|
signature.update(raw);
|
||||||
|
signature.verify(sig);
|
||||||
|
messageDigest.reset();
|
||||||
|
messageDigest.update(raw);
|
||||||
|
messageDigest.update(sig);
|
||||||
|
byte[] hash = messageDigest.digest();
|
||||||
|
Set<BatchId> ackSet = new HashSet<BatchId>(acks);
|
||||||
|
Set<GroupId> subSet = new HashSet<GroupId>(subs);
|
||||||
|
return new HeaderImpl(new BundleId(hash), raw.length, ackSet, subSet,
|
||||||
|
transports, sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,7 +48,7 @@ public class MessageImpl implements Message {
|
|||||||
return body.length;
|
return body.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBody() {
|
public byte[] getBytes() {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
37
components/net/sf/briar/protocol/OutgoingBatchBuilder.java
Normal file
37
components/net/sf/briar/protocol/OutgoingBatchBuilder.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package net.sf.briar.protocol;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.Signature;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
|
||||||
|
import net.sf.briar.api.protocol.Batch;
|
||||||
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
|
import net.sf.briar.api.serial.WriterFactory;
|
||||||
|
|
||||||
|
public class OutgoingBatchBuilder extends BatchBuilderImpl {
|
||||||
|
|
||||||
|
OutgoingBatchBuilder(KeyPair keyPair, Signature signature,
|
||||||
|
MessageDigest messageDigest, WriterFactory writerFactory) {
|
||||||
|
super(keyPair, signature, messageDigest, writerFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignature(byte[] sig) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Batch build() throws IOException, SignatureException,
|
||||||
|
InvalidKeyException {
|
||||||
|
byte[] raw = getSignableRepresentation();
|
||||||
|
signature.initSign(keyPair.getPrivate());
|
||||||
|
signature.update(raw);
|
||||||
|
byte[] sig = signature.sign();
|
||||||
|
messageDigest.reset();
|
||||||
|
messageDigest.update(raw);
|
||||||
|
messageDigest.update(sig);
|
||||||
|
byte[] hash = messageDigest.digest();
|
||||||
|
return new BatchImpl(new BatchId(hash), raw.length, messages, sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
44
components/net/sf/briar/protocol/OutgoingHeaderBuilder.java
Normal file
44
components/net/sf/briar/protocol/OutgoingHeaderBuilder.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package net.sf.briar.protocol;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.Signature;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
|
import net.sf.briar.api.protocol.BundleId;
|
||||||
|
import net.sf.briar.api.protocol.GroupId;
|
||||||
|
import net.sf.briar.api.protocol.Header;
|
||||||
|
import net.sf.briar.api.serial.WriterFactory;
|
||||||
|
|
||||||
|
public class OutgoingHeaderBuilder extends HeaderBuilderImpl {
|
||||||
|
|
||||||
|
OutgoingHeaderBuilder(KeyPair keyPair, Signature signature,
|
||||||
|
MessageDigest messageDigest, WriterFactory writerFactory) {
|
||||||
|
super(keyPair, signature, messageDigest, writerFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignature(byte[] sig) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Header build() throws IOException, SignatureException,
|
||||||
|
InvalidKeyException {
|
||||||
|
byte[] raw = getSignableRepresentation();
|
||||||
|
signature.initSign(keyPair.getPrivate());
|
||||||
|
signature.update(raw);
|
||||||
|
byte[] sig = signature.sign();
|
||||||
|
messageDigest.reset();
|
||||||
|
messageDigest.update(raw);
|
||||||
|
messageDigest.update(sig);
|
||||||
|
byte[] hash = messageDigest.digest();
|
||||||
|
Set<BatchId> ackSet = new HashSet<BatchId>(acks);
|
||||||
|
Set<GroupId> subSet = new HashSet<GroupId>(subs);
|
||||||
|
return new HeaderImpl(new BundleId(hash), raw.length, ackSet, subSet,
|
||||||
|
transports, sig);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import java.io.InputStream;
|
|||||||
import net.sf.briar.api.serial.Reader;
|
import net.sf.briar.api.serial.Reader;
|
||||||
import net.sf.briar.api.serial.ReaderFactory;
|
import net.sf.briar.api.serial.ReaderFactory;
|
||||||
|
|
||||||
class ReaderFactoryImpl implements ReaderFactory {
|
public class ReaderFactoryImpl implements ReaderFactory {
|
||||||
|
|
||||||
public Reader createReader(InputStream in) {
|
public Reader createReader(InputStream in) {
|
||||||
return new ReaderImpl(in);
|
return new ReaderImpl(in);
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ class ReaderImpl implements Reader {
|
|||||||
readLimit = 0L;
|
readLimit = 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasBoolean() throws IOException {
|
public boolean hasBoolean() throws IOException {
|
||||||
if(!started) readNext(true);
|
if(!started) readNext(true);
|
||||||
if(eof) return false;
|
if(eof) return false;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import java.io.OutputStream;
|
|||||||
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;
|
||||||
|
|
||||||
class WriterFactoryImpl implements WriterFactory {
|
public class WriterFactoryImpl implements WriterFactory {
|
||||||
|
|
||||||
public Writer createWriter(OutputStream out) {
|
public Writer createWriter(OutputStream out) {
|
||||||
return new WriterImpl(out);
|
return new WriterImpl(out);
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ class WriterImpl implements Writer {
|
|||||||
this.out = out;
|
this.out = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
public void writeBoolean(boolean b) throws IOException {
|
public void writeBoolean(boolean b) throws IOException {
|
||||||
if(b) out.write(Tag.TRUE);
|
if(b) out.write(Tag.TRUE);
|
||||||
else out.write(Tag.FALSE);
|
else out.write(Tag.FALSE);
|
||||||
@@ -156,9 +161,4 @@ class WriterImpl implements Writer {
|
|||||||
public void writeNull() throws IOException {
|
public void writeNull() throws IOException {
|
||||||
out.write(Tag.NULL);
|
out.write(Tag.NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
|
||||||
out.flush();
|
|
||||||
out.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
<test name='net.sf.briar.i18n.I18nTest'/>
|
<test name='net.sf.briar.i18n.I18nTest'/>
|
||||||
<test name='net.sf.briar.invitation.InvitationWorkerTest'/>
|
<test name='net.sf.briar.invitation.InvitationWorkerTest'/>
|
||||||
<test name='net.sf.briar.protocol.BundleReaderTest'/>
|
<test name='net.sf.briar.protocol.BundleReaderTest'/>
|
||||||
|
<test name='net.sf.briar.protocol.BundleReadWriteTest'/>
|
||||||
<test name='net.sf.briar.protocol.BundleWriterTest'/>
|
<test name='net.sf.briar.protocol.BundleWriterTest'/>
|
||||||
<test name='net.sf.briar.serial.ReaderImplTest'/>
|
<test name='net.sf.briar.serial.ReaderImplTest'/>
|
||||||
<test name='net.sf.briar.serial.WriterImplTest'/>
|
<test name='net.sf.briar.serial.WriterImplTest'/>
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package net.sf.briar.db;
|
package net.sf.briar.db;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.SignatureException;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -18,9 +16,9 @@ import net.sf.briar.api.protocol.AuthorId;
|
|||||||
import net.sf.briar.api.protocol.Batch;
|
import net.sf.briar.api.protocol.Batch;
|
||||||
import net.sf.briar.api.protocol.BatchBuilder;
|
import net.sf.briar.api.protocol.BatchBuilder;
|
||||||
import net.sf.briar.api.protocol.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
import net.sf.briar.api.protocol.Bundle;
|
|
||||||
import net.sf.briar.api.protocol.BundleBuilder;
|
|
||||||
import net.sf.briar.api.protocol.BundleId;
|
import net.sf.briar.api.protocol.BundleId;
|
||||||
|
import net.sf.briar.api.protocol.BundleReader;
|
||||||
|
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.Header;
|
import net.sf.briar.api.protocol.Header;
|
||||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||||
@@ -507,7 +505,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateBundleThrowsExceptionIfContactIsMissing()
|
public void testGenerateBundleThrowsExceptionIfContactIsMissing()
|
||||||
throws DbException, IOException, SignatureException {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Database<Object> database = context.mock(Database.class);
|
final Database<Object> database = context.mock(Database.class);
|
||||||
@@ -518,7 +516,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<BatchBuilder> batchBuilderProvider =
|
final Provider<BatchBuilder> batchBuilderProvider =
|
||||||
context.mock(Provider.class, "batchBuilderProvider");
|
context.mock(Provider.class, "batchBuilderProvider");
|
||||||
final BundleBuilder bundleBuilder = context.mock(BundleBuilder.class);
|
final BundleWriter bundleBuilder = context.mock(BundleWriter.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Check that the contact is still in the DB
|
// Check that the contact is still in the DB
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
@@ -539,8 +537,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateBundle() throws DbException, IOException,
|
public void testGenerateBundle() throws Exception {
|
||||||
SignatureException {
|
|
||||||
final long headerSize = 1234L;
|
final long headerSize = 1234L;
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -552,12 +549,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<BatchBuilder> batchBuilderProvider =
|
final Provider<BatchBuilder> batchBuilderProvider =
|
||||||
context.mock(Provider.class, "batchBuilderProvider");
|
context.mock(Provider.class, "batchBuilderProvider");
|
||||||
final BundleBuilder bundleBuilder = context.mock(BundleBuilder.class);
|
final BundleWriter bundleWriter = context.mock(BundleWriter.class);
|
||||||
final HeaderBuilder headerBuilder = context.mock(HeaderBuilder.class);
|
final HeaderBuilder headerBuilder = context.mock(HeaderBuilder.class);
|
||||||
final Header header = context.mock(Header.class);
|
final Header header = context.mock(Header.class);
|
||||||
final BatchBuilder batchBuilder = context.mock(BatchBuilder.class);
|
final BatchBuilder batchBuilder = context.mock(BatchBuilder.class);
|
||||||
final Batch batch = context.mock(Batch.class);
|
final Batch batch = context.mock(Batch.class);
|
||||||
final Bundle bundle = context.mock(Bundle.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
allowing(database).startTransaction();
|
allowing(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -582,11 +578,11 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
// Build the header
|
// Build the header
|
||||||
oneOf(headerBuilder).build();
|
oneOf(headerBuilder).build();
|
||||||
will(returnValue(header));
|
will(returnValue(header));
|
||||||
oneOf(bundleBuilder).getCapacity();
|
oneOf(bundleWriter).getCapacity();
|
||||||
will(returnValue(1024L * 1024L));
|
will(returnValue(1024L * 1024L));
|
||||||
oneOf(header).getSize();
|
oneOf(header).getSize();
|
||||||
will(returnValue(headerSize));
|
will(returnValue(headerSize));
|
||||||
oneOf(bundleBuilder).addHeader(header);
|
oneOf(bundleWriter).addHeader(header);
|
||||||
// Add a batch to the bundle
|
// Add a batch to the bundle
|
||||||
oneOf(database).getSendableMessages(txn, contactId,
|
oneOf(database).getSendableMessages(txn, contactId,
|
||||||
Batch.MAX_SIZE - headerSize);
|
Batch.MAX_SIZE - headerSize);
|
||||||
@@ -604,25 +600,24 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
oneOf(database).addOutstandingBatch(
|
oneOf(database).addOutstandingBatch(
|
||||||
txn, contactId, batchId, messages);
|
txn, contactId, batchId, messages);
|
||||||
// Add the batch to the bundle
|
// Add the batch to the bundle
|
||||||
oneOf(bundleBuilder).addBatch(batch);
|
oneOf(bundleWriter).addBatch(batch);
|
||||||
// Check whether to add another batch
|
// Check whether to add another batch
|
||||||
oneOf(batch).getSize();
|
oneOf(batch).getSize();
|
||||||
will(returnValue((long) message.getSize()));
|
will(returnValue((long) message.getSize()));
|
||||||
// No, just send the bundle
|
// No, just send the bundle
|
||||||
oneOf(bundleBuilder).build();
|
oneOf(bundleWriter).close();
|
||||||
will(returnValue(bundle));
|
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
headerBuilderProvider, batchBuilderProvider);
|
headerBuilderProvider, batchBuilderProvider);
|
||||||
|
|
||||||
db.generateBundle(contactId, bundleBuilder);
|
db.generateBundle(contactId, bundleWriter);
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReceiveBundleThrowsExceptionIfContactIsMissing()
|
public void testReceiveBundleThrowsExceptionIfContactIsMissing()
|
||||||
throws DbException, IOException, SignatureException {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Database<Object> database = context.mock(Database.class);
|
final Database<Object> database = context.mock(Database.class);
|
||||||
@@ -633,7 +628,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<BatchBuilder> batchBuilderProvider =
|
final Provider<BatchBuilder> batchBuilderProvider =
|
||||||
context.mock(Provider.class, "batchBuilderProvider");
|
context.mock(Provider.class, "batchBuilderProvider");
|
||||||
final Bundle bundle = context.mock(Bundle.class);
|
final BundleReader bundleReader = context.mock(BundleReader.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Check that the contact is still in the DB
|
// Check that the contact is still in the DB
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
@@ -646,7 +641,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
headerBuilderProvider, batchBuilderProvider);
|
headerBuilderProvider, batchBuilderProvider);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
db.receiveBundle(contactId, bundle);
|
db.receiveBundle(contactId, bundleReader);
|
||||||
assertTrue(false);
|
assertTrue(false);
|
||||||
} catch(NoSuchContactException expected) {}
|
} catch(NoSuchContactException expected) {}
|
||||||
|
|
||||||
@@ -654,8 +649,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReceivedBundle() throws DbException, IOException,
|
public void testReceiveBundle() throws Exception {
|
||||||
SignatureException {
|
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Database<Object> database = context.mock(Database.class);
|
final Database<Object> database = context.mock(Database.class);
|
||||||
@@ -666,7 +660,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<BatchBuilder> batchBuilderProvider =
|
final Provider<BatchBuilder> batchBuilderProvider =
|
||||||
context.mock(Provider.class, "batchBuilderProvider");
|
context.mock(Provider.class, "batchBuilderProvider");
|
||||||
final Bundle bundle = context.mock(Bundle.class);
|
final BundleReader bundleReader = context.mock(BundleReader.class);
|
||||||
final Header header = context.mock(Header.class);
|
final Header header = context.mock(Header.class);
|
||||||
final Batch batch = context.mock(Batch.class);
|
final Batch batch = context.mock(Batch.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
@@ -676,7 +670,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
allowing(database).containsContact(txn, contactId);
|
allowing(database).containsContact(txn, contactId);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
// Header
|
// Header
|
||||||
oneOf(bundle).getHeader();
|
oneOf(bundleReader).getHeader();
|
||||||
will(returnValue(header));
|
will(returnValue(header));
|
||||||
// Acks
|
// Acks
|
||||||
oneOf(header).getAcks();
|
oneOf(header).getAcks();
|
||||||
@@ -692,7 +686,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
will(returnValue(transports));
|
will(returnValue(transports));
|
||||||
oneOf(database).setTransports(txn, contactId, transports);
|
oneOf(database).setTransports(txn, contactId, transports);
|
||||||
// Batches
|
// Batches
|
||||||
oneOf(bundle).getNextBatch();
|
oneOf(bundleReader).getNextBatch();
|
||||||
will(returnValue(batch));
|
will(returnValue(batch));
|
||||||
oneOf(batch).getMessages();
|
oneOf(batch).getMessages();
|
||||||
will(returnValue(Collections.singleton(message)));
|
will(returnValue(Collections.singleton(message)));
|
||||||
@@ -706,8 +700,9 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
will(returnValue(batchId));
|
will(returnValue(batchId));
|
||||||
oneOf(database).addBatchToAck(txn, contactId, batchId);
|
oneOf(database).addBatchToAck(txn, contactId, batchId);
|
||||||
// Any more batches? Nope
|
// Any more batches? Nope
|
||||||
oneOf(bundle).getNextBatch();
|
oneOf(bundleReader).getNextBatch();
|
||||||
will(returnValue(null));
|
will(returnValue(null));
|
||||||
|
oneOf(bundleReader).close();
|
||||||
// Lost batches
|
// Lost batches
|
||||||
oneOf(header).getId();
|
oneOf(header).getId();
|
||||||
will(returnValue(bundleId));
|
will(returnValue(bundleId));
|
||||||
@@ -718,7 +713,7 @@ public abstract class DatabaseComponentTest extends TestCase {
|
|||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
||||||
headerBuilderProvider, batchBuilderProvider);
|
headerBuilderProvider, batchBuilderProvider);
|
||||||
|
|
||||||
db.receiveBundle(contactId, bundle);
|
db.receiveBundle(contactId, bundleReader);
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public class H2DatabaseTest extends TestCase {
|
|||||||
assertEquals(authorId, m1.getAuthor());
|
assertEquals(authorId, m1.getAuthor());
|
||||||
assertEquals(timestamp, m1.getTimestamp());
|
assertEquals(timestamp, m1.getTimestamp());
|
||||||
assertEquals(size, m1.getSize());
|
assertEquals(size, m1.getSize());
|
||||||
assertTrue(Arrays.equals(body, m1.getBody()));
|
assertTrue(Arrays.equals(body, m1.getBytes()));
|
||||||
// Delete the records
|
// Delete the records
|
||||||
db.removeContact(txn, contactId);
|
db.removeContact(txn, contactId);
|
||||||
db.removeMessage(txn, messageId);
|
db.removeMessage(txn, messageId);
|
||||||
|
|||||||
156
test/net/sf/briar/protocol/BundleReadWriteTest.java
Normal file
156
test/net/sf/briar/protocol/BundleReadWriteTest.java
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
package net.sf.briar.protocol;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.KeyPairGenerator;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.Signature;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import net.sf.briar.TestUtils;
|
||||||
|
import net.sf.briar.api.protocol.AuthorId;
|
||||||
|
import net.sf.briar.api.protocol.Batch;
|
||||||
|
import net.sf.briar.api.protocol.BatchBuilder;
|
||||||
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
|
import net.sf.briar.api.protocol.BundleReader;
|
||||||
|
import net.sf.briar.api.protocol.BundleWriter;
|
||||||
|
import net.sf.briar.api.protocol.GroupId;
|
||||||
|
import net.sf.briar.api.protocol.Header;
|
||||||
|
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||||
|
import net.sf.briar.api.protocol.Message;
|
||||||
|
import net.sf.briar.api.protocol.MessageId;
|
||||||
|
import net.sf.briar.api.protocol.MessageParser;
|
||||||
|
import net.sf.briar.api.protocol.UniqueId;
|
||||||
|
import net.sf.briar.api.serial.FormatException;
|
||||||
|
import net.sf.briar.api.serial.Reader;
|
||||||
|
import net.sf.briar.api.serial.Writer;
|
||||||
|
import net.sf.briar.api.serial.WriterFactory;
|
||||||
|
import net.sf.briar.serial.ReaderFactoryImpl;
|
||||||
|
import net.sf.briar.serial.WriterFactoryImpl;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
|
public class BundleReadWriteTest extends TestCase {
|
||||||
|
|
||||||
|
private static final String SIGNATURE_ALGO = "SHA256withRSA";
|
||||||
|
private static final String KEY_PAIR_ALGO = "RSA";
|
||||||
|
private static final String DIGEST_ALGO = "SHA-256";
|
||||||
|
|
||||||
|
private final File testDir = TestUtils.getTestDirectory();
|
||||||
|
private final File bundle = new File(testDir, "bundle");
|
||||||
|
|
||||||
|
private final long capacity = 1024L;
|
||||||
|
private final BatchId ack = new BatchId(TestUtils.getRandomId());
|
||||||
|
private final Set<BatchId> acks = Collections.singleton(ack);
|
||||||
|
private final GroupId sub = new GroupId(TestUtils.getRandomId());
|
||||||
|
private final Set<GroupId> subs = Collections.singleton(sub);
|
||||||
|
private final Map<String, String> transports =
|
||||||
|
Collections.singletonMap("foo", "bar");
|
||||||
|
|
||||||
|
private final MessageId messageId = new MessageId(TestUtils.getRandomId());
|
||||||
|
private final AuthorId authorId = new AuthorId(TestUtils.getRandomId());
|
||||||
|
private final long timestamp = System.currentTimeMillis();
|
||||||
|
private final byte[] messageBody = new byte[123];
|
||||||
|
private final Message message = new MessageImpl(messageId, MessageId.NONE,
|
||||||
|
sub, authorId, timestamp, messageBody);
|
||||||
|
|
||||||
|
// FIXME: This test should not depend on an impl in another component
|
||||||
|
private final WriterFactory wf = new WriterFactoryImpl();
|
||||||
|
|
||||||
|
private final KeyPair keyPair;
|
||||||
|
private final Signature sig;
|
||||||
|
private final MessageDigest digest;
|
||||||
|
|
||||||
|
public BundleReadWriteTest() throws NoSuchAlgorithmException {
|
||||||
|
super();
|
||||||
|
keyPair = KeyPairGenerator.getInstance(KEY_PAIR_ALGO).generateKeyPair();
|
||||||
|
sig = Signature.getInstance(SIGNATURE_ALGO);
|
||||||
|
digest = MessageDigest.getInstance(DIGEST_ALGO);
|
||||||
|
assertEquals(digest.getDigestLength(), UniqueId.LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
testDir.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWriteBundle() throws Exception {
|
||||||
|
HeaderBuilder h = new OutgoingHeaderBuilder(keyPair, sig, digest, wf);
|
||||||
|
h.addAcks(acks);
|
||||||
|
h.addSubscriptions(subs);
|
||||||
|
h.addTransports(transports);
|
||||||
|
Header header = h.build();
|
||||||
|
|
||||||
|
BatchBuilder b = new OutgoingBatchBuilder(keyPair, sig, digest, wf);
|
||||||
|
b.addMessage(message);
|
||||||
|
Batch batch = b.build();
|
||||||
|
|
||||||
|
FileOutputStream out = new FileOutputStream(bundle);
|
||||||
|
Writer writer = new WriterFactoryImpl().createWriter(out);
|
||||||
|
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||||
|
|
||||||
|
w.addHeader(header);
|
||||||
|
w.addBatch(batch);
|
||||||
|
w.close();
|
||||||
|
|
||||||
|
assertTrue(bundle.exists());
|
||||||
|
assertTrue(bundle.length() > messageBody.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWriteAndReadBundle() throws Exception {
|
||||||
|
|
||||||
|
testWriteBundle();
|
||||||
|
|
||||||
|
MessageParser messageParser = new MessageParser() {
|
||||||
|
public Message parseMessage(byte[] body) throws FormatException,
|
||||||
|
SignatureException {
|
||||||
|
// FIXME: Really parse the message
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Provider<HeaderBuilder> headerBuilderProvider =
|
||||||
|
new Provider<HeaderBuilder>() {
|
||||||
|
public HeaderBuilder get() {
|
||||||
|
return new IncomingHeaderBuilder(keyPair, sig, digest, wf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Provider<BatchBuilder> batchBuilderProvider =
|
||||||
|
new Provider<BatchBuilder>() {
|
||||||
|
public BatchBuilder get() {
|
||||||
|
return new IncomingBatchBuilder(keyPair, sig, digest, wf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FileInputStream in = new FileInputStream(bundle);
|
||||||
|
Reader reader = new ReaderFactoryImpl().createReader(in);
|
||||||
|
BundleReader r = new BundleReaderImpl(reader, bundle.length(),
|
||||||
|
messageParser, headerBuilderProvider, batchBuilderProvider);
|
||||||
|
|
||||||
|
Header h = r.getHeader();
|
||||||
|
assertEquals(acks, h.getAcks());
|
||||||
|
assertEquals(subs, h.getSubscriptions());
|
||||||
|
assertEquals(transports, h.getTransports());
|
||||||
|
Batch b = r.getNextBatch();
|
||||||
|
assertEquals(Collections.singletonList(message), b.getMessages());
|
||||||
|
assertNull(r.getNextBatch());
|
||||||
|
r.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
TestUtils.deleteTestDirectory(testDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ import net.sf.briar.TestUtils;
|
|||||||
import net.sf.briar.api.protocol.Batch;
|
import net.sf.briar.api.protocol.Batch;
|
||||||
import net.sf.briar.api.protocol.BatchBuilder;
|
import net.sf.briar.api.protocol.BatchBuilder;
|
||||||
import net.sf.briar.api.protocol.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
|
import net.sf.briar.api.protocol.BundleReader;
|
||||||
import net.sf.briar.api.protocol.GroupId;
|
import net.sf.briar.api.protocol.GroupId;
|
||||||
import net.sf.briar.api.protocol.Header;
|
import net.sf.briar.api.protocol.Header;
|
||||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||||
@@ -46,7 +47,7 @@ public class BundleReaderTest extends TestCase {
|
|||||||
private final byte[] batchSig = TestUtils.getRandomId();
|
private final byte[] batchSig = TestUtils.getRandomId();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetHeader() throws IOException, SignatureException {
|
public void testGetHeader() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final Reader reader = context.mock(Reader.class);
|
final Reader reader = context.mock(Reader.class);
|
||||||
final MessageParser messageParser = context.mock(MessageParser.class);
|
final MessageParser messageParser = context.mock(MessageParser.class);
|
||||||
@@ -82,7 +83,7 @@ public class BundleReaderTest extends TestCase {
|
|||||||
oneOf(headerBuilder).build();
|
oneOf(headerBuilder).build();
|
||||||
will(returnValue(header));
|
will(returnValue(header));
|
||||||
}});
|
}});
|
||||||
BundleReader r = createBundleReader(reader, messageParser,
|
BundleReader r = new BundleReaderImpl(reader, size, messageParser,
|
||||||
headerBuilderProvider, batchBuilderProvider);
|
headerBuilderProvider, batchBuilderProvider);
|
||||||
|
|
||||||
assertEquals(header, r.getHeader());
|
assertEquals(header, r.getHeader());
|
||||||
@@ -91,8 +92,7 @@ public class BundleReaderTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBatchBeforeHeaderThrowsException() throws IOException,
|
public void testBatchBeforeHeaderThrowsException() throws Exception {
|
||||||
SignatureException {
|
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final Reader reader = context.mock(Reader.class);
|
final Reader reader = context.mock(Reader.class);
|
||||||
final MessageParser messageParser = context.mock(MessageParser.class);
|
final MessageParser messageParser = context.mock(MessageParser.class);
|
||||||
@@ -102,7 +102,7 @@ public class BundleReaderTest extends TestCase {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final Provider<BatchBuilder> batchBuilderProvider =
|
final Provider<BatchBuilder> batchBuilderProvider =
|
||||||
context.mock(Provider.class, "batchBuilderProvider");
|
context.mock(Provider.class, "batchBuilderProvider");
|
||||||
BundleReader r = createBundleReader(reader, messageParser,
|
BundleReader r = new BundleReaderImpl(reader, size, messageParser,
|
||||||
headerBuilderProvider, batchBuilderProvider);
|
headerBuilderProvider, batchBuilderProvider);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -114,8 +114,30 @@ public class BundleReaderTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetHeaderNoBatches() throws IOException,
|
public void testCloseBeforeHeaderDoesNotThrowException() throws IOException,
|
||||||
SignatureException {
|
SignatureException {
|
||||||
|
Mockery context = new Mockery();
|
||||||
|
final Reader reader = context.mock(Reader.class);
|
||||||
|
final MessageParser messageParser = context.mock(MessageParser.class);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Provider<HeaderBuilder> headerBuilderProvider =
|
||||||
|
context.mock(Provider.class);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final Provider<BatchBuilder> batchBuilderProvider =
|
||||||
|
context.mock(Provider.class, "batchBuilderProvider");
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(reader).close();
|
||||||
|
}});
|
||||||
|
BundleReader r = new BundleReaderImpl(reader, size, messageParser,
|
||||||
|
headerBuilderProvider, batchBuilderProvider);
|
||||||
|
|
||||||
|
r.close();
|
||||||
|
|
||||||
|
context.assertIsSatisfied();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetHeaderNoBatches() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final Reader reader = context.mock(Reader.class);
|
final Reader reader = context.mock(Reader.class);
|
||||||
final MessageParser messageParser = context.mock(MessageParser.class);
|
final MessageParser messageParser = context.mock(MessageParser.class);
|
||||||
@@ -155,19 +177,21 @@ public class BundleReaderTest extends TestCase {
|
|||||||
oneOf(reader).hasListEnd();
|
oneOf(reader).hasListEnd();
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(reader).readListEnd();
|
oneOf(reader).readListEnd();
|
||||||
|
// Close
|
||||||
|
oneOf(reader).close();
|
||||||
}});
|
}});
|
||||||
BundleReader r = createBundleReader(reader, messageParser,
|
BundleReader r = new BundleReaderImpl(reader, size, messageParser,
|
||||||
headerBuilderProvider, batchBuilderProvider);
|
headerBuilderProvider, batchBuilderProvider);
|
||||||
|
|
||||||
assertEquals(header, r.getHeader());
|
assertEquals(header, r.getHeader());
|
||||||
assertNull(r.getNextBatch());
|
assertNull(r.getNextBatch());
|
||||||
|
r.close();
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetHeaderOneBatch() throws IOException,
|
public void testGetHeaderOneBatch() throws Exception {
|
||||||
SignatureException {
|
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final Reader reader = context.mock(Reader.class);
|
final Reader reader = context.mock(Reader.class);
|
||||||
final MessageParser messageParser = context.mock(MessageParser.class);
|
final MessageParser messageParser = context.mock(MessageParser.class);
|
||||||
@@ -226,26 +250,17 @@ public class BundleReaderTest extends TestCase {
|
|||||||
oneOf(reader).hasListEnd();
|
oneOf(reader).hasListEnd();
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
oneOf(reader).readListEnd();
|
oneOf(reader).readListEnd();
|
||||||
|
// Close
|
||||||
|
oneOf(reader).close();
|
||||||
}});
|
}});
|
||||||
BundleReader r = createBundleReader(reader, messageParser,
|
BundleReader r = new BundleReaderImpl(reader, size, messageParser,
|
||||||
headerBuilderProvider, batchBuilderProvider);
|
headerBuilderProvider, batchBuilderProvider);
|
||||||
|
|
||||||
assertEquals(header, r.getHeader());
|
assertEquals(header, r.getHeader());
|
||||||
assertEquals(batch, r.getNextBatch());
|
assertEquals(batch, r.getNextBatch());
|
||||||
assertNull(r.getNextBatch());
|
assertNull(r.getNextBatch());
|
||||||
|
r.close();
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
private BundleReader createBundleReader(Reader reader,
|
|
||||||
MessageParser messageParser,
|
|
||||||
Provider<HeaderBuilder> headerBuilderProvider,
|
|
||||||
Provider<BatchBuilder> batchBuilderProvider) {
|
|
||||||
return new BundleReader(reader, messageParser, headerBuilderProvider,
|
|
||||||
batchBuilderProvider) {
|
|
||||||
public long getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import junit.framework.TestCase;
|
|||||||
import net.sf.briar.TestUtils;
|
import net.sf.briar.TestUtils;
|
||||||
import net.sf.briar.api.protocol.Batch;
|
import net.sf.briar.api.protocol.Batch;
|
||||||
import net.sf.briar.api.protocol.BatchId;
|
import net.sf.briar.api.protocol.BatchId;
|
||||||
import net.sf.briar.api.protocol.Bundle;
|
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.Header;
|
import net.sf.briar.api.protocol.Header;
|
||||||
import net.sf.briar.api.protocol.Message;
|
import net.sf.briar.api.protocol.Message;
|
||||||
@@ -21,6 +21,7 @@ import org.junit.Test;
|
|||||||
|
|
||||||
public class BundleWriterTest extends TestCase {
|
public class BundleWriterTest extends TestCase {
|
||||||
|
|
||||||
|
private final long capacity = 1024L * 1024L;
|
||||||
private final BatchId ack = new BatchId(TestUtils.getRandomId());
|
private final BatchId ack = new BatchId(TestUtils.getRandomId());
|
||||||
private final Set<BatchId> acks = Collections.singleton(ack);
|
private final Set<BatchId> acks = Collections.singleton(ack);
|
||||||
private final GroupId sub = new GroupId(TestUtils.getRandomId());
|
private final GroupId sub = new GroupId(TestUtils.getRandomId());
|
||||||
@@ -28,7 +29,6 @@ public class BundleWriterTest extends TestCase {
|
|||||||
private final Map<String, String> transports =
|
private final Map<String, String> transports =
|
||||||
Collections.singletonMap("foo", "bar");
|
Collections.singletonMap("foo", "bar");
|
||||||
private final byte[] headerSig = TestUtils.getRandomId();
|
private final byte[] headerSig = TestUtils.getRandomId();
|
||||||
private final long capacity = 1024L * 1024L;
|
|
||||||
private final byte[] messageBody = new byte[123];
|
private final byte[] messageBody = new byte[123];
|
||||||
private final byte[] batchSig = TestUtils.getRandomId();
|
private final byte[] batchSig = TestUtils.getRandomId();
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ public class BundleWriterTest extends TestCase {
|
|||||||
will(returnValue(headerSig));
|
will(returnValue(headerSig));
|
||||||
oneOf(writer).writeRaw(headerSig);
|
oneOf(writer).writeRaw(headerSig);
|
||||||
}});
|
}});
|
||||||
BundleWriter w = createBundleWriter(writer);
|
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||||
|
|
||||||
w.addHeader(header);
|
w.addHeader(header);
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ public class BundleWriterTest extends TestCase {
|
|||||||
will(returnValue(headerSig));
|
will(returnValue(headerSig));
|
||||||
oneOf(writer).writeRaw(headerSig);
|
oneOf(writer).writeRaw(headerSig);
|
||||||
}});
|
}});
|
||||||
BundleWriter w = createBundleWriter(writer);
|
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||||
|
|
||||||
w.addHeader(header);
|
w.addHeader(header);
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ public class BundleWriterTest extends TestCase {
|
|||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final Writer writer = context.mock(Writer.class);
|
final Writer writer = context.mock(Writer.class);
|
||||||
final Batch batch = context.mock(Batch.class);
|
final Batch batch = context.mock(Batch.class);
|
||||||
BundleWriter w = createBundleWriter(writer);
|
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
w.addBatch(batch);
|
w.addBatch(batch);
|
||||||
@@ -117,7 +117,7 @@ public class BundleWriterTest extends TestCase {
|
|||||||
public void testCloseBeforeHeaderThrowsException() throws IOException {
|
public void testCloseBeforeHeaderThrowsException() throws IOException {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final Writer writer = context.mock(Writer.class);
|
final Writer writer = context.mock(Writer.class);
|
||||||
BundleWriter w = createBundleWriter(writer);
|
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
w.close();
|
w.close();
|
||||||
@@ -159,7 +159,7 @@ public class BundleWriterTest extends TestCase {
|
|||||||
oneOf(writer).writeListEnd();
|
oneOf(writer).writeListEnd();
|
||||||
oneOf(writer).close();
|
oneOf(writer).close();
|
||||||
}});
|
}});
|
||||||
BundleWriter w = createBundleWriter(writer);
|
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||||
|
|
||||||
w.addHeader(header);
|
w.addHeader(header);
|
||||||
w.close();
|
w.close();
|
||||||
@@ -200,7 +200,7 @@ public class BundleWriterTest extends TestCase {
|
|||||||
oneOf(writer).writeListStart();
|
oneOf(writer).writeListStart();
|
||||||
oneOf(batch).getMessages();
|
oneOf(batch).getMessages();
|
||||||
will(returnValue(Collections.singleton(message)));
|
will(returnValue(Collections.singleton(message)));
|
||||||
oneOf(message).getBody();
|
oneOf(message).getBytes();
|
||||||
will(returnValue(messageBody));
|
will(returnValue(messageBody));
|
||||||
oneOf(writer).writeRaw(messageBody);
|
oneOf(writer).writeRaw(messageBody);
|
||||||
oneOf(writer).writeListEnd();
|
oneOf(writer).writeListEnd();
|
||||||
@@ -211,7 +211,7 @@ public class BundleWriterTest extends TestCase {
|
|||||||
oneOf(writer).writeListStart();
|
oneOf(writer).writeListStart();
|
||||||
oneOf(batch).getMessages();
|
oneOf(batch).getMessages();
|
||||||
will(returnValue(Collections.singleton(message)));
|
will(returnValue(Collections.singleton(message)));
|
||||||
oneOf(message).getBody();
|
oneOf(message).getBytes();
|
||||||
will(returnValue(messageBody));
|
will(returnValue(messageBody));
|
||||||
oneOf(writer).writeRaw(messageBody);
|
oneOf(writer).writeRaw(messageBody);
|
||||||
oneOf(writer).writeListEnd();
|
oneOf(writer).writeListEnd();
|
||||||
@@ -222,7 +222,7 @@ public class BundleWriterTest extends TestCase {
|
|||||||
oneOf(writer).writeListEnd();
|
oneOf(writer).writeListEnd();
|
||||||
oneOf(writer).close();
|
oneOf(writer).close();
|
||||||
}});
|
}});
|
||||||
BundleWriter w = createBundleWriter(writer);
|
BundleWriter w = new BundleWriterImpl(writer, capacity);
|
||||||
|
|
||||||
w.addHeader(header);
|
w.addHeader(header);
|
||||||
w.addBatch(batch);
|
w.addBatch(batch);
|
||||||
@@ -231,12 +231,4 @@ public class BundleWriterTest extends TestCase {
|
|||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
private BundleWriter createBundleWriter(Writer writer) {
|
|
||||||
return new BundleWriter(writer, capacity) {
|
|
||||||
public Bundle build() throws IOException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user