// BOOTPSender.java (C) K. J. Turner, K. A. Whyte 08/03/06 // Boot Protocol sender (client) package protocol; // protocol package import java.util.Enumeration; // enumeration import java.util.Vector; // vector (list) import support.*; // protocol entity support /** This is the class for a boot protocol sender. @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 (27th July 2010, KJT): unchecked warning suppressed */ public class BOOTPSender // protocol sender (client) implements ProtocolEntity, Timeouts { // protocol entity, timeout // simulator variables private ProtocolEntity peer; // peer entity (client) private Medium medium; // communications medium private String name; // entity name // protocol variables private int transId; // transaction identifier private String hwAddress = "hw"; // hardware address private String ipAddress = "net.91"; // IP address private String bootFile = "boot"; // boot file name private PDU pduSent; // PDU sent private PDU pduReceived; // PDU received private boolean timerEnabled; // whether timer is enabled private Vector entityEvents; // events from entity // protocol state int state; // current protocol state final static int idle = 0; // no request outstanding final static int wait = 1; // waiting for reply // protocol messages final static String request = "REQUEST"; // boot request message final static String reply = "REPLY"; // boot reply message // protocol methods public BOOTPSender (Medium m, String name) { // construct sender instance this.name = name; // set protocol entity name medium = m; // set underlying medium initialise (); // initialise protocol } public String getName () { // get protocol entity name return((name)); // return protocol entity name } public boolean hasTimer (String type) { // protocol uses timer? return((true)); // report it does } public void initialise() { // initialise protocol state = idle; // initialise state pduReceived = null; // initialise no PDU received pduSent = null; // initialise no PDU sent timerEnabled = false; // initialise no timeout entityEvents = new Vector(); // empty medium events } public void setPeer(ProtocolEntity peer) { // set protocol peer this.peer = peer; // set this entity's peer } /** Set the timer for a specified PDU. @param pdu PDU @param enabled whether the timer is enabled */ public void setTimer(PDU pdu, boolean enabled) { timerEnabled = enabled; // store timer status } public Vector getServices() { Vector events = // list of events new Vector(); String pduType; // received PDU type String pduData; // PDU data String pduTrans; // transaction identifier int transPos, hwPos; // trans/hw address positions int trans; // transaction identifier if (pduReceived != null) { // PDU received? pduType = pduReceived.type; // get received PDU type pduData = pduReceived.sdu; // get received PDU data transPos = pduData.indexOf('(') + 1; // get contents start hwPos = pduData.indexOf(','); // get transaction end trans = // get transaction identifier Integer.parseInt(pduData.substring(transPos, hwPos)); if (pduType.equals(reply) && // reply message and ... trans == transId) { // same transaction identifier? timerEnabled = false; state = idle; // no longer waiting } } if (state == idle) { // not awaiting reply trans = // make random id 10..99 10 + ((int) (BOOTPMedium.random() * 90)); events.addElement( // send request for IP/file request + "(" + trans + "," + hwAddress + ") - send IP address and boot file path request"); events.addElement( // send request for file request + "(" + trans + "," + hwAddress + "," + ipAddress + ") - send boot file path request"); events.addElement( // send request for file path request + "(" + trans + "," + hwAddress + "," + ipAddress + "," + bootFile + ") - send path request for given boot file"); } if (timerEnabled) events.addElement("Timeout - presume loss of message and resend"); return(events); // return list of events } public Vector performService(String s) { Vector events = // initialise events list new Vector(); int start, middle, end; // start/mid/end positions String pduData; // PDU data if (s.startsWith(request)) { start = s.indexOf('(') + 1; // get contents start middle = s.indexOf(','); // get trans ident end end = s.indexOf(')' ); // get contents end transId = // get transaction ident Integer.parseInt(s.substring(start, middle)); pduData = s.substring(start, end); // get SDU transmitPDU( // send request new PDU(request, pduData), peer); events.addElement( // transmit PDU new ProtocolEvent(ProtocolEvent.TRANSMIT, pduSent)); state = wait; // awaiting reply } if (s.startsWith("Timeout")) { // timeout? transmitPDU(pduSent, peer); // re-send PDU events.addElement( // add timeout event and PDU new ProtocolEvent(ProtocolEvent.TIMEOUT, pduSent)); } for (Enumeration e = entityEvents.elements(); // go through medium events e.hasMoreElements(); ) events.addElement( // add medium event (ProtocolEvent) e.nextElement()); return((events)); // return list of events } public Vector receivePDU(PDU pdu) { // handle received PDU pduReceived = pdu; // store PDU return(new Vector()); // return no events } public void transmitPDU( // transmit PDU PDU pdu, ProtocolEntity dest) { // for given PDU, destination pdu.setSource(this); // source is this entity pdu.setDestination(dest); // destination is as given pduSent = pdu; // copy PDU sent entityEvents = medium.receivePDU(pdu); // medium receives PDU pduReceived = null; // note no PDU in response timerEnabled = false; // note no timeout } }