hw2: completed but untested
This commit is contained in:
parent
acc8707c3f
commit
ea830e85bd
2 changed files with 69 additions and 5 deletions
|
@ -2,13 +2,72 @@ import transport.Receiver;
|
||||||
import transport.TimeoutAction;
|
import transport.TimeoutAction;
|
||||||
|
|
||||||
public class GBNTReceiver extends Receiver implements TimeoutAction {
|
public class GBNTReceiver extends Receiver implements TimeoutAction {
|
||||||
|
|
||||||
|
private char sequence;
|
||||||
|
boolean firstPacket = true;
|
||||||
|
private static final int RECEIVER_TIMEOUT_MS = 1000;
|
||||||
|
private State state = State.SETUP;
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
SETUP,
|
||||||
|
RECEIVING
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] generateACK(char sequence) {
|
||||||
|
byte[] dest = new byte[2];
|
||||||
|
dest[0] = (byte) ((sequence >> 8) & 0xFF);
|
||||||
|
dest[1] = (byte) (sequence & 0xFF);
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char readBigEndianChar(byte[] src, int offset) {
|
||||||
|
return (char) (src[offset] << 8 + src[offset + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char incrementAndRollover(char c) {
|
||||||
|
return (char) ((c + 1) % 65536);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void timeoutAction() {
|
public void timeoutAction() {
|
||||||
|
try {
|
||||||
|
disconnect();
|
||||||
|
} catch (java.lang.InterruptedException ex) {
|
||||||
|
System.out.println("Thread interrupted. Exiting directly.");
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void unreliableReceive(byte[] bytes, int i, int i1) {
|
protected void unreliableReceive(byte[] bytes, int offset, int length) {
|
||||||
|
switch(this.state) {
|
||||||
|
case SETUP:
|
||||||
|
if (length != 2) {
|
||||||
|
if (firstPacket) return;
|
||||||
|
else {
|
||||||
|
state = State.RECEIVING;
|
||||||
|
this.unreliableReceive(bytes, offset, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sequence = readBigEndianChar(bytes, 0);
|
||||||
|
unreliableSend(bytes, offset, 2);
|
||||||
|
firstPacket = false;
|
||||||
|
break;
|
||||||
|
case RECEIVING:
|
||||||
|
if (length == 2) { // if packet is a close packet
|
||||||
|
if (incrementAndRollover(this.sequence) != readBigEndianChar(bytes, offset)) return; // ignore if not synchronized
|
||||||
|
this.unreliableSend(bytes, offset, 2);
|
||||||
|
timeoutAction();
|
||||||
|
}
|
||||||
|
if (length < 3) return;
|
||||||
|
char seq = readBigEndianChar(bytes, 0);
|
||||||
|
if (seq != incrementAndRollover(sequence)) return; //drop the packet
|
||||||
|
else {
|
||||||
|
this.unreliableReceive(bytes, offset + 2, length);
|
||||||
|
sequence = incrementAndRollover(sequence);
|
||||||
|
this.unreliableSend(generateACK(sequence), 0, 2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,10 @@ public class GBNTSender extends transport.Sender implements TimeoutAction {
|
||||||
return (char) (src[offset] << 8 + src[offset + 1]);
|
return (char) (src[offset] << 8 + src[offset + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static char addAndRollover(char c, char i) {
|
||||||
|
return (char) ((c + i) % 65536);
|
||||||
|
}
|
||||||
|
|
||||||
private static char incrementAndRollover(char c) {
|
private static char incrementAndRollover(char c) {
|
||||||
return (char) ((c + 1) % 65536);
|
return (char) ((c + 1) % 65536);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +61,7 @@ public class GBNTSender extends transport.Sender implements TimeoutAction {
|
||||||
private static final char W = 10;
|
private static final char W = 10;
|
||||||
private char base = (char) (new Random().nextInt() % 65536);
|
private char base = (char) (new Random().nextInt() % 65536);
|
||||||
private char waitingACK = 0;
|
private char waitingACK = 0;
|
||||||
private int timeoutMs = 1000;
|
private int timeoutMs = 500;
|
||||||
private double rttEWMA = 0;
|
private double rttEWMA = 0;
|
||||||
private double devRttEWMA = 0;
|
private double devRttEWMA = 0;
|
||||||
|
|
||||||
|
@ -107,7 +111,7 @@ public class GBNTSender extends transport.Sender implements TimeoutAction {
|
||||||
protected int reliableSend(byte[] bytes, int offset, int length) {
|
protected int reliableSend(byte[] bytes, int offset, int length) {
|
||||||
if (state != State.SENDING) throw new IllegalStateException();
|
if (state != State.SENDING) throw new IllegalStateException();
|
||||||
|
|
||||||
Packet p = new Packet(base, bytes, offset, length);
|
Packet p = new Packet(addAndRollover(base, waitingACK), bytes, offset, length);
|
||||||
waitingACK++;
|
waitingACK++;
|
||||||
packets.add(p);
|
packets.add(p);
|
||||||
p.send();
|
p.send();
|
||||||
|
@ -142,6 +146,7 @@ public class GBNTSender extends transport.Sender implements TimeoutAction {
|
||||||
byte[] expected = createSetupPacket();
|
byte[] expected = createSetupPacket();
|
||||||
if (bytes[offset] == expected[0] && bytes[1] == expected[offset + 1]) {
|
if (bytes[offset] == expected[0] && bytes[1] == expected[offset + 1]) {
|
||||||
state = State.SENDING;
|
state = State.SENDING;
|
||||||
|
base = incrementAndRollover(base);
|
||||||
resumeSender();
|
resumeSender();
|
||||||
} else {
|
} else {
|
||||||
sendSetup();
|
sendSetup();
|
||||||
|
|
Reference in a new issue