// MUXProtocol.java package protocol; // protocol package import java.util.*; // import Java utility classes import support.*; // import Jasper support classes /** This is the class that supports the (de)multiplexing protocol. It handles both synchronous and asynchronous modes. @author Kenneth J. Turner @version 1.0 (20th July 2010, KJT): initial version */ public class MUXProtocol implements ProtocolEntity { /** Service send offer */ private final static String RECEIVE = "Send data to "; /** Protocol send offer */ private final static String SEND = "Multiplex and send "; /** Protocol send all available offer */ private final static String SEND_ALL = SEND + "all available data"; /** Protocol send one offer */ private final static String SEND_ONE = SEND + "the individual data"; /** Service source offer */ private final static String SINK = "Sink "; /** Protocol events */ private Vector protocolEvents; /** Protocol PDU received */ private MUXPdu protocolIn; /** Protocol channel */ private Medium protocolMedium; /** Protocol protocol mode (true = asynchronous, false = synchronous) */ public static boolean protocolMode; /** Protocol name */ private String protocolName; /** Protocol PDU sent */ private MUXPdu protocolOut; /** Protocol peer */ private MUXProtocol protocolPeer; /** Protocol user */ private MUXService protocolUser; /** Constructor for a (de)multiplexer. @param protocolMedium channel @param protocolName protocol name */ public MUXProtocol(Medium protocolMedium, String protocolName) { this.protocolName = protocolName; // set protocol name this.protocolMedium = protocolMedium; // set protocol medium initialise(); // initialise protocol } /** Return a protocol event with the given comment. @param comment protocol comment @return protocol event */ private ProtocolEvent comment(String comment) { return(new ProtocolEvent(ProtocolEvent.COMMENT, this, comment)); } /** Get the protocol mode. @return protocol mode (true = asynchronous, false = synchronous) */ public boolean getMode() { return(protocolMode); // return protocol mode } /** Get the protocol name. @return protocol name */ public String getName() { return(protocolName); // return protocol name } /** Get the protocol peer. @return protocol peer */ public MUXProtocol getPeer() { return(protocolPeer); // return protocol peer } /** Get protocol input. @return protocol input */ public MUXPdu getProtocolIn() { return(protocolIn); // return protocol input } /** Get protocol output. @return protocol output */ public MUXPdu getProtocolOut() { return(protocolOut); // return protocol output } /** Return services currently offered. @return list of protocol services */ public Vector getServices() { Vector list = new Vector(); // initialise protocol services int firstSDU = protocolOut.firstSDU(); // get first SDU index if (firstSDU >= 0) { // SDU available? if (protocolMode) // asynchronous? list.add(SEND_ONE); // append send one offer else // synchronous list.add(SEND_ALL); // append send all offer } String[] sduList = // get SDU list from PDU ((MUXPdu) protocolIn).getSDUs(); for (int i = 0; i < sduList.length; i++) { // go through SDUs String data = sduList[i]; // get SDU data if (data != null) // SDU available? list.add(RECEIVE + SINK + i); // append protocol receive offer } return (list); // return protocol service list } /** Initialise the protocol entity. */ public void initialise() { protocolEvents = new Vector();// initialise protocol events protocolIn = new MUXPdu(); // initialise protocol input protocolOut = new MUXPdu(); // initialise protocol output } /** Perform service. @param service service request @return resulting protocol events */ public Vector performService(String service) { protocolEvents = new Vector(); // initialise protocol events if (service.startsWith(SEND)) { // send all request? protocolEvents.addElement( // add send event new ProtocolEvent(ProtocolEvent.TRANSMIT, protocolOut)); protocolEvents.addElement( // add receive event new ProtocolEvent(ProtocolEvent.RECEIVE, protocolOut)); transmitPDU(protocolOut, protocolPeer); // send protocol PDU protocolOut = new MUXPdu(); // re-initialise sent PDU } else if (service.startsWith(RECEIVE)) { // receive request? int sinkStart = // get start of sink index service.indexOf(SINK) + SINK.length(); int sink = // get source index Integer.parseInt(service.substring(sinkStart)); String[] sduList = protocolIn.getSDUs(); // get SDU list from PDU String data = sduList[sink]; // get SDU data MUXSdu sdu = new MUXSdu(sink, data); // create SDU transmitPDU(sdu, protocolUser); // send to service user protocolIn.setSDU(sink, null); // remove sink SDU data } return(protocolEvents); // return protocol events } /** Receive PDU. @param pdu PDU @return resulting protocol events */ public Vector receivePDU(PDU pdu) { protocolEvents = new Vector(); // initialise event list if (pdu != null) { // non-empty PDU? String pduType = pdu.type; // get PDU type if (pduType.equals(MUXSdu.TYPE)) { // service user message? int source = ((MUXSdu) pdu).entity; // get source index String data = ((MUXSdu) pdu).sdu; // get service user data String comment; // declare protocol comment if (protocolMode) { // asynchronous? comment = // set comment from presence protocolOut.firstSDU() >= 0 ? "Overwritten" : "Stored"; protocolOut = new MUXPdu(); // initialise protocol output } else // synchronous comment = // set comment from presence protocolOut.getSDU(source) != null ? "Overwritten" : "Stored"; protocolOut.setSDU(source, data); // store source SDU data protocolEvents.addElement( // add receive comment event comment(comment)); } else if (pduType.equals(MUXPdu.TYPE)) { // protocol peer message? String comment = // set comment from presence protocolIn.firstSDU() >= 0 ? "Overwritten" : "Stored"; protocolIn = (MUXPdu) pdu; // store received PDU protocolEvents.addElement( // add receive comment event comment(comment)); } } return(protocolEvents); // return protocol events } /** Set the protocol mode. @param protocolMode protocol mode (true = asynchronous, false = synchronous) */ public void setMode(boolean protocolMode) { this.protocolMode = protocolMode; // set protocol mode } /** Set the protocol peer. @param protocolPeer protocol peer */ public void setPeer(ProtocolEntity protocolPeer) { this.protocolPeer = // set protocol peer (MUXProtocol) protocolPeer; } /** Set the protocol service. @param protocolUser protocol service user */ public void setUser(ProtocolEntity protocolUser) { this.protocolUser = // set service user (MUXService) protocolUser; } /** Send PDU. @param pdu PDU @param destination protocol destination */ public void transmitPDU(PDU pdu, ProtocolEntity destination) { pdu.setSource(this); // set protocol entity as source pdu.setDestination(destination); // set message destination Vector receiveEvents; // declare receive events if (destination == protocolPeer) { // for protocol peer? receiveEvents = // receive PDU at medium protocolPeer.receivePDU(pdu); } else // for service user? receiveEvents = // receive PDU at user protocolUser.receivePDU(pdu); for (int i = 0; i < receiveEvents.size(); i++) // go through receive events protocolEvents.addElement( // append receive event receiveEvents.get(i)); } }