mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 20:29:52 +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:
@@ -467,7 +467,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.setBytes(4, m.getAuthor().getBytes());
|
||||
ps.setLong(5, m.getTimestamp());
|
||||
ps.setInt(6, m.getSize());
|
||||
ps.setBlob(7, new ByteArrayInputStream(m.getBody()));
|
||||
ps.setBlob(7, new ByteArrayInputStream(m.getBytes()));
|
||||
ps.setInt(8, 0);
|
||||
int rowsAffected = ps.executeUpdate();
|
||||
assert rowsAffected == 1;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.sf.briar.db;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SignatureException;
|
||||
import java.util.HashSet;
|
||||
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.BatchBuilder;
|
||||
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.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;
|
||||
@@ -190,8 +192,8 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
}
|
||||
}
|
||||
|
||||
public Bundle generateBundle(ContactId c, BundleBuilder b)
|
||||
throws DbException, IOException, SignatureException {
|
||||
public void generateBundle(ContactId c, BundleWriter b) throws DbException,
|
||||
IOException, GeneralSecurityException {
|
||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c);
|
||||
HeaderBuilder h;
|
||||
// Add acks
|
||||
@@ -280,15 +282,13 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
// more messages trickling in but we can't wait forever
|
||||
if(size * 2 < Batch.MAX_SIZE) break;
|
||||
}
|
||||
Bundle bundle = b.build();
|
||||
if(LOG.isLoggable(Level.FINE))
|
||||
LOG.fine("Bundle generated, " + bundle.getSize() + " bytes");
|
||||
b.close();
|
||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Bundle generated");
|
||||
System.gc();
|
||||
return bundle;
|
||||
}
|
||||
|
||||
private Batch fillBatch(ContactId c, long capacity) throws DbException,
|
||||
SignatureException {
|
||||
IOException, GeneralSecurityException {
|
||||
contactLock.readLock().lock();
|
||||
try {
|
||||
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,
|
||||
IOException, SignatureException {
|
||||
public void receiveBundle(ContactId c, BundleReader b) throws DbException,
|
||||
IOException, GeneralSecurityException {
|
||||
if(LOG.isLoggable(Level.FINE))
|
||||
LOG.fine("Received bundle from " + c + ", "
|
||||
+ b.getSize() + " bytes");
|
||||
@@ -529,52 +529,64 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
}
|
||||
// Store the messages
|
||||
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++;
|
||||
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))
|
||||
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
|
||||
Set<BatchId> lost;
|
||||
contactLock.readLock().lock();
|
||||
@@ -586,7 +598,7 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
try {
|
||||
Txn txn = db.startTransaction();
|
||||
try {
|
||||
lost = db.addReceivedBundle(txn, c, h.getId());
|
||||
lost = db.addReceivedBundle(txn, c, b);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
@@ -629,7 +641,6 @@ class ReadWriteLockDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
contactLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
public void removeContact(ContactId c) throws DbException {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.sf.briar.db;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SignatureException;
|
||||
import java.util.HashSet;
|
||||
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.BatchBuilder;
|
||||
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.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;
|
||||
@@ -143,8 +145,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
}
|
||||
}
|
||||
|
||||
public Bundle generateBundle(ContactId c, BundleBuilder b)
|
||||
throws DbException, IOException, SignatureException {
|
||||
public void generateBundle(ContactId c, BundleWriter b) throws DbException,
|
||||
IOException, GeneralSecurityException {
|
||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Generating bundle for " + c);
|
||||
HeaderBuilder h;
|
||||
// Add acks
|
||||
@@ -215,15 +217,13 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
// more messages trickling in but we can't wait forever
|
||||
if(size * 2 < Batch.MAX_SIZE) break;
|
||||
}
|
||||
Bundle bundle = b.build();
|
||||
if(LOG.isLoggable(Level.FINE))
|
||||
LOG.fine("Bundle generated, " + bundle.getSize() + " bytes");
|
||||
b.close();
|
||||
if(LOG.isLoggable(Level.FINE)) LOG.fine("Bundle generated");
|
||||
System.gc();
|
||||
return bundle;
|
||||
}
|
||||
|
||||
private Batch fillBatch(ContactId c, long capacity) throws DbException,
|
||||
SignatureException {
|
||||
IOException, GeneralSecurityException {
|
||||
synchronized(contactLock) {
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
synchronized(messageLock) {
|
||||
@@ -335,8 +335,8 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
}
|
||||
}
|
||||
|
||||
public void receiveBundle(ContactId c, Bundle b) throws DbException,
|
||||
IOException, SignatureException {
|
||||
public void receiveBundle(ContactId c, BundleReader b) throws DbException,
|
||||
IOException, GeneralSecurityException {
|
||||
if(LOG.isLoggable(Level.FINE))
|
||||
LOG.fine("Received bundle from " + c + ", "
|
||||
+ b.getSize() + " bytes");
|
||||
@@ -402,40 +402,52 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
}
|
||||
// Store the messages
|
||||
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++;
|
||||
waitForPermissionToWrite();
|
||||
synchronized(contactLock) {
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
synchronized(messageLock) {
|
||||
synchronized(messageStatusLock) {
|
||||
synchronized(subscriptionLock) {
|
||||
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 " + batches + " batches");
|
||||
b.close();
|
||||
retransmitLostBatches(c, h.getId());
|
||||
System.gc();
|
||||
}
|
||||
|
||||
private void storeBatch(ContactId c, Batch b) throws DbException {
|
||||
waitForPermissionToWrite();
|
||||
synchronized(contactLock) {
|
||||
if(!containsContact(c)) throw new NoSuchContactException();
|
||||
synchronized(messageLock) {
|
||||
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
|
||||
Set<BatchId> lost;
|
||||
synchronized(contactLock) {
|
||||
@@ -444,7 +456,7 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
synchronized(messageStatusLock) {
|
||||
Txn txn = db.startTransaction();
|
||||
try {
|
||||
lost = db.addReceivedBundle(txn, c, h.getId());
|
||||
lost = db.addReceivedBundle(txn, c, b);
|
||||
db.commitTransaction(txn);
|
||||
} catch(DbException e) {
|
||||
db.abortTransaction(txn);
|
||||
@@ -472,7 +484,6 @@ class SynchronizedDatabaseComponent<Txn> extends DatabaseComponentImpl<Txn> {
|
||||
}
|
||||
}
|
||||
}
|
||||
System.gc();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.SignatureException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
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.BatchBuilder;
|
||||
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.Header;
|
||||
import net.sf.briar.api.protocol.HeaderBuilder;
|
||||
@@ -24,26 +24,32 @@ import net.sf.briar.api.serial.Reader;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
/** 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 final Reader r;
|
||||
private final long size;
|
||||
private final MessageParser messageParser;
|
||||
private final Provider<HeaderBuilder> headerBuilderProvider;
|
||||
private final Provider<BatchBuilder> batchBuilderProvider;
|
||||
private State state = State.START;
|
||||
|
||||
BundleReader(Reader r, MessageParser messageParser,
|
||||
BundleReaderImpl(Reader r, long size, MessageParser messageParser,
|
||||
Provider<HeaderBuilder> headerBuilderProvider,
|
||||
Provider<BatchBuilder> batchBuilderProvider) {
|
||||
this.r = r;
|
||||
this.size = size;
|
||||
this.messageParser = messageParser;
|
||||
this.headerBuilderProvider = headerBuilderProvider;
|
||||
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();
|
||||
r.setReadLimit(Header.MAX_SIZE);
|
||||
Set<BatchId> acks = new HashSet<BatchId>();
|
||||
@@ -69,7 +75,7 @@ abstract class BundleReader implements Bundle {
|
||||
return h.build();
|
||||
}
|
||||
|
||||
public Batch getNextBatch() throws IOException, SignatureException {
|
||||
public Batch getNextBatch() throws IOException, GeneralSecurityException {
|
||||
if(state == State.FIRST_BATCH) {
|
||||
r.readListStart();
|
||||
state = State.MORE_BATCHES;
|
||||
@@ -91,4 +97,8 @@ abstract class BundleReader implements Bundle {
|
||||
b.setSignature(sig);
|
||||
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.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.Header;
|
||||
import net.sf.briar.api.protocol.Message;
|
||||
import net.sf.briar.api.serial.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 };
|
||||
|
||||
@@ -19,7 +19,7 @@ abstract class BundleWriter implements BundleBuilder {
|
||||
private final long capacity;
|
||||
private State state = State.START;
|
||||
|
||||
BundleWriter(Writer w, long capacity) {
|
||||
BundleWriterImpl(Writer w, long capacity) {
|
||||
this.w = w;
|
||||
this.capacity = capacity;
|
||||
}
|
||||
@@ -48,12 +48,12 @@ abstract class BundleWriter implements BundleBuilder {
|
||||
}
|
||||
if(state != State.MORE_BATCHES) throw new IllegalStateException();
|
||||
w.writeListStart();
|
||||
for(Message m : b.getMessages()) w.writeRaw(m.getBody());
|
||||
for(Message m : b.getMessages()) w.writeRaw(m.getBytes());
|
||||
w.writeListEnd();
|
||||
w.writeRaw(b.getSignature());
|
||||
}
|
||||
|
||||
void close() throws IOException {
|
||||
public void close() throws IOException {
|
||||
if(state == State.FIRST_BATCH) {
|
||||
w.writeListStart();
|
||||
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;
|
||||
}
|
||||
|
||||
public byte[] getBody() {
|
||||
public byte[] getBytes() {
|
||||
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.ReaderFactory;
|
||||
|
||||
class ReaderFactoryImpl implements ReaderFactory {
|
||||
public class ReaderFactoryImpl implements ReaderFactory {
|
||||
|
||||
public Reader createReader(InputStream in) {
|
||||
return new ReaderImpl(in);
|
||||
|
||||
@@ -53,6 +53,10 @@ class ReaderImpl implements Reader {
|
||||
readLimit = 0L;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
in.close();
|
||||
}
|
||||
|
||||
public boolean hasBoolean() throws IOException {
|
||||
if(!started) readNext(true);
|
||||
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.WriterFactory;
|
||||
|
||||
class WriterFactoryImpl implements WriterFactory {
|
||||
public class WriterFactoryImpl implements WriterFactory {
|
||||
|
||||
public Writer createWriter(OutputStream out) {
|
||||
return new WriterImpl(out);
|
||||
|
||||
@@ -18,6 +18,11 @@ class WriterImpl implements Writer {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
public void writeBoolean(boolean b) throws IOException {
|
||||
if(b) out.write(Tag.TRUE);
|
||||
else out.write(Tag.FALSE);
|
||||
@@ -156,9 +161,4 @@ class WriterImpl implements Writer {
|
||||
public void writeNull() throws IOException {
|
||||
out.write(Tag.NULL);
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user