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.
145 lines
3.9 KiB
Java
145 lines
3.9 KiB
Java
4 years ago
|
// SWP5Receiver.java (C) I. A. Robin, K. J. Turner 04/03/06
|
||
|
|
||
|
package protocol;
|
||
|
|
||
|
import java.util.*;
|
||
|
import support.*;
|
||
|
|
||
|
public class SWP5Receiver implements ProtocolEntity {
|
||
|
|
||
|
private int maxSeq;
|
||
|
private int winSize;
|
||
|
private int lowerWindowEdge;
|
||
|
private int upperWindowEdge;
|
||
|
private boolean[] pduArrived;
|
||
|
private PDU[] recvBuffer;
|
||
|
private SWP5Service user;
|
||
|
private ProtocolEntity peer;
|
||
|
private Medium medium;
|
||
|
private Vector userEvents;
|
||
|
private int ackSeq; // next AK seq. no.
|
||
|
|
||
|
public SWP5Receiver(int maxSeq, int winSize, Medium m) {
|
||
|
setMaxSeq(maxSeq);
|
||
|
setWindowSize(winSize);
|
||
|
medium = m;
|
||
|
initialise();
|
||
|
}
|
||
|
|
||
|
public void setMaxSeq(int maxSeq) {
|
||
|
this.maxSeq = maxSeq;
|
||
|
}
|
||
|
|
||
|
public void setWindowSize(int winSize) {
|
||
|
this.winSize = winSize;
|
||
|
}
|
||
|
|
||
|
public void initialise() {
|
||
|
recvBuffer = new PDU[maxSeq + 1];
|
||
|
pduArrived = new boolean[maxSeq + 1];
|
||
|
for (int i = 0; i <= maxSeq; i++) pduArrived[i] = false;
|
||
|
lowerWindowEdge = 0;
|
||
|
upperWindowEdge = winSize;
|
||
|
ackSeq = -1;
|
||
|
}
|
||
|
|
||
|
private int inc(int seq) {
|
||
|
return(mod(seq + 1));
|
||
|
}
|
||
|
|
||
|
private int mod(int n) {
|
||
|
int base = maxSeq + 1;
|
||
|
n %= base;
|
||
|
return(n >= 0 ? n : n + base);
|
||
|
}
|
||
|
|
||
|
private boolean isWithinWindow(int seq) {
|
||
|
return(lowerWindowEdge <= seq && seq < upperWindowEdge) ||
|
||
|
(upperWindowEdge < lowerWindowEdge &&
|
||
|
(seq >= lowerWindowEdge || seq < upperWindowEdge));
|
||
|
}
|
||
|
|
||
|
private ProtocolEvent comment(String c) {
|
||
|
return(new ProtocolEvent(ProtocolEvent.COMMENT, this, c));
|
||
|
}
|
||
|
|
||
|
public String getName() {
|
||
|
return("Protocol B");
|
||
|
}
|
||
|
|
||
|
public void setPeer(ProtocolEntity peer) {
|
||
|
this.peer = peer;
|
||
|
}
|
||
|
|
||
|
public void setUser(ProtocolEntity user) {
|
||
|
this.user = (SWP5Service)user;
|
||
|
}
|
||
|
|
||
|
public Vector<ProtocolEvent> receivePDU(PDU pdu) {
|
||
|
Vector<ProtocolEvent> events = new Vector<ProtocolEvent>();
|
||
|
if (pdu != null && pdu.type.equals("DT")) {
|
||
|
ackSeq = -1;
|
||
|
int seq = pdu.seq;
|
||
|
if (isWithinWindow(seq)) {
|
||
|
pduArrived[seq] = true;
|
||
|
recvBuffer[seq] = pdu;
|
||
|
seq = lowerWindowEdge;
|
||
|
// deliver sequence of data messages to user
|
||
|
for (int i = 0; i < winSize && pduArrived[seq]; i++) {
|
||
|
PDU pduSent = new PDU("DatInd", recvBuffer[seq].getSDU());
|
||
|
transmitPDU(pduSent, user);
|
||
|
events.addElement(
|
||
|
new ProtocolEvent(ProtocolEvent.DELIVER, pduSent));
|
||
|
seq = inc(seq);
|
||
|
}
|
||
|
ackSeq = seq;
|
||
|
// clear pduArrived flags for messages passed to user
|
||
|
for (int i = lowerWindowEdge; i != seq; i = inc(i))
|
||
|
pduArrived[i] = false;
|
||
|
// update window edges
|
||
|
lowerWindowEdge = seq;
|
||
|
upperWindowEdge = mod(lowerWindowEdge + winSize);
|
||
|
}
|
||
|
else { // duplicate seq. no.
|
||
|
ackSeq = lowerWindowEdge;
|
||
|
events.addElement(comment("Ignored"));
|
||
|
}
|
||
|
}
|
||
|
return(events);
|
||
|
}
|
||
|
|
||
|
public void transmitPDU(PDU pdu, ProtocolEntity dest) {
|
||
|
pdu.setSource(this);
|
||
|
pdu.setDestination(dest);
|
||
|
if (dest == peer)
|
||
|
userEvents = medium.receivePDU(pdu);
|
||
|
else
|
||
|
userEvents = user.receivePDU(pdu);
|
||
|
}
|
||
|
|
||
|
public Vector<String> getServices() {
|
||
|
Vector<String> services = new Vector<String>();
|
||
|
if (ackSeq >= 0)
|
||
|
services.addElement("Send AK(" + ackSeq + ")");
|
||
|
return(services);
|
||
|
}
|
||
|
|
||
|
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));
|
||
|
// send AK for next sequence number required
|
||
|
PDU ackPDU = new PDU("AK", seq);
|
||
|
transmitPDU(ackPDU, peer);
|
||
|
events.addElement(new ProtocolEvent(ProtocolEvent.TRANSMIT, ackPDU));
|
||
|
ackSeq = -1;
|
||
|
}
|
||
|
for (Enumeration e = userEvents.elements(); e.hasMoreElements(); )
|
||
|
events.addElement((ProtocolEvent) e.nextElement());
|
||
|
return(events);
|
||
|
}
|
||
|
|
||
|
}
|