You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
4.2 KiB
Java

// SWP3Receiver.java (C) I. A. Robin, K. J. Turner 08/03/06
package protocol;
import java.util.Enumeration;
import java.util.Vector;
import support.*;
public class SWP3Receiver implements ProtocolEntity {
private int maxSeq;
private int winSize;
private int lowerWindowEdge;
private int upperWindowEdge;
private PDU pduReceived;
private boolean[] pduArrived;
private Medium medium;
private ProtocolEntity peer;
private Vector<ProtocolEvent> entityEvents; // events from entity
public SWP3Receiver(int maxSeq, int winSize, Medium m) {
this.maxSeq = maxSeq;
this.winSize = winSize;
pduArrived = new boolean[maxSeq + 1];
medium = m;
initialise();
}
private ProtocolEvent comment(String c) {
return(new ProtocolEvent(ProtocolEvent.COMMENT, this, c));
}
public String getName() {
return("Receiver");
}
public Vector<String> getServices() {
Vector<String> list = new Vector<String>();
PDU pdu = pduReceived;
if (pdu != null && pdu.type.equals("DT")) {
int seq = pdu.seq;
if (isWithinWindow(seq)) {
int s = lowerWindowEdge;
for (int i = 0; i < winSize && pduArrived[s]; i++) {
s = inc(s);
}
list.addElement("Send AK(" + s + ")");
}
else // duplicate seq. no.
list.addElement("Send AK(" + lowerWindowEdge +")");
}
return(list);
}
private int inc(int seq) {
return(mod(seq + 1));
}
public void initialise() {
for (int i = 0; i <= maxSeq; i++) pduArrived[i] = false;
lowerWindowEdge = 0;
upperWindowEdge = winSize;
pduReceived = null;
entityEvents = new Vector<ProtocolEvent>(); // empty entity events
}
private boolean isWithinWindow(int seq) {
return
(lowerWindowEdge <= seq && seq < upperWindowEdge) ||
(upperWindowEdge < lowerWindowEdge &&
(seq >= lowerWindowEdge || seq < upperWindowEdge));
}
private int mod(int n) {
int base = maxSeq + 1;
n %= base;
return(n >= 0 ? n : n + base);
}
public Vector<ProtocolEvent> performService(String s) {
Vector<ProtocolEvent> events = new Vector<ProtocolEvent>();
if (s.startsWith("Send AK")) {
int startIndex = s.indexOf( '(' ) + 1;
int endIndex = s.indexOf( ')' );
int seq = Integer.parseInt(s.substring(startIndex, endIndex));
PDU pdu = new PDU("AK", seq);
transmitPDU(pdu, peer);
events.addElement(new ProtocolEvent(ProtocolEvent.TRANSMIT, pdu));
pduReceived = null;
}
for (Enumeration e = entityEvents.elements(); e.hasMoreElements(); )
events.addElement((ProtocolEvent) e.nextElement());
return(events);
}
public Vector<ProtocolEvent> receivePDU(PDU pdu) {
Vector<ProtocolEvent> events = new Vector<ProtocolEvent>();
if (pdu != null && pdu.type.equals("DT")) {
int seq = pdu.seq;
if (isWithinWindow(seq)) {
boolean alreadyBuffered = pduArrived[seq];
boolean delivered = false;
pduArrived[seq] = true;
int s = lowerWindowEdge;
// deliver sequence of data messages to user
for (int i = 0; i < winSize && pduArrived[s]; i++) {
events.addElement(comment("DT(" + s + ") delivered"));
s = inc(s);
}
// clear pduArrived flags for messages passed to user
for (int i = lowerWindowEdge; i != s; i = inc(i)) {
pduArrived[i] = false;
if (i == seq) {
alreadyBuffered = true;
delivered = true;
}
}
if (alreadyBuffered && !delivered)
events.addElement(comment("Ignored"));
if (!alreadyBuffered) {
events.addElement(comment("Buffered"));
alreadyBuffered = true;
}
// update window edges
lowerWindowEdge = s;
upperWindowEdge = mod(lowerWindowEdge + winSize);
}
else { // duplicate sequence number received
events.addElement(comment("Ignored"));
}
}
pduReceived = pdu;
return(events);
}
public void setMaxSeq(int maxSeq) {
this.maxSeq = maxSeq;
}
public void setPeer(ProtocolEntity peer) {
this.peer = peer;
}
public void setWindowSize(int winSize) {
this.winSize = winSize;
}
public void transmitPDU(PDU pdu, ProtocolEntity dest) {
pdu.setSource(this);
pdu.setDestination(dest);
entityEvents = medium.receivePDU(pdu);
}
}