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
274 lines
8.6 KiB
Java
4 years ago
|
// 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));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|