// TCPService.java package protocol; // protocol package import java.util.*; // import Java utility classes import support.*; // import Jasper support classes /** This is the class for a TCP service entity. @author Iain A. Robin, Kenneth J. Turner @version 1.0 (1st September 1999, IAR): initial version
1.4 (9th March 2006, KJT): updated for JDK 1.5
1.5 (26th July 2010, KJT): minor tidying */ public class TCPService implements ProtocolEntity { /** Debug flag */ private final static boolean DEBUG = false; // Service primitives (based on Halsall Figs 11.6 - 11.8): /** Active open message */ public final static String ACTIVE_OPEN = "Active Open"; /** Passive open message */ public final static String PASSIVE_OPEN = "Passive Open"; /** Open failure message */ public final static String OPEN_FAILURE = "Open Failure"; /** Open received message */ public final static String OPEN_RECEIVED = "Open Received"; /** Open success message */ public final static String OPEN_SUCCESS = "Open Success"; /** Send message */ public final static String SEND = "Send"; /** Deliver message */ public final static String DELIVER = "Deliver"; /** Close message */ public final static String CLOSE = "Close"; /** Closing message */ public final static String CLOSING = "Closing"; /** Closed message */ public final static String CLOSED = "Closed"; /** Abort message */ public final static String ABORT = "Abort"; /** Push message */ public final static String PUSH = "(Push)"; /** Open confirmed message (internal use) */ public final static String OPEN_CONFIRMED = "Open Confirmed"; // State constants /** Connected state */ private final static int CONNECTED = 0; /** Calling state */ private final static int CALLING = 1; /** Listening state */ private final static int LISTENING = 2; /** Close sent state */ private final static int CLOSE_SENT = 3; /** Disconnected state */ private final static int DISCONNECTED = 4; /** Protocol for service */ private ProtocolEntity provider; /** Events from provider */ private Vector providerEvents; /** Service name */ private String name; /** Service entity role */ private int role; /** Protocol state */ private int state; /** Request Push flag */ private boolean push; /** Message size */ private int messageSize; /** Constructor for a TCP service entity. @param name service name @param role service role */ public TCPService(String name, int role) { this.name = name; this.role = role; initialise(); } /** Return the TCP service entity name. @return service name */ public String getName() { return (name); } /** Return the services offered by the entity. @return services offered */ public Vector getServices() { Vector services = new Vector(); if (state == CONNECTED) { // connected? if (!TCP.isSlowStart() || // not slow start and name.equals("User A")) { // user A? String service = // set send service SEND + " " + messageSize + " octets"; if (push) // push flag set? service += " " + PUSH; // append push services.addElement(service); // add send service } if (!TCP.isSlowStart()) // not slow start? services.addElement(CLOSE); // add close service } else if (state == DISCONNECTED) { if (role == TCP.SERVER) services.addElement(PASSIVE_OPEN); else services.addElement(ACTIVE_OPEN); } return (services); } /** Initialise service entity. */ public void initialise() { providerEvents = new Vector(); push = false; if (TCP.isSlowStart()) // slow start? setState(CONNECTED); // start directly as connected else // client-server/peer-peer setState(DISCONNECTED); // start as disconnected } /** Perform entity service. @param service service requested @return resulting service events */ public Vector performService(String service) { Vector events = new Vector(); PDU pdu; switch (state) { case CONNECTED: if (service.startsWith(SEND)) { String type = SEND + " (" + messageSize + ")"; if (service.indexOf(PUSH) > 0) type += " " + PUSH; pdu = new PDU(type); pdu.size = messageSize; transmitPDU(pdu, provider); events.addElement( new ProtocolEvent(ProtocolEvent.TRANSMIT, pdu)); } if (service.startsWith(CLOSE)) { pdu = new PDU(CLOSE); transmitPDU(pdu, provider); events.addElement( new ProtocolEvent(ProtocolEvent.TRANSMIT, pdu)); setState(CLOSE_SENT); } break; case CALLING: break; case DISCONNECTED: if (service.equals(ACTIVE_OPEN)) { pdu = new PDU(service); transmitPDU(pdu, provider); events.addElement( new ProtocolEvent(ProtocolEvent.TRANSMIT, pdu)); setState(CALLING); } if (service.equals(PASSIVE_OPEN)) { pdu = new PDU(service); transmitPDU(pdu, provider); events.addElement( new ProtocolEvent(ProtocolEvent.TRANSMIT, pdu)); setState(LISTENING); } break; } for (Enumeration enumeration = providerEvents.elements(); enumeration.hasMoreElements(); ) events.addElement((ProtocolEvent) enumeration.nextElement()); return (events); } /** Receive SDU. @param sdu SDU @return resulting service events */ public Vector receivePDU(PDU sdu) { // respond to PDU received from underlying protocol Vector events = new Vector(); String sduType = sdu.type; if (sduType.equals(OPEN_SUCCESS) || sduType.equals(OPEN_CONFIRMED)) setState(CONNECTED); else if (sduType.equals(OPEN_FAILURE) || sduType.equals(CLOSED)) setState(DISCONNECTED); return (events); } /** Sets the messageSize attribute of the TCPService object * @param size The new messageSize value */ public void setMessageSize(int size) { messageSize = size; } /** Set entity service provider @param provider service provider */ public void setProvider(ProtocolEntity provider) { this.provider = provider; } /** Set the Push attribute of a service entity. @param push Push value */ public void setPush(boolean push) { this.push = push; } /** Set the state attribute of a service entity. @param state state */ public void setState(int state) { if (DEBUG) System.err.println("state (" + name + "): " + state); this.state = state; } /** Transmit an SDU. @param sdu SDU @param destination destination */ public void transmitPDU(PDU sdu, ProtocolEntity destination) { sdu.setSource(this); sdu.setDestination(destination); providerEvents = destination.receivePDU(sdu); } }