// 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 receivePDU(PDU pdu) { Vector events = new Vector(); 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 getServices() { Vector services = new Vector(); if (ackSeq >= 0) services.addElement("Send AK(" + ackSeq + ")"); return(services); } public Vector performService(String s) { Vector events = new Vector(); 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); } }