This repository has been archived on 2021-10-31. You can view files and clone it, but cannot push or open issues or pull requests.
NTW/hw2/src/GBNTReceiver.java

74 lines
2.4 KiB
Java

import transport.Receiver;
import transport.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
public void timeoutAction() {
try {
disconnect();
} catch (java.lang.InterruptedException ex) {
System.out.println("Thread interrupted. Exiting directly.");
System.exit(0);
}
}
@Override
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;
}
}
}