// ABRAService.java (C) I. A. Robin, K. J. Turner 08/03/06 package protocol; import java.util.*; import support.*; public class ABRAService implements ProtocolEntity { // Service state constants private static final int DISCONNECTED = 0; // no connection in progress // or active private static final int CALLING = 1; // connection initiated by local // user is being established private static final int CALLED = 2; // connection initiated by remote // user is being established private static final int CONNECTED = 3; // data transfer is possible // Service primitives public static final String CON_REQ = "Connection Request"; public static final String CON_IND = "Connection Indication"; public static final String CON_RESP = "Connection Response"; public static final String CON_CONF = "Connection Confirmation"; public static final String DAT_REQ = "Data Request"; public static final String DAT_IND = "Data Indication"; public static final String DIS_REQ = "Disconnection Request"; public static final String DIS_IND = "Disconnection Indication"; private ProtocolEntity provider; // protocol providing service private Vector providerEvents; private PDU pduSent; private String name; private int state; private int block; // sequence number of data block private boolean okToSend; // OK to send DatReq to provider public ABRAService(String name) { this.name = name; initialise(); } public String getName() { return(name); } public Vector getServices() { Vector list = new Vector(); switch (state) { case DISCONNECTED: list.addElement("Send " + CON_REQ); break; case CALLING: list.addElement("Send " + DIS_REQ); break; case CALLED: list.addElement("Send " + CON_RESP); list.addElement("Send " + DIS_REQ); break; case CONNECTED: if (okToSend) list.addElement("Send " + DAT_REQ + "(D" + block + ")"); list.addElement("Send " + DIS_REQ); break; } return(list); } public void initialise() { block = 0; okToSend = true; providerEvents = new Vector(); state = DISCONNECTED; } public Vector performService(String s) { Vector events = new Vector(); switch (state) { case DISCONNECTED: if (s.equals("Send " + CON_REQ)) { transmitPDU(new PDU("ConReq"), provider); events.addElement( new ProtocolEvent(ProtocolEvent.SEND, pduSent)); state = CALLING; } case CALLING: if (s.equals("Send " + DIS_REQ)) { transmitPDU(new PDU("DisReq"), provider); events.addElement( new ProtocolEvent(ProtocolEvent.SEND, pduSent)); state = DISCONNECTED; } break; case CALLED: if (s.equals("Send " + CON_RESP)) { transmitPDU(new PDU("ConResp"), provider); events.addElement( new ProtocolEvent(ProtocolEvent.SEND, pduSent)); state = CONNECTED; } if (s.equals("Send " + DIS_REQ)) { transmitPDU(new PDU("DisReq"), provider); events.addElement( new ProtocolEvent(ProtocolEvent.SEND, pduSent)); state = DISCONNECTED; } break; case CONNECTED: if (s.startsWith("Send " + DAT_REQ)) { String sdu = "D" + block; transmitPDU(new PDU("DatReq", sdu), provider); block++; events.addElement( new ProtocolEvent(ProtocolEvent.SEND, pduSent)); // No state transition } if (s.equals("Send " + DIS_REQ)) { transmitPDU(new PDU("DisReq"), provider); events.addElement( new ProtocolEvent(ProtocolEvent.SEND, pduSent)); state = DISCONNECTED; } } for (Enumeration e = providerEvents.elements(); e.hasMoreElements(); ) events.addElement((ProtocolEvent) e.nextElement()); return(events); } /** Respond to PDU received from underlying protocol */ public Vector receivePDU(PDU pdu) { Vector events = new Vector(); String pduType = pdu.type; switch (state) { case DISCONNECTED: if (pduType.equals("ConInd")) state = CALLED; break; case CALLING: // Is the ConInd possibility below needed? if (pduType.equals("ConConf") || pduType.equals("ConInd")) state = CONNECTED; if (pduType.equals("DisInd")) state = DISCONNECTED; break; case CALLED: if (pduType.equals("DisInd")) state = DISCONNECTED; break; case CONNECTED: if (pduType.equals("DisInd")) state = DISCONNECTED; break; } return(events); } /** Implements flow control by back-pressure. DatReq allowed only when okToSend is true */ public void setOKToSend(boolean ok) { okToSend = ok; } public void setProvider(ProtocolEntity provider) { this.provider = provider; } public void transmitPDU(PDU pdu, ProtocolEntity dest) { pdu.setSource(this); pdu.setDestination(dest); providerEvents = dest.receivePDU(pdu); pduSent = pdu; } }