mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 02:39:05 +01:00
Use whole buffers for reads and writes.
This commit is contained in:
@@ -7,20 +7,21 @@ class Ack extends Frame {
|
||||
static final int LENGTH = 12;
|
||||
|
||||
Ack() {
|
||||
super(new byte[LENGTH], LENGTH);
|
||||
b[0] = (byte) Frame.ACK_FLAG;
|
||||
super(new byte[LENGTH]);
|
||||
buf[0] = (byte) Frame.ACK_FLAG;
|
||||
}
|
||||
|
||||
Ack(byte[] b) {
|
||||
super(b, LENGTH);
|
||||
b[0] = (byte) Frame.ACK_FLAG;
|
||||
Ack(byte[] buf) {
|
||||
super(buf);
|
||||
if(buf.length != LENGTH) throw new IllegalArgumentException();
|
||||
buf[0] = (byte) Frame.ACK_FLAG;
|
||||
}
|
||||
|
||||
int getWindowSize() {
|
||||
return ByteUtils.readUint24(b, 5);
|
||||
return ByteUtils.readUint24(buf, 5);
|
||||
}
|
||||
|
||||
void setWindowSize(int windowSize) {
|
||||
ByteUtils.writeUint24(windowSize, b, 5);
|
||||
ByteUtils.writeUint24(windowSize, buf, 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,21 +7,21 @@ class Data extends Frame {
|
||||
static final int MAX_PAYLOAD_LENGTH = 1024;
|
||||
static final int MAX_LENGTH = MIN_LENGTH + MAX_PAYLOAD_LENGTH;
|
||||
|
||||
Data(byte[] b, int length) {
|
||||
super(b, length);
|
||||
if(length < MIN_LENGTH || length > MAX_LENGTH)
|
||||
Data(byte[] buf) {
|
||||
super(buf);
|
||||
if(buf.length < MIN_LENGTH || buf.length > MAX_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
boolean isLastFrame() {
|
||||
return b[0] == Frame.FIN_FLAG;
|
||||
return buf[0] == Frame.FIN_FLAG;
|
||||
}
|
||||
|
||||
void setLastFrame(boolean lastFrame) {
|
||||
if(lastFrame) b[0] = (byte) Frame.FIN_FLAG;
|
||||
if(lastFrame) buf[0] = (byte) Frame.FIN_FLAG;
|
||||
}
|
||||
|
||||
int getPayloadLength() {
|
||||
return length - MIN_LENGTH;
|
||||
return buf.length - MIN_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,40 +6,38 @@ abstract class Frame {
|
||||
|
||||
static final byte ACK_FLAG = (byte) 128, FIN_FLAG = 64;
|
||||
|
||||
protected final byte[] b;
|
||||
protected final int length;
|
||||
protected final byte[] buf;
|
||||
|
||||
Frame(byte[] b, int length) {
|
||||
this.b = b;
|
||||
this.length = length;
|
||||
Frame(byte[] buf) {
|
||||
this.buf = buf;
|
||||
}
|
||||
|
||||
byte[] getBuffer() {
|
||||
return b;
|
||||
return buf;
|
||||
}
|
||||
|
||||
int getLength() {
|
||||
return length;
|
||||
return buf.length;
|
||||
}
|
||||
|
||||
long getChecksum() {
|
||||
return ByteUtils.readUint32(b, length - 4);
|
||||
return ByteUtils.readUint32(buf, buf.length - 4);
|
||||
}
|
||||
|
||||
void setChecksum(long checksum) {
|
||||
ByteUtils.writeUint32(checksum, b, length - 4);
|
||||
ByteUtils.writeUint32(checksum, buf, buf.length - 4);
|
||||
}
|
||||
|
||||
long calculateChecksum() {
|
||||
return Crc32.crc(b, 0, length - 4);
|
||||
return Crc32.crc(buf, 0, buf.length - 4);
|
||||
}
|
||||
|
||||
long getSequenceNumber() {
|
||||
return ByteUtils.readUint32(b, 1);
|
||||
return ByteUtils.readUint32(buf, 1);
|
||||
}
|
||||
|
||||
void setSequenceNumber(long sequenceNumber) {
|
||||
ByteUtils.writeUint32(sequenceNumber, b, 1);
|
||||
ByteUtils.writeUint32(sequenceNumber, buf, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,7 +49,7 @@ abstract class Frame {
|
||||
public boolean equals(Object o) {
|
||||
if(o instanceof Frame) {
|
||||
Frame f = (Frame) o;
|
||||
if(b[0] != f.b[0]) return false;
|
||||
if(buf[0] != f.buf[0]) return false;
|
||||
return getSequenceNumber() == f.getSequenceNumber();
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -135,12 +135,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
||||
offHook.release();
|
||||
}
|
||||
|
||||
public void handleWrite(byte[] b, int length) throws IOException {
|
||||
if(length < b.length) {
|
||||
byte[] copy = new byte[length];
|
||||
System.arraycopy(b, 0, copy, 0, length);
|
||||
b = copy;
|
||||
}
|
||||
public void handleWrite(byte[] b) throws IOException {
|
||||
try {
|
||||
port.writeBytes(b);
|
||||
} catch(SerialPortException e) {
|
||||
@@ -153,7 +148,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
||||
try {
|
||||
if(ev.isRXCHAR()) {
|
||||
byte[] b = port.readBytes();
|
||||
if(connected.get()) reliabilityLayer.handleRead(b, b.length);
|
||||
if(connected.get()) reliabilityLayer.handleRead(b);
|
||||
else handleText(b);
|
||||
} else if(ev.isDSR() && ev.getEventValue() == 0) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Remote end hung up");
|
||||
@@ -188,7 +183,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
||||
if(off < b.length) {
|
||||
byte[] data = new byte[b.length - off];
|
||||
System.arraycopy(b, off, data, 0, data.length);
|
||||
reliabilityLayer.handleRead(data, data.length);
|
||||
reliabilityLayer.handleRead(data);
|
||||
}
|
||||
return;
|
||||
} else if(s.equals("OK")) {
|
||||
|
||||
@@ -4,5 +4,5 @@ import java.io.IOException;
|
||||
|
||||
interface ReadHandler {
|
||||
|
||||
void handleRead(byte[] b, int length) throws IOException;
|
||||
void handleRead(byte[] b) throws IOException;
|
||||
}
|
||||
|
||||
@@ -65,20 +65,15 @@ class Receiver implements ReadHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public void handleRead(byte[] b, int length) throws IOException {
|
||||
public void handleRead(byte[] b) throws IOException {
|
||||
if(!valid) throw new IOException("Connection closed");
|
||||
if(length < Data.MIN_LENGTH || length > Data.MAX_LENGTH) {
|
||||
if(LOG.isLoggable(FINE))
|
||||
LOG.fine("Ignoring frame with invalid length");
|
||||
return;
|
||||
}
|
||||
switch(b[0]) {
|
||||
case 0:
|
||||
case Frame.FIN_FLAG:
|
||||
handleData(b, length);
|
||||
handleData(b);
|
||||
break;
|
||||
case Frame.ACK_FLAG:
|
||||
sender.handleAck(b, length);
|
||||
sender.handleAck(b);
|
||||
break;
|
||||
default:
|
||||
if(LOG.isLoggable(FINE)) LOG.fine("Ignoring unknown frame type");
|
||||
@@ -86,9 +81,13 @@ class Receiver implements ReadHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void handleData(byte[] b, int length)
|
||||
throws IOException {
|
||||
Data d = new Data(b, length);
|
||||
private synchronized void handleData(byte[] b) throws IOException {
|
||||
if(b.length < Data.MIN_LENGTH || b.length > Data.MAX_LENGTH) {
|
||||
if(LOG.isLoggable(FINE))
|
||||
LOG.fine("Ignoring data frame with invalid length");
|
||||
return;
|
||||
}
|
||||
Data d = new Data(b);
|
||||
int payloadLength = d.getPayloadLength();
|
||||
if(payloadLength > windowSize) {
|
||||
if(LOG.isLoggable(FINE)) LOG.fine("No space in the window");
|
||||
|
||||
@@ -42,7 +42,7 @@ class ReliabilityLayer implements ReadHandler, WriteHandler {
|
||||
while(valid) {
|
||||
byte[] b = writes.take();
|
||||
if(b.length == 0) return; // Poison pill
|
||||
writeHandler.handleWrite(b, b.length);
|
||||
writeHandler.handleWrite(b);
|
||||
}
|
||||
} catch(InterruptedException e) {
|
||||
if(LOG.isLoggable(WARNING))
|
||||
@@ -73,20 +73,14 @@ class ReliabilityLayer implements ReadHandler, WriteHandler {
|
||||
}
|
||||
|
||||
// The modem calls this method to pass data up to the SLIP decoder
|
||||
public void handleRead(byte[] b, int length) throws IOException {
|
||||
public void handleRead(byte[] b) throws IOException {
|
||||
if(!valid) throw new IOException("Connection closed");
|
||||
decoder.handleRead(b, length);
|
||||
decoder.handleRead(b);
|
||||
}
|
||||
|
||||
// The SLIP encoder calls this method to pass data down to the modem
|
||||
public void handleWrite(byte[] b, int length) throws IOException {
|
||||
public void handleWrite(byte[] b) throws IOException {
|
||||
if(!valid) throw new IOException("Connection closed");
|
||||
if(length == 0) return;
|
||||
if(length < b.length) {
|
||||
byte[] copy = new byte[length];
|
||||
System.arraycopy(b, 0, copy, 0, length);
|
||||
b = copy;
|
||||
}
|
||||
writes.add(b);
|
||||
if(b.length > 0) writes.add(b);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,13 +47,13 @@ class Sender {
|
||||
if(LOG.isLoggable(FINE))
|
||||
LOG.fine("Acknowledging #" + sequenceNumber);
|
||||
}
|
||||
writeHandler.handleWrite(a.getBuffer(), a.getLength());
|
||||
writeHandler.handleWrite(a.getBuffer());
|
||||
}
|
||||
|
||||
void handleAck(byte[] b, int length) {
|
||||
if(length != Ack.LENGTH) {
|
||||
void handleAck(byte[] b) {
|
||||
if(b.length != Ack.LENGTH) {
|
||||
if(LOG.isLoggable(FINE))
|
||||
LOG.fine("Ignoring ack frame with wrong length");
|
||||
LOG.fine("Ignoring ack frame with invalid length");
|
||||
return;
|
||||
}
|
||||
Ack a = new Ack(b);
|
||||
@@ -115,7 +115,7 @@ class Sender {
|
||||
if(fastRetransmit != null) {
|
||||
Data d = fastRetransmit.data;
|
||||
try {
|
||||
writeHandler.handleWrite(d.getBuffer(), d.getLength());
|
||||
writeHandler.handleWrite(d.getBuffer());
|
||||
} catch(IOException e) {
|
||||
// FIXME: Do something more meaningful
|
||||
if(LOG.isLoggable(WARNING)) LOG.warning(e.toString());
|
||||
@@ -169,16 +169,14 @@ class Sender {
|
||||
// Send a window probe if necessary
|
||||
if(sendProbe) {
|
||||
byte[] buf = new byte[Data.MIN_LENGTH];
|
||||
Data probe = new Data(buf, Data.MIN_LENGTH);
|
||||
Data probe = new Data(buf);
|
||||
probe.setChecksum(probe.calculateChecksum());
|
||||
writeHandler.handleWrite(buf, Data.MIN_LENGTH);
|
||||
writeHandler.handleWrite(buf);
|
||||
}
|
||||
// Retransmit any lost data frames
|
||||
if(retransmit != null) {
|
||||
for(Outstanding o : retransmit) {
|
||||
Data d = o.data;
|
||||
writeHandler.handleWrite(d.getBuffer(), d.getLength());
|
||||
}
|
||||
for(Outstanding o : retransmit)
|
||||
writeHandler.handleWrite(o.data.getBuffer());
|
||||
}
|
||||
} catch(IOException e) {
|
||||
// FIXME: Do something more meaningful
|
||||
@@ -202,7 +200,7 @@ class Sender {
|
||||
}
|
||||
if(LOG.isLoggable(FINE))
|
||||
LOG.fine("Transmitting #" + d.getSequenceNumber());
|
||||
writeHandler.handleWrite(d.getBuffer(), d.getLength());
|
||||
writeHandler.handleWrite(d.getBuffer());
|
||||
}
|
||||
|
||||
private static class Outstanding {
|
||||
|
||||
@@ -6,8 +6,8 @@ import java.io.OutputStream;
|
||||
class SenderOutputStream extends OutputStream {
|
||||
|
||||
private final Sender sender;
|
||||
private final byte[] buf = new byte[Data.MAX_LENGTH];
|
||||
|
||||
private byte[] buf = null;
|
||||
private int offset = 0;
|
||||
private long sequenceNumber = 1L;
|
||||
|
||||
@@ -17,18 +17,16 @@ class SenderOutputStream extends OutputStream {
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if(buf == null) assignBuffer();
|
||||
send(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
if(buf != null) send(false);
|
||||
if(offset > Data.HEADER_LENGTH) send(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
if(buf == null) assignBuffer();
|
||||
buf[offset] = (byte) b;
|
||||
offset++;
|
||||
if(offset == Data.HEADER_LENGTH + Data.MAX_PAYLOAD_LENGTH) send(false);
|
||||
@@ -41,13 +39,11 @@ class SenderOutputStream extends OutputStream {
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
if(buf == null) assignBuffer();
|
||||
int available = Data.MAX_LENGTH - offset - Data.FOOTER_LENGTH;
|
||||
while(available <= len) {
|
||||
System.arraycopy(b, off, buf, offset, available);
|
||||
offset += available;
|
||||
send(false);
|
||||
assignBuffer();
|
||||
off += available;
|
||||
len -= available;
|
||||
available = Data.MAX_LENGTH - offset - Data.FOOTER_LENGTH;
|
||||
@@ -56,13 +52,10 @@ class SenderOutputStream extends OutputStream {
|
||||
offset += len;
|
||||
}
|
||||
|
||||
private void assignBuffer() {
|
||||
buf = new byte[Data.MAX_LENGTH];
|
||||
offset = Data.HEADER_LENGTH;
|
||||
}
|
||||
|
||||
private void send(boolean lastFrame) throws IOException {
|
||||
Data d = new Data(buf, offset + Data.FOOTER_LENGTH);
|
||||
byte[] frame = new byte[offset + Data.FOOTER_LENGTH];
|
||||
System.arraycopy(buf, 0, frame, 0, frame.length);
|
||||
Data d = new Data(frame);
|
||||
d.setLastFrame(lastFrame);
|
||||
d.setSequenceNumber(sequenceNumber++);
|
||||
d.setChecksum(d.calculateChecksum());
|
||||
@@ -72,7 +65,6 @@ class SenderOutputStream extends OutputStream {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IOException("Interrupted while writing");
|
||||
}
|
||||
buf = null;
|
||||
offset = 0;
|
||||
offset = Data.HEADER_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,16 +24,17 @@ class SlipDecoder implements ReadHandler {
|
||||
this.readHandler = readHandler;
|
||||
}
|
||||
|
||||
public void handleRead(byte[] b, int length) throws IOException {
|
||||
for(int i = 0; i < length; i++) {
|
||||
public void handleRead(byte[] b) throws IOException {
|
||||
for(int i = 0; i < b.length; i++) {
|
||||
switch(b[i]) {
|
||||
case END:
|
||||
if(escape) {
|
||||
reset(true);
|
||||
} else {
|
||||
if(decodedLength > 0) {
|
||||
readHandler.handleRead(buf, decodedLength);
|
||||
buf = new byte[Data.MAX_LENGTH];
|
||||
byte[] decoded = new byte[decodedLength];
|
||||
System.arraycopy(buf, 0, decoded, 0, decodedLength);
|
||||
readHandler.handleRead(decoded);
|
||||
}
|
||||
reset(false);
|
||||
}
|
||||
|
||||
@@ -14,26 +14,25 @@ class SlipEncoder implements WriteHandler {
|
||||
this.writeHandler = writeHandler;
|
||||
}
|
||||
|
||||
public void handleWrite(byte[] b, int length) throws IOException {
|
||||
if(length > Data.MAX_LENGTH) throw new IllegalArgumentException();
|
||||
int encodedLength = length + 2;
|
||||
for(int i = 0; i < length; i++) {
|
||||
public void handleWrite(byte[] b) throws IOException {
|
||||
if(b.length > Data.MAX_LENGTH) throw new IllegalArgumentException();
|
||||
int encodedLength = b.length + 2;
|
||||
for(int i = 0; i < b.length; i++)
|
||||
if(b[i] == END || b[i] == ESC) encodedLength++;
|
||||
}
|
||||
byte[] buf = new byte[encodedLength];
|
||||
buf[0] = END;
|
||||
for(int i = 0, j = 1; i < length; i++) {
|
||||
byte[] encoded = new byte[encodedLength];
|
||||
encoded[0] = END;
|
||||
for(int i = 0, j = 1; i < b.length; i++) {
|
||||
if(b[i] == END) {
|
||||
buf[j++] = ESC;
|
||||
buf[j++] = TEND;
|
||||
encoded[j++] = ESC;
|
||||
encoded[j++] = TEND;
|
||||
} else if(b[i] == ESC) {
|
||||
buf[j++] = ESC;
|
||||
buf[j++] = TESC;
|
||||
encoded[j++] = ESC;
|
||||
encoded[j++] = TESC;
|
||||
} else {
|
||||
buf[j++] = b[i];
|
||||
encoded[j++] = b[i];
|
||||
}
|
||||
}
|
||||
buf[encodedLength - 1] = END;
|
||||
writeHandler.handleWrite(buf, encodedLength);
|
||||
encoded[encodedLength - 1] = END;
|
||||
writeHandler.handleWrite(encoded);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,5 +4,5 @@ import java.io.IOException;
|
||||
|
||||
interface WriteHandler {
|
||||
|
||||
void handleWrite(byte[] b, int length) throws IOException;
|
||||
void handleWrite(byte[] b) throws IOException;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user