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.

178 lines
6.4 KiB
Java

// 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
<br/> 1.4 (9th March 2006, KJT): updated for JDK 1.5
<br/> 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<ProtocolEvent> 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<ProtocolEvent>(); // 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<String> getServices() {
Vector<String> events = // list of events
new Vector<String>();
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<ProtocolEvent> performService(String s) {
Vector<ProtocolEvent> events = // initialise events list
new Vector<ProtocolEvent>();
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<ProtocolEvent> receivePDU(PDU pdu) { // handle received PDU
pduReceived = pdu; // store PDU
return(new Vector<ProtocolEvent>()); // 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
}
}