@@ -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" | + " <1>: The echo requested code from virtual lab\n" | ||||
+ " <2>: The time duration of the session [sec]") | + " <2>: The time duration of the session [sec]") | ||||
.build(); | .build(); | ||||
Option aqr = Option.builder("a") | |||||
.longOpt("aqr") | |||||
Option arq = Option.builder("a") | |||||
.longOpt("arq") | |||||
.numberOfArgs(3) | .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" | + " <1>: The ACK requested code for virtual lab\n" | ||||
+ " <2>: The NACK requested code from virtual lab\n" | + " <2>: The NACK requested code from virtual lab\n" | ||||
+ " <2>: The time duration for the session [sec]") | + " <2>: The time duration for the session [sec]") | ||||
@@ -105,7 +105,7 @@ public class VirtualModem { | |||||
options.addOption(speed); | options.addOption(speed); | ||||
options.addOption(log); | options.addOption(log); | ||||
options.addOption(echo); | options.addOption(echo); | ||||
options.addOption(aqr); | |||||
options.addOption(arq); | |||||
options.addOption(img); | options.addOption(img); | ||||
options.addOption(gps); | 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()) { | if (com.open()) { | ||||
a.caption(ack, nack); | a.caption(ack, nack); | ||||
a.run(); | a.run(); | ||||