You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

286 lines
7.1 KiB
Java

// 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
<br/> 1.4 (9th March 2006, KJT): updated for JDK 1.5
<br/> 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<ProtocolEvent> 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<String> getServices() {
Vector<String> services = new Vector<String>();
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<ProtocolEvent>();
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<ProtocolEvent> performService(String service) {
Vector<ProtocolEvent> events = new Vector<ProtocolEvent>();
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<ProtocolEvent> receivePDU(PDU sdu) {
// respond to PDU received from underlying protocol
Vector<ProtocolEvent> events = new Vector<ProtocolEvent>();
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);
}
}