@@ -1,138 +0,0 @@ | |||
/** | |||
* @file AQR.java | |||
* | |||
* @author Christos Choutouridis AEM:8997 | |||
* @email cchoutou@ece.auth.gr | |||
*/ | |||
package net.hoo2.auth.vmodem; | |||
/** @name imports */ | |||
/** @{ */ | |||
import java.util.*; | |||
/** @} */ | |||
/** | |||
* @class AQR | |||
* | |||
* Class to used for the ACK-NACK sequence | |||
*/ | |||
class AQR { | |||
static final int AQ_DURATION_DEFAULT = 240; /**< Default duration for the sequence */ | |||
static final int AQR_BUFFER_SIZE = 256; /**< AQR buffer size */ | |||
static final String AQR_BEGIN = "PSTART"; /**< Begin pattern of the response */ | |||
static final String AQR_END = "PSTOP"; /**< End pattern of the response */ | |||
static final int AQR_SEQUENCE_BEGIN = 31; /**< The response sequence string position */ | |||
static final int AQR_SEQUENCE_END = 47; /**< The end of response sequence string position */ | |||
static final int AQR_CRC_BEGIN = 49; /**< The response crc string position */ | |||
static final int AQR_CRC_END = 52; /**< The end of response crc string position */ | |||
private Com com_; /**< Reference to communication module */ | |||
private Log log_; /**< Reference to logging module */ | |||
private Transaction transaction_; /**< A transaction object to used as a buffer for all requests */ | |||
private int duration_; /**< The desired duration for the session */ | |||
private byte[] ack_; /**< The desired ACK code for the session */ | |||
private byte[] nack_; /**< The desired NACK code for the session */ | |||
/** | |||
* Basic constructor | |||
* @param com The Com module to use | |||
* @param log The Log module to use | |||
* @param ack The desired ACK code | |||
* @param nack The desired NACK code | |||
* @param duration The desired duration for the session | |||
*/ | |||
AQR (Com com, Log log, byte[] ack, byte[] nack, int duration) { | |||
com_ = com; | |||
log_ = log; | |||
duration_ = duration; | |||
transaction_= new Transaction(null, new byte[AQR_BUFFER_SIZE]); | |||
ack_ = ack; | |||
nack_ = nack; | |||
} | |||
/** | |||
* Functionality to drain the response buffer for the welcome message | |||
* from the server | |||
* @param ack The ack code that we will use (for printing, not sending) | |||
* @param nack The nack code that we will use (for printing, not sending) | |||
*/ | |||
void caption (byte[] ack, byte[] nack) { | |||
String line; | |||
line = "Running AQR with: " + new String(ack) + "/" + new String(nack); | |||
log_.write(line, true); | |||
transaction_ = com_.request (transaction_, null, null, null, false); | |||
line = new String(transaction_.getResponse()); | |||
log_.out(line); | |||
} | |||
/** | |||
* Main transaction loop. It send requests to server, get the response | |||
* and log the procedure while doing it. | |||
*/ | |||
void run () { | |||
long start; | |||
long now; | |||
long mark =0, delay =0; | |||
String line; | |||
int bads = 0; | |||
boolean good = true; | |||
boolean prev = true; | |||
start = System.currentTimeMillis(); | |||
do { | |||
// Check if the previous transaction was error-free | |||
if (good) | |||
transaction_ = com_.request(transaction_, ack_, AQR_BEGIN.getBytes(), AQR_END.getBytes(), false); | |||
else | |||
transaction_ = com_.request(transaction_, nack_, AQR_BEGIN.getBytes(), AQR_END.getBytes(), false); | |||
good = (_crc_check(transaction_.response)) ? true : false; // crc check the response | |||
bads = (good) ? 0 : bads+1; // count the error strike | |||
// delay calculation | |||
if (prev && !good) mark = transaction_.departure; | |||
if (!prev && good) delay = transaction_.arrival - mark; | |||
else delay = 0; | |||
prev = good; | |||
line = new String(transaction_.code) + ": " | |||
+ new String(transaction_.getResponse()) | |||
+ " Er: " + bads | |||
+ " Tr= " + (transaction_.arrival - transaction_.departure) + " [msec]"; | |||
if (delay != 0) line += " Tt= " + delay + " [msec]"; | |||
log_.write(line); | |||
now = System.currentTimeMillis(); | |||
} while (now - start < duration_*1000); | |||
} | |||
/** @name private helper API */ | |||
/**@{ */ | |||
/** | |||
* A CRC check functionality | |||
* @param data The data to check for validity | |||
* @return The check result | |||
*/ | |||
private boolean _crc_check (byte[] data) { | |||
byte[] seq = Arrays.copyOfRange(data, AQR_SEQUENCE_BEGIN, AQR_SEQUENCE_END); | |||
int crc = Integer.valueOf( | |||
new String(Arrays.copyOfRange(data, AQR_CRC_BEGIN, AQR_CRC_END))); | |||
return (crc == _crc(seq)) ? true : false; | |||
} | |||
/** | |||
* A CRC calculation function. This primitive CRC calculator | |||
* does not use any known CRC polynomial. It just uses XOR | |||
* @param data Reference to buffer | |||
* @return The CRC result | |||
*/ | |||
private int _crc (byte[] data) { | |||
int calc =0; | |||
for (int i=0 ; i<data.length ; ++i) | |||
calc ^= data[i]; | |||
return calc; | |||
} | |||
/**@} */ | |||
} |
@@ -0,0 +1,154 @@ | |||
/** | |||
* @file ARQ.java | |||
* | |||
* @author Christos Choutouridis AEM:8997 | |||
* @email cchoutou@ece.auth.gr | |||
*/ | |||
package net.hoo2.auth.vmodem; | |||
/** @name imports */ | |||
/** @{ */ | |||
import java.util.*; | |||
/** @} */ | |||
/** | |||
* @class ARQ | |||
* | |||
* Class to used for the ACK-NACK sequence | |||
*/ | |||
class ARQ { | |||
static final int ARQ_DURATION_DEFAULT = 240; /** Default duration for the sequence */ | |||
static final int ARQ_BUFFER_SIZE = 256; /** ARQ buffer size */ | |||
static final String ARQ_BEGIN = "PSTART"; /** Begin pattern of the response */ | |||
static final String ARQ_END = "PSTOP"; /** End pattern of the response */ | |||
static final int ARQ_SEQUENCE_BEGIN = 31; /** The response sequence string position */ | |||
static final int ARQ_SEQUENCE_END = 47; /** The end of response sequence string position */ | |||
static final int ARQ_CRC_BEGIN = 49; /** The response crc string position */ | |||
static final int ARQ_CRC_END = 52; /** The end of response crc string position */ | |||
private Com com_; /** Reference to communication module */ | |||
private Log log_; /** Reference to logging module */ | |||
private Transaction transaction_; /** A transaction object to used as a buffer for all requests */ | |||
private int duration_; /** The desired duration for the session */ | |||
private byte[] ack_; /** The desired ACK code for the session */ | |||
private byte[] nack_; /** The desired NACK code for the session */ | |||
/** | |||
* Basic constructor | |||
* @param com The Com module to use | |||
* @param log The Log module to use | |||
* @param ack The desired ACK code | |||
* @param nack The desired NACK code | |||
* @param duration The desired duration for the session | |||
*/ | |||
ARQ (Com com, Log log, byte[] ack, byte[] nack, int duration) { | |||
com_ = com; | |||
log_ = log; | |||
duration_ = duration; | |||
transaction_= new Transaction(null, new byte[ARQ_BUFFER_SIZE]); | |||
ack_ = ack; | |||
nack_ = nack; | |||
} | |||
/** | |||
* Functionality to drain the response buffer for the welcome message | |||
* from the server | |||
* @param ack The ack code that we will use (for printing, not sending) | |||
* @param nack The nack code that we will use (for printing, not sending) | |||
*/ | |||
void caption (byte[] ack, byte[] nack) { | |||
String line; | |||
line = "Running ARQ with: " + new String(ack) + "/" + new String(nack); | |||
log_.write(line, true); | |||
transaction_ = com_.request (transaction_, null, null, null, false); | |||
line = new String(transaction_.getResponse()); | |||
log_.out(line); | |||
} | |||
/** | |||
* Main transaction loop. It send requests to server, get the response | |||
* and log the procedure while doing it. | |||
*/ | |||
void run () { | |||
long start; | |||
long now; | |||
long mark =0, tr =0, ts =0, tt =0; | |||
String line; | |||
int errors = 0; | |||
boolean good = true; | |||
start = System.currentTimeMillis(); | |||
do { | |||
// Check if the previous transaction was error-free | |||
if (good) | |||
transaction_ = com_.request(transaction_, ack_, ARQ_BEGIN.getBytes(), ARQ_END.getBytes(), false); | |||
else | |||
transaction_ = com_.request(transaction_, nack_, ARQ_BEGIN.getBytes(), ARQ_END.getBytes(), false); | |||
good = (_crc_check(transaction_.response)) ? true : false; // crc check the response | |||
// time calculations | |||
tr = transaction_.arrival - transaction_.departure; | |||
tt = 0; | |||
if ((errors == 0) && good) { | |||
tt = ts = tr; | |||
} | |||
if ((errors == 0) && !good) { | |||
mark = transaction_.departure; | |||
ts = tr; | |||
} | |||
if ((errors != 0) && good) { | |||
tt = transaction_.arrival - mark; | |||
ts += tr; | |||
} | |||
if ((errors !=0) && !good) { | |||
ts += tr; | |||
} | |||
errors = (good) ? 0 : errors+1; // update the error strike | |||
line = new String(transaction_.code) + ": " | |||
+ new String(transaction_.getResponse()) | |||
+ " Er: " + errors | |||
+ " Tr= " + tr + " [msec]"; | |||
if (errors !=0) | |||
line += " Ts= 0 [msec] Tt= 0 [msec]"; | |||
else | |||
line += " Ts= " + ts + " [msec]" + " Tt= " + tt + " [msec]"; | |||
log_.write(line); | |||
now = System.currentTimeMillis(); | |||
} while (now - start < duration_*1000); | |||
} | |||
/** @name private helper API */ | |||
/**@{ */ | |||
/** | |||
* A CRC check functionality | |||
* @param data The data to check for validity | |||
* @return The check result | |||
*/ | |||
private boolean _crc_check (byte[] data) { | |||
byte[] seq = Arrays.copyOfRange(data, ARQ_SEQUENCE_BEGIN, ARQ_SEQUENCE_END); | |||
int crc = Integer.valueOf( | |||
new String(Arrays.copyOfRange(data, ARQ_CRC_BEGIN, ARQ_CRC_END)) | |||
); | |||
return (crc == _crc(seq)) ? true : false; | |||
} | |||
/** | |||
* A CRC calculation function. This primitive CRC calculator | |||
* does not use any known CRC polynomial. It just uses XOR | |||
* @param data Reference to buffer | |||
* @return The CRC result | |||
*/ | |||
private int _crc (byte[] data) { | |||
int calc =0; | |||
for (int i=0 ; i<data.length ; ++i) | |||
calc ^= data[i]; | |||
return calc; | |||
} | |||
/**@} */ | |||
} |
@@ -73,10 +73,10 @@ public class VirtualModem { | |||
+ " <1>: The echo requested code from virtual lab\n" | |||
+ " <2>: The time duration of the session [sec]") | |||
.build(); | |||
Option aqr = Option.builder("a") | |||
.longOpt("aqr") | |||
Option arq = Option.builder("a") | |||
.longOpt("arq") | |||
.numberOfArgs(3) | |||
.desc ("Request aqr sequence where <arg> = <1> <2> <3>\n" | |||
.desc ("Request arq sequence where <arg> = <1> <2> <3>\n" | |||
+ " <1>: The ACK requested code for virtual lab\n" | |||
+ " <2>: The NACK requested code from virtual lab\n" | |||
+ " <2>: The time duration for the session [sec]") | |||
@@ -105,7 +105,7 @@ public class VirtualModem { | |||
options.addOption(speed); | |||
options.addOption(log); | |||
options.addOption(echo); | |||
options.addOption(aqr); | |||
options.addOption(arq); | |||
options.addOption(img); | |||
options.addOption(gps); | |||
} | |||
@@ -173,11 +173,11 @@ public class VirtualModem { | |||
} | |||
} | |||
else if (line.hasOption("aqr")) { | |||
byte[] ack = line.getOptionValues("aqr")[0].getBytes(); | |||
byte[] nack = line.getOptionValues("aqr")[1].getBytes(); | |||
AQR a = new AQR(com, log, ack, nack, | |||
Integer.valueOf(line.getOptionValues("aqr")[2])); | |||
else if (line.hasOption("arq")) { | |||
byte[] ack = line.getOptionValues("arq")[0].getBytes(); | |||
byte[] nack = line.getOptionValues("arq")[1].getBytes(); | |||
ARQ a = new ARQ(com, log, ack, nack, | |||
Integer.valueOf(line.getOptionValues("arq")[2])); | |||
if (com.open()) { | |||
a.caption(ack, nack); | |||
a.run(); | |||