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.

274 lines
8.6 KiB
Java

// MCASTRouterA.java
package protocol; // protocol package
import java.util.*; // import Java utility classes
import support.*; // import Jasper support classes
/**
This is the class that supports a router for broad/uni/multicast.
@author Kenneth J. Turner
@version 1.0 (22nd July 2010, KJT): initial version
*/
public class MCASTRouter implements ProtocolEntity {
/** Service send offer */
private final static String SEND = "Forward message for router ";
/** Current router letter */
public char currentRouter;
/** Service provider events */
private Vector<ProtocolEvent> serviceEvents;
/** Service data unit output */
private Vector<MCASTSdu> sdus;
/** Service entity name */
private String serviceName;
/**
Constructor for sources/sinks.
@param serviceName service name
*/
public MCASTRouter(String serviceName) {
this.serviceName = serviceName; // set service name
currentRouter = lastOf(serviceName); // set current router letter
initialise(); // initialise service entity
}
/**
Find the SDU with the given destinations.
@param destinations destinations
@return the corresponding SDU (or null if none)
*/
public MCASTSdu findSDU(String destinations) {
MCASTSdu result = null; // initialise SDU result
for (int i = 0; i < sdus.size(); i++) { // go through SDUs
MCASTSdu sdu = sdus.get(i); // get SDU
if (sdu.destinations.equals(destinations)) { // destinations found?
result = sdu; // save result
break; // exit loop
}
}
return(result); // return SDU
}
/**
Get first character of string.
@param string string to extract from
@return first character of string
*/
public char firstOf(String string) {
char letter = '?'; // initialise letter
if (string != null) { // non-null string?
int length = string.length(); // get string length
if (length > 0) // non-empty string?
letter = string.charAt(0); // get first character
}
return(letter); // return first character
}
/**
Return the service name.
@return service name
*/
public String getName() {
return(serviceName); // return service name
}
/**
Return the service data units.
@return service data units
*/
public Vector<MCASTSdu> getSDUs() {
return(sdus); // return service data units
}
/**
Return services currently offered.
@return list of services
*/
public Vector<String> getServices() {
Vector<String> list = new Vector<String>(); // initialise service list
if (sdus != null && sdus.size() > 0) { // SDUs from service user?
for (int i = 0; i < sdus.size(); i++) { // go through SDUs
MCASTSdu sdu = sdus.get(i); // get SDU
String destinations = sdu.destinations; // get SDU destinations
String destination = ""; // initialise destination
for (int j = 0; j < destinations.length(); j++) { // go through dests.
if (j > 0) // not first destination?
destination += ", "; // append comma
destination += destinations.charAt(j);// append destination
}
char router = firstOf(destination); // get router letter
if (router != currentRouter) // not current router?
list.addElement(SEND + destination); // add send to list
}
}
return(list); // return service list
}
/**
Initialise the service entity.
*/
public void initialise() {
serviceEvents = new Vector<ProtocolEvent>();// initialise service events
sdus = new Vector<MCASTSdu>(); // initialise SDUs
}
/**
Get last character of string.
@param string string to extract from
@return last character of string
*/
public char lastOf(String string) {
char letter = '?'; // initialise letter
if (string != null) { // non-null string?
int length = string.length(); // get string length
if (length > 0) // non-empty string?
letter = string.charAt(length - 1); // get last character
}
return(letter); // return last character
}
/**
Check if the destination router is more than one hop from the current router
(i.e. is not the next router letter.
@param destination entity destination
@return true/false if destination is not/is adjacent
*/
public boolean laterRouter(ProtocolEntity destination) {
int currentIndex = (int) currentRouter; // get current router index
int destinationIndex = // get destination router index
(int) ((MCASTRouter) destination).currentRouter;
return(destinationIndex > currentIndex + 1);// return router letter check
}
/**
Return the next router to reach the destination. This is a very restricted
routing table for the purposes of this example.
@param destination entity destination
@return next entity destination
*/
public ProtocolEntity nextRouter(ProtocolEntity destination) {
char destinationLetter = // get destination router letter
((MCASTRouter) destination).currentRouter;
char nextLetter = destinationLetter; // assume destination by default
switch (currentRouter) { // route based on current router
case 'A': // at router A?
switch (destinationLetter) { // check destination index
case 'D': // to router D?
nextLetter = 'C'; // via C
break;
case 'E': // to router E?
nextLetter = 'C'; // via C
break;
}
break;
}
return(MCAST.getEntity(nextLetter)); // return next router entity
}
/**
Perform service. Note that the current implementation works for a particular
topology but is not general. When there are multiple destinations, the
router forward to the first two of these. A more general implementation
would embody particular knowledge about routing.
@param service service request
@return resulting service events
*/
public Vector<ProtocolEvent> performService(String service) {
serviceEvents = new Vector<ProtocolEvent>();// initialise service events
if (service.startsWith(SEND)) { // send request?
String destinations = // get destinations
service.substring(SEND.length());
String destination = // remove destination commas
destinations.replaceAll(", ", ""); // get destination(s)
MCASTSdu sdu = findSDU(destination); // find corresponding SDU
char router = firstOf(destination); // get destination router letter
serviceEvents.addElement( // add forward comment
MCAST.comment(this, "forward"));
transmitPDU(sdu, router); // transmit SDU
sdus.remove(sdu); // remove SDU from SDUs
}
return(serviceEvents); // return service events
}
/**
Receive an SDU.
@param sdu SDU
@return resulting service events
*/
public Vector<ProtocolEvent> receivePDU(PDU sdu) {
serviceEvents = new Vector<ProtocolEvent>();// initialise service events
if (sdu != null) { // non-empty SDU?
String destinations = // get SDU destination(s)
((MCASTSdu) sdu).destinations;
if (destinations.length() > 1) { // more than one destination?
String message = ((MCASTSdu) sdu).sdu; // get SDU message
sdu = // get SDU for first destination
new MCASTSdu(destinations.substring(0, 1), message);
sdus.addElement((MCASTSdu) sdu); // store SDU
sdu = // get SDU for later dests.
new MCASTSdu(destinations.substring(1), message);
sdus.addElement((MCASTSdu) sdu); // store SDU
}
else // one destination
sdus.addElement((MCASTSdu) sdu); // store SDU
}
return(serviceEvents); // return service events
}
/**
Send an SDU to the given destination letter.
@param sdu SDU
@param destination destination letter
*/
public void transmitPDU(PDU sdu, char destination) {
ProtocolEntity entityDestination = // get protocol entity dest.
MCAST.getEntity(destination);
transmitPDU(sdu, entityDestination); // transmit PDU
}
/**
Send an SDU to the given destination entity.
@param sdu SDU
@param destination destination entity
*/
public void transmitPDU(PDU sdu, ProtocolEntity destination) {
destination = nextRouter(destination); // set next router destination
sdu.setSource(this); // set source as this entity
sdu.setDestination(destination); // set destination
serviceEvents.addElement( // add send event
new ProtocolEvent(ProtocolEvent.SEND, sdu));
Vector<ProtocolEvent> receiveEvents = // receive SDU at destination
destination.receivePDU(sdu);
if (laterRouter(destination)) { // later router?
serviceEvents.addElement( // add send event
new ProtocolEvent(ProtocolEvent.TRAVERSE, sdu));
}
for (int i = 0; i < receiveEvents.size(); i++) // go through receive events
serviceEvents.addElement( // append receive event
receiveEvents.get(i));
}
}