Add generic record reader and writer.

This commit is contained in:
akwizgran
2018-04-19 10:38:44 +01:00
parent edee90dbe2
commit 20a131bec5
10 changed files with 221 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
package org.briarproject.bramble.api.record;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class Record {
public static final int RECORD_HEADER_BYTES = 4;
public static final int MAX_RECORD_PAYLOAD_BYTES = 48 * 1024; // 48 KiB
private final byte protocolVersion, recordType;
private final byte[] payload;
public Record(byte protocolVersion, byte recordType, byte[] payload) {
if (payload.length > MAX_RECORD_PAYLOAD_BYTES)
throw new IllegalArgumentException();
this.protocolVersion = protocolVersion;
this.recordType = recordType;
this.payload = payload;
}
public byte getProtocolVersion() {
return protocolVersion;
}
public byte getRecordType() {
return recordType;
}
public byte[] getPayload() {
return payload;
}
}

View File

@@ -0,0 +1,20 @@
package org.briarproject.bramble.api.record;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.EOFException;
import java.io.IOException;
@NotNullByDefault
public interface RecordReader {
/**
* Reads and returns the next record.
*
* @throws EOFException if the end of the stream is reached without reading
* a complete record
*/
Record readRecord() throws IOException;
void close() throws IOException;
}

View File

@@ -0,0 +1,8 @@
package org.briarproject.bramble.api.record;
import java.io.InputStream;
public interface RecordReaderFactory {
RecordReader createRecordReader(InputStream in);
}

View File

@@ -0,0 +1,15 @@
package org.briarproject.bramble.api.record;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface RecordWriter {
void writeRecord(Record r) throws IOException;
void flush() throws IOException;
void close() throws IOException;
}

View File

@@ -0,0 +1,8 @@
package org.briarproject.bramble.api.record;
import java.io.OutputStream;
public interface RecordWriterFactory {
RecordWriter createRecordWriter(OutputStream out);
}

View File

@@ -0,0 +1,21 @@
package org.briarproject.bramble.record;
import org.briarproject.bramble.api.record.RecordReaderFactory;
import org.briarproject.bramble.api.record.RecordWriterFactory;
import dagger.Module;
import dagger.Provides;
@Module
public class RecordModule {
@Provides
RecordReaderFactory provideRecordReaderFactory() {
return new RecordReaderFactoryImpl();
}
@Provides
RecordWriterFactory provideRecordWriterFactory() {
return new RecordWriterFactoryImpl();
}
}

View File

@@ -0,0 +1,14 @@
package org.briarproject.bramble.record;
import org.briarproject.bramble.api.record.RecordReader;
import org.briarproject.bramble.api.record.RecordReaderFactory;
import java.io.InputStream;
class RecordReaderFactoryImpl implements RecordReaderFactory {
@Override
public RecordReader createRecordReader(InputStream in) {
return new RecordReaderImpl(in);
}
}

View File

@@ -0,0 +1,43 @@
package org.briarproject.bramble.record;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.record.Record;
import org.briarproject.bramble.api.record.RecordReader;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.annotation.concurrent.NotThreadSafe;
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
@NotThreadSafe
@NotNullByDefault
class RecordReaderImpl implements RecordReader {
private final DataInputStream in;
RecordReaderImpl(InputStream in) {
this.in = new DataInputStream(new BufferedInputStream(in, 1024));
}
@Override
public Record readRecord() throws IOException {
byte protocolVersion = in.readByte();
byte recordType = in.readByte();
int payloadLength = in.readShort() & 0xFFFF; // Convert to unsigned
if (payloadLength < 0 || payloadLength > MAX_RECORD_PAYLOAD_BYTES)
throw new FormatException();
byte[] payload = new byte[payloadLength];
in.readFully(payload);
return new Record(protocolVersion, recordType, payload);
}
@Override
public void close() throws IOException {
in.close();
}
}

View File

@@ -0,0 +1,14 @@
package org.briarproject.bramble.record;
import org.briarproject.bramble.api.record.RecordWriter;
import org.briarproject.bramble.api.record.RecordWriterFactory;
import java.io.OutputStream;
class RecordWriterFactoryImpl implements RecordWriterFactory {
@Override
public RecordWriter createRecordWriter(OutputStream out) {
return new RecordWriterImpl(out);
}
}

View File

@@ -0,0 +1,42 @@
package org.briarproject.bramble.record;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.record.Record;
import org.briarproject.bramble.api.record.RecordWriter;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.annotation.concurrent.NotThreadSafe;
@NotThreadSafe
@NotNullByDefault
class RecordWriterImpl implements RecordWriter {
private final DataOutputStream out;
RecordWriterImpl(OutputStream out) {
this.out = new DataOutputStream(new BufferedOutputStream(out, 1024));
}
@Override
public void writeRecord(Record r) throws IOException {
out.write(r.getProtocolVersion());
out.write(r.getRecordType());
byte[] payload = r.getPayload();
out.writeShort(payload.length);
out.write(payload);
}
@Override
public void flush() throws IOException {
out.flush();
}
@Override
public void close() throws IOException {
out.close();
}
}