// 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 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 getServices() { Vector list = new Vector(); 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(); // 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 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)); 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 receivePDU(PDU pdu) { Vector events = new Vector(); 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); } }