@@ -2,3 +2,5 @@ | |||
*.project | |||
*.classpath | |||
*.doc | |||
@@ -1,25 +1,47 @@ | |||
/** | |||
* @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; | |||
static final int AQR_BUFFER_SIZE = 256; | |||
static final String AQR_BEGIN = "PSTART"; | |||
static final String AQR_END = "PSTOP"; | |||
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; | |||
static final int AQR_SEQUENCE_END = 47; | |||
static final int AQR_CRC_BEGIN = 49; | |||
static final int AQR_CRC_END = 52; | |||
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_; | |||
private Log log_; | |||
private Transaction transaction_; | |||
private int duration_; | |||
private byte[] ack_; | |||
private byte[] nack_; | |||
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; | |||
@@ -28,7 +50,13 @@ class AQR { | |||
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; | |||
@@ -40,6 +68,10 @@ class AQR { | |||
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; | |||
@@ -51,12 +83,13 @@ class AQR { | |||
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; | |||
bads = (good) ? 0 : bads+1; | |||
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; | |||
@@ -73,18 +106,33 @@ class AQR { | |||
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; | |||
} | |||
/**@} */ | |||
} |
@@ -1,17 +1,35 @@ | |||
/** | |||
* @file Com.java | |||
* | |||
* @author Christos Choutouridis AEM:8997 | |||
* @email cchoutou@ece.auth.gr | |||
*/ | |||
package net.hoo2.auth.vmodem; | |||
/** @name imports */ | |||
/** @{ */ | |||
import java.util.Arrays; | |||
import ithakimodem.*; | |||
/** @} */ | |||
/** | |||
* @class Com | |||
* | |||
* Wrapper object of the provided Modem class to provide | |||
* a convenient and common API for all the session functionalities | |||
*/ | |||
class Com { | |||
static final int SPEED_DEFAULT = 48000; | |||
static final int TIMEOUT_DEFAULT = 2000; | |||
static final String URL_DEFAULT = "ithaki"; | |||
static final int SPEED_DEFAULT = 48000; /**< default communication speed [bps] */ | |||
static final int TIMEOUT_DEFAULT = 2000; /**< default timeout values [sec] */ | |||
static final String URL_DEFAULT = "ithaki"; /**< Default destination. Ithaki of-course */ | |||
private Modem modem_; | |||
private int speed_; | |||
private int timeout_; | |||
private Modem modem_; /**< Ref to Modem */ | |||
private int speed_; /**< Communication speed [bps] */ | |||
private int timeout_; /**< communication timeout [sec] */ | |||
/** | |||
* Basic constructor | |||
*/ | |||
Com () { | |||
modem_ = new Modem(); | |||
speed_ = SPEED_DEFAULT; | |||
@@ -19,6 +37,14 @@ class Com { | |||
modem_.setSpeed(speed_); | |||
modem_.setTimeout(timeout_); | |||
} | |||
/** A more fancy constructor | |||
* | |||
* @param log Reference to Log to use | |||
* @param speed The desired speed [bps] | |||
* @param timeout The desired timeout [sec] | |||
* @note | |||
* Currently not used | |||
*/ | |||
Com (Log log, int speed, int timeout) { | |||
modem_ = new Modem(); | |||
speed_ = speed; | |||
@@ -26,63 +52,96 @@ class Com { | |||
modem_.setSpeed(speed_); | |||
modem_.setTimeout(timeout_); | |||
} | |||
// get/set | |||
/** @name Mutator interface */ | |||
/**@{ */ | |||
/** Get the current timeout value [sec] */ | |||
int timeout () { return timeout_; } | |||
/** Set the timeout value [sec] */ | |||
void timeout (int timeout) { | |||
if (timeout_ != timeout) { | |||
timeout_ = timeout; | |||
modem_.setTimeout(timeout_); | |||
} | |||
} | |||
/** Get the current speed [bps] */ | |||
int speed () { return speed_; } | |||
/** Set the speed [bps] */ | |||
void speed (int speed) { | |||
if (speed_ != speed) { | |||
speed_ = speed; | |||
modem_.setSpeed(speed_); | |||
} | |||
} | |||
/**@} */ | |||
/** @name Public API of the class */ | |||
/**@{ */ | |||
/** Open a communication channel with a URL */ | |||
boolean open (String url) { return modem_.open(url); } | |||
/** Open a communication channel with Ithaki */ | |||
boolean open () { return modem_.open(URL_DEFAULT); } | |||
/** Close the connection */ | |||
boolean close() { return modem_.close(); } | |||
/** | |||
* @grief The basic communication functionality | |||
* | |||
* This function sends a request to server and return the response. In order to | |||
* do that, the main reading loop seeks for the starting pattern and use the data | |||
* from that point up to the ending pattern. This is very helpful for binary incoming | |||
* data. | |||
* @note | |||
* Blocking mode | |||
* @param data Reference to Transaction data to use @see Transaction | |||
* @param code The request code to send | |||
* @param begin The starting pattern of the response data | |||
* @param end The ending pattern of the response data | |||
* @param bin A flag to indicate that the data are in binary form | |||
* @return Reference to Transaction object with the response data. @see Transaction | |||
*/ | |||
Transaction request (Transaction data, byte[] code, byte[] begin, byte[] end, boolean bin) { | |||
int ch =0; | |||
boolean have_begin = (begin != null) ? false : true; | |||
boolean incoming = false; | |||
// Clear the receive buffer first | |||
_clear (data.response, 0, data.response.length); | |||
if (code != null) { | |||
data.code = code; | |||
modem_.write(data.code); | |||
// if we have a request | |||
data.code = code; // store the request code for the transaction | |||
modem_.write(data.code); // send the code and mark the time | |||
modem_.write((int)'\r'); | |||
data.departure = System.currentTimeMillis();// - (long)((8*(data.code.length+1))*(1000.0/speed_)); | |||
} | |||
// main receive loop | |||
data.size =0; | |||
do { | |||
// escape guard for memory protection | |||
if (data.size >= data.response.length) { | |||
data.size =0; | |||
return data; | |||
} | |||
// read the data byte from server | |||
try { | |||
ch = modem_.read(); | |||
} | |||
catch (Exception e) { | |||
// Oops!!!! something went wrong. Break and return :( | |||
System.err.println (e.getMessage()); | |||
data.size =0; | |||
return data; | |||
} | |||
if (!incoming) { | |||
// first byte triggered. mark the time | |||
incoming = true; | |||
data.arrival = System.currentTimeMillis();// - (long)(8*(1000.0/speed_)); | |||
} | |||
data.response [data.size++] = (byte)ch; | |||
data.response [data.size++] = (byte)ch; // store the byte | |||
if (!have_begin && (detect(data.response, begin, data.size) != -1)) { | |||
// If begin pattern detected, start over. | |||
_clear(data.response, 0, data.size); | |||
data.size = _copy (data.response, begin); | |||
have_begin = true; | |||
@@ -95,9 +154,28 @@ class Com { | |||
) | |||
) | |||
); | |||
/*^ | |||
* We loop until: | |||
* 1) server returns -1 | |||
* 2) A end pattern arrives | |||
* 3) A "\r\n\n\n" sequence arrives (in character mode, not for binary files) | |||
* 4) A "NO CARRIER" sequence arrives (in character mode, not for binary files) | |||
*/ | |||
return data; | |||
} | |||
/** | |||
* @brief | |||
* A pattern detect functionality. | |||
* | |||
* Search in data input for the pattern and return its position if found. | |||
* @note | |||
* O(n^2) in time. | |||
* @param data The data buffer to search into | |||
* @param pattern The pattern to search for | |||
* @param max The maximum length to search | |||
* @return The position of pattern in data, or -1 if not found | |||
*/ | |||
static int detect (byte[] data, byte[] pattern, int max) { | |||
if (pattern != null) { | |||
for (int i =0 ; i<max && i<data.length - pattern.length; ++i) { | |||
@@ -114,12 +192,27 @@ class Com { | |||
} | |||
return -1; | |||
} | |||
/**@} */ | |||
/** @name Private helper api */ | |||
/**@{*/ | |||
/** | |||
* Clear a buffer segment | |||
* @param buffer Buffer to clear | |||
* @param begin The starting point | |||
* @param end The ending point | |||
*/ | |||
private void _clear (byte[] buffer, int begin, int end) { | |||
for (int i=begin ; i<end && i<buffer.length ; ++i) | |||
buffer[i] = 0; | |||
} | |||
/** | |||
* Copy a buffer to another | |||
* @param dest The destination buffer | |||
* @param src The source buffer | |||
* @return The number of bytes copied | |||
*/ | |||
private int _copy (byte[] dest, byte[] src) { | |||
if (dest.length >= src.length) { | |||
for (int i=0 ; i<src.length ; ++i) | |||
@@ -128,24 +221,35 @@ class Com { | |||
} | |||
return 0; | |||
} | |||
/**@}*/ | |||
} | |||
/** | |||
* @class | |||
* Class to represent client-server transaction data | |||
*/ | |||
class Transaction { | |||
byte[] code; | |||
byte[] response; | |||
long departure; | |||
long arrival; | |||
int size; | |||
byte[] code; /**< request code from client */ | |||
byte[] response; /**< response data from server */ | |||
long departure; /**< request time */ | |||
long arrival; /**< response time */ | |||
int size; /**< size of response data in bytes */ | |||
/** | |||
* Basic constructor | |||
* @param code Code to use | |||
* @param response Response buffer to use | |||
*/ | |||
Transaction (byte[] code, byte[] response) { | |||
this.code = code; | |||
this.response = response; | |||
departure = arrival = 0; | |||
size = 0; | |||
} | |||
/** | |||
* Get a copy of the response | |||
*/ | |||
byte[] getResponse() { | |||
return Arrays.copyOf(response, size); | |||
} | |||
@@ -1,25 +1,49 @@ | |||
/** | |||
* @file Echo.java | |||
* | |||
* @author Christos Choutouridis AEM:8997 | |||
* @email cchoutou@ece.auth.gr | |||
*/ | |||
package net.hoo2.auth.vmodem; | |||
/** | |||
* @class Echo | |||
* | |||
* Class to used for the echo sequence | |||
*/ | |||
class Echo { | |||
static final int ECHO_DURATION_DEFAULT = 240; | |||
static final int ECHO_BUFFER_SIZE = 256; | |||
static final String ECHO_BEGIN = "PSTART"; | |||
static final String ECHO_END = "PSTOP"; | |||
private Com com_; | |||
private Log log_; | |||
private Transaction transaction_; | |||
private int duration_; | |||
private byte[] code_; | |||
static final int ECHO_DURATION_DEFAULT = 240; /**< Default duration for the sequence */ | |||
static final int ECHO_BUFFER_SIZE = 256; /**< Echo buffer size */ | |||
static final String ECHO_BEGIN = "PSTART"; /**< Begin pattern of the response */ | |||
static final String ECHO_END = "PSTOP"; /**< End pattern of the response */ | |||
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[] code_; /**< The desired code for the session */ | |||
/** | |||
* Basic constructor | |||
* @param com The Communication module to use | |||
* @param log The logging module to use | |||
* @param code The code to use | |||
* @param duration The duration to use | |||
*/ | |||
Echo (Com com, Log log, byte[] code, int duration) { | |||
com_ = com; | |||
log_ = log; | |||
duration_ = duration; | |||
// Allocate memory for the response | |||
transaction_= new Transaction(null, new byte[ECHO_BUFFER_SIZE]); | |||
code_ = code; | |||
} | |||
/** | |||
* Functionality to drain the response buffer for the welcome message | |||
* from the server | |||
* @param code The code that we will use (for printing, not sending) | |||
*/ | |||
void caption (byte[] code) { | |||
String line; | |||
@@ -31,6 +55,10 @@ class Echo { | |||
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; | |||
@@ -1,31 +1,48 @@ | |||
/** | |||
* @file GPS.java | |||
* | |||
* @author Christos Choutouridis AEM:8997 | |||
* @email cchoutou@ece.auth.gr | |||
*/ | |||
package net.hoo2.auth.vmodem; | |||
/** @name imports */ | |||
/** @{ */ | |||
import java.util.Arrays; | |||
/** @} */ | |||
/** | |||
* @class GPS | |||
* | |||
* Class to used for the GPS session | |||
*/ | |||
class GPS { | |||
static final int GPS_BUFFER_SIZE = 256; | |||
static final String GPS_BEGIN = "START ITHAKI GPS TRACKING"; | |||
static final String GPS_END = "STOP ITHAKI GPS TRACKING"; | |||
static final int GPS_USE_TRACK = 1; | |||
static final String GPS_TRACK_PREFIX = "R="; | |||
static final String GPS_IMAGE_PREFIX = "T="; | |||
static final int GPS_MAX_POINTS = 9; | |||
static final int GPS_COORDINATES_SIZE = 6; | |||
static final int GPS_BUFFER_SIZE = 256; /**< GPS trace buffer size */ | |||
static final String GPS_BEGIN = "START ITHAKI GPS TRACKING"; /**< starting pattern */ | |||
static final String GPS_END = "STOP ITHAKI GPS TRACKING"; /**< ending pattern */ | |||
static final int GPS_USE_TRACK = 1; /**< Which track to use (given) */ | |||
static final String GPS_TRACK_PREFIX = "R="; /**< GPS command track request prefix */ | |||
static final String GPS_IMAGE_PREFIX = "T="; /**< GPS command image request prefix */ | |||
static final int GPS_MAX_POINTS = 9; /**< Maximum points (given) */ | |||
static final int GPS_COORDINATES_SIZE = 6; /**< Coordinates size */ | |||
static final int GPS_LATITUDE_BEGIN = 17; | |||
static final int GPS_LATITUDE_END = 28; | |||
static final int GPS_LONGITUDE_BEGIN= 29; | |||
static final int GPS_LONGITUDE_END = 41; | |||
static final int GPS_LATITUDE_BEGIN = 17; /**< The latitude sequence string position */ | |||
static final int GPS_LATITUDE_END = 28; /**< The end of latitude sequence string position */ | |||
static final int GPS_LONGITUDE_BEGIN= 29; /**< The longitude sequence string position */ | |||
static final int GPS_LONGITUDE_END = 41; /**< The end of longitude sequence string position */ | |||
private Com com_; | |||
private Log log_; | |||
private Transaction transaction_; | |||
private byte[] code_; | |||
private int start_; | |||
private int duration_; | |||
private int points_; | |||
private byte[] coordinates_; | |||
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 byte[] code_; /**< The desired code for the session */ | |||
private int start_; /**< Starting point [sec] */ | |||
private int duration_; /**< Duration of requested trace */ | |||
private int points_; /**< Number of points to fetch from the above trace */ | |||
private byte[] coordinates_; /**< Coordinates buffer */ | |||
/** | |||
* Basic constructor | |||
*/ | |||
GPS (Com com, Log log, byte[] code, int start, int duration, int points) { | |||
com_ = com; | |||
log_ = log; | |||
@@ -37,6 +54,10 @@ class GPS { | |||
coordinates_= new byte[GPS_COORDINATES_SIZE]; | |||
} | |||
/** | |||
* Functionality to drain the response buffer for the welcome message | |||
* from the server | |||
*/ | |||
void caption () { | |||
String line; | |||
@@ -49,10 +70,15 @@ class GPS { | |||
log_.out(line); | |||
} | |||
/** | |||
* Main transaction loop. It send requests to server, get the response | |||
* and log the procedure while doing it. | |||
* @return the image request code to pass to image module | |||
*/ | |||
String run () { | |||
String code, image_code; | |||
String line; | |||
log_.out("Get traces"); | |||
image_code = new String(code_); | |||
for (int trace =start_ ; trace < start_+duration_ ; trace += duration_/points_) { | |||
@@ -72,7 +98,15 @@ class GPS { | |||
} | |||
return image_code; | |||
} | |||
/** @name private helper API */ | |||
/** @{ */ | |||
/** | |||
* Extract coordinates from response | |||
* @param stream The stream to search | |||
* @return The coordinates buffer | |||
*/ | |||
private byte[] _get_coordinates (byte[] stream) { | |||
int start = Com.detect(stream, "GPGGA".getBytes(), stream.length); | |||
double latitude = _nmea2dec (Double.valueOf( | |||
@@ -95,10 +129,15 @@ class GPS { | |||
- coordinates_[4]/60.0)*3600); // latitude " | |||
return coordinates_; | |||
} | |||
/** | |||
* A helper to convert the NMEA format to canonical | |||
* decimal coordinate format | |||
*/ | |||
double _nmea2dec (double c) { | |||
int d = (int)c/100; | |||
c -= d*100; | |||
return d + (c/60); | |||
} | |||
/** @} */ | |||
} |
@@ -1,30 +1,59 @@ | |||
/** | |||
* @file Image.java | |||
* | |||
* @author Christos Choutouridis AEM:8997 | |||
* @email cchoutou@ece.auth.gr | |||
*/ | |||
package net.hoo2.auth.vmodem; | |||
/** @name imports */ | |||
/** @{ */ | |||
import java.io.*; | |||
/** @} */ | |||
/** | |||
* @class Image | |||
* | |||
* Class to used for the error free and non error free image requests | |||
*/ | |||
class Image { | |||
static final int IMAGE_BUFFER_SIZE = 256*1024; | |||
static final byte[] IMAGE_BEGIN = {(byte)0xFF, (byte)0xD8}; | |||
static final byte[] IMAGE_END = {(byte)0xFF, (byte)0xD9}; | |||
static final int IMAGE_BUFFER_SIZE = 256*1024; /**< image buffer size */ | |||
static final byte[] IMAGE_BEGIN = {(byte)0xFF, (byte)0xD8}; /**< jpeg image begin pattern */ | |||
static final byte[] IMAGE_END = {(byte)0xFF, (byte)0xD9}; /**< jpeg image end pattern */ | |||
private Com com_; | |||
private Log log_; | |||
private Transaction transaction_; | |||
private String filename_; | |||
private int items_; | |||
private byte[] code_; | |||
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 String filename_; /**< The filename to store */ | |||
private int items_; /**< how many images to fetch */ | |||
private byte[] code_; /**< The image request code for the virtual lab */ | |||
/** | |||
* Basic constructor | |||
* @param com The com module to use | |||
* @param log The log module to use | |||
* @param code The request code | |||
* @param filename The filename | |||
* @param items How many items to fetch | |||
*/ | |||
Image (Com com, Log log, byte[] code, String filename, int items) { | |||
com_ = com; | |||
log_ = log; | |||
// Allocate memory for the response | |||
transaction_= new Transaction(null, new byte[IMAGE_BUFFER_SIZE]); | |||
filename_ = filename; | |||
items_ = items; | |||
code_ = code; | |||
} | |||
/** Get function for the code */ | |||
void code (byte[] code) { code_ = code; } | |||
/** | |||
* Functionality to drain the response buffer for the welcome message | |||
* from the server | |||
* @param code The code that we will use (for printing, not sending) | |||
*/ | |||
void caption (byte[] code) { | |||
String line; | |||
@@ -35,12 +64,17 @@ class Image { | |||
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 () { | |||
String file, line; | |||
BufferedOutputStream ostream; | |||
for (int i =1 ; i<= items_ ; ++i) { | |||
// Make the filename string | |||
if (items_>1) | |||
file = filename_ + "_" + i + ".jpg"; | |||
else | |||
@@ -1,19 +1,42 @@ | |||
/** | |||
* @file Log.java | |||
* | |||
* @author Christos Choutouridis AEM:8997 | |||
* @email cchoutou@ece.auth.gr | |||
*/ | |||
package net.hoo2.auth.vmodem; | |||
/** @name imports */ | |||
/** @{ */ | |||
import java.io.IOException; | |||
import java.io.PrintWriter; | |||
/** @} */ | |||
/** | |||
* @class Log | |||
* | |||
* A common log functionality class for all sessions | |||
*/ | |||
class Log { | |||
private String logfile_; | |||
private boolean verbose_; | |||
private PrintWriter writer_; | |||
private String logfile_; /**< The log file name */ | |||
private boolean verbose_; /**< The desired verbosity (for the console)*/ | |||
private PrintWriter writer_; /**< A buffered writer to use for streaming */ | |||
/** | |||
* Basic constructor | |||
* @param logfile The log filename | |||
* @param verbose The desired verbosity (for the console) | |||
*/ | |||
Log (String logfile, boolean verbose) { | |||
logfile_ = logfile; | |||
verbose_ = verbose; | |||
} | |||
/** | |||
* Try to open the log file | |||
* @return The status of the operation | |||
*/ | |||
boolean open () { | |||
if (logfile_ != null) { | |||
try { | |||
@@ -26,11 +49,20 @@ class Log { | |||
} | |||
return true; | |||
} | |||
/** | |||
* Try to open a log file | |||
* @param logfile The log file to open | |||
* @return The status of the operation | |||
*/ | |||
boolean open (String logfile) { | |||
logfile_ = logfile; | |||
return open(); | |||
} | |||
/** | |||
* Close the opened file | |||
* @return The status of the operation | |||
*/ | |||
boolean close () { | |||
try { | |||
if (writer_ != null) | |||
@@ -40,17 +72,30 @@ class Log { | |||
} | |||
return true; | |||
} | |||
/** | |||
* Log to file and print to console | |||
* @param line The line to log | |||
* @param out Console output request flag. If true, echo the line to console | |||
*/ | |||
void write (String line, boolean out) { | |||
if (logfile_ != null) writer_.println(line); | |||
if (verbose_ || out) System.out.println(line); | |||
} | |||
/** | |||
* Log to file and print to console | |||
* @param line The line to log | |||
*/ | |||
void write (String line) { | |||
if (logfile_ != null) writer_.println(line); | |||
if (verbose_) System.out.println(line); | |||
} | |||
/** | |||
* Echo the line to console | |||
* @param line The line to print | |||
*/ | |||
void out (String line) { | |||
if (verbose_) System.out.println(line); | |||
} | |||
@@ -10,7 +10,7 @@ package net.hoo2.auth.vmodem; | |||
/** @name imports */ | |||
/** @{ */ | |||
import org.apache.commons.cli.*; | |||
import org.apache.commons.cli.*; /**< command line utility */ | |||
/** @} */ | |||
@@ -19,31 +19,35 @@ import org.apache.commons.cli.*; | |||
* | |||
* @brief This is the main control class of the program. | |||
* | |||
* This class includes the main function.Using this class's api | |||
* the user can ... | |||
* This class includes the main function which read the user input | |||
* and create the apropriate object for the requested sequence to | |||
* retrieve data. | |||
*/ | |||
public class VirtualModem { | |||
/** @name Data */ | |||
/** @{ */ | |||
CommandLine line; | |||
CommandLineParser parser; | |||
Options options; | |||
HelpFormatter formatter; | |||
Com com; | |||
Log log; | |||
CommandLine line; /**< Command line for the argument list */ | |||
CommandLineParser parser; /**< Parser for the argument list */ | |||
Options options; /**< Option configuration container */ | |||
HelpFormatter formatter; /**< An extra helper for -h */ | |||
Com com; /**< Reference to basic configuration module */ | |||
Log log; /**< Reference to basig logging module */ | |||
/** @} */ | |||
/** @name constructors */ | |||
/** @{ */ | |||
/** | |||
* @brief The main constructor of the class | |||
* We allocate memory for the data needed for the command line | |||
*/ | |||
public VirtualModem () { | |||
parser = new DefaultParser(); | |||
options = new Options(); | |||
formatter = new HelpFormatter(); | |||
com = new Com(); | |||
Option verb = new Option ("v", "verbose", false, "Be more verbose"); | |||
// Create argument options and a basic help file | |||
// for future use. | |||
Option verb = new Option ("v", "verbose", false, "Be more verbose to the console"); | |||
Option help = new Option ("h", "help", false, "Print this message"); | |||
Option timeout = Option.builder("t") | |||
.longOpt("timeout") | |||
@@ -60,27 +64,40 @@ public class VirtualModem { | |||
Option log = Option.builder("l") | |||
.longOpt("log") | |||
.hasArg() | |||
.desc("Log file name") | |||
.desc("Log file name to use") | |||
.build(); | |||
Option echo = Option.builder("e") | |||
.longOpt("echo") | |||
.numberOfArgs(2) | |||
.desc ("Request echo sequence") | |||
.desc ("Request echo sequence where <arg> = <1> <2>\n" | |||
+ " <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") | |||
.numberOfArgs(3) | |||
.desc ("Request aqr sequence") | |||
.desc ("Request aqr 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]") | |||
.build(); | |||
Option img = Option.builder("g") | |||
.longOpt("img") | |||
.numberOfArgs(3) | |||
.desc("Request an image sequence") | |||
.desc("Request an image sequence where <arg> = <1> <2> <3>\n" | |||
+ " <1>: The image requested code from virtual lab\n" | |||
+ " <2>: The filename to use for storing the image (without .jpg)\n" | |||
+ " <3>: The requested images to fetch.") | |||
.build(); | |||
Option gps = Option.builder("p") | |||
.longOpt("gps") | |||
.numberOfArgs(5) | |||
.desc("Request a GPS sequence") | |||
.numberOfArgs(5) // G8164 10 800 8 gps_10_800 | |||
.desc("Request a GPS sequence where <arg> = <1> <2> <3> <4>\n" | |||
+ " <1>: The gps requested code from virtual lab\n" | |||
+ " <2>: The time from trace to use as starting point [sec]\n" | |||
+ " <3>: The time duration for the trace to fetch [sec]\n" | |||
+ " <4>: The number of points to fetch from the above trace\n" | |||
+ " <5>: The filename to use for storing the image (without .jpg)") | |||
.build(); | |||
options.addOption(verb); | |||
options.addOption(help); | |||
@@ -92,8 +109,15 @@ public class VirtualModem { | |||
options.addOption(img); | |||
options.addOption(gps); | |||
} | |||
/** @} */ | |||
/** @name private api */ | |||
/**@{*/ | |||
/** | |||
* parse the command line arguments | |||
* @param args the arguments to parse | |||
* @return the status of the operation | |||
*/ | |||
private boolean getCmdOptions (String[] args) { | |||
try { | |||
// parse the command line arguments | |||
@@ -106,10 +130,19 @@ public class VirtualModem { | |||
} | |||
return true; | |||
} | |||
/** | |||
* Dispatch the correct functionality based on arguments | |||
* @return the status of the operation (currently true) | |||
*/ | |||
private boolean commandDispatcher () { | |||
boolean verbose = false; | |||
if (line.hasOption("help")) { | |||
formatter.printHelp( "virtualModem", options ); | |||
return true; | |||
} | |||
// Get log and verbose options first | |||
if (line.hasOption("verbose")) | |||
verbose = true; | |||
@@ -129,68 +162,64 @@ public class VirtualModem { | |||
} | |||
// Execution dispatcher | |||
do { | |||
if (line.hasOption("help")) { | |||
formatter.printHelp( "virtualModem", options ); | |||
break; | |||
} | |||
if (line.hasOption("echo")) { | |||
byte[] code = line.getOptionValues("echo")[0].getBytes(); | |||
Echo e = new Echo(com, log, code, | |||
Integer.valueOf(line.getOptionValues("echo")[1])); | |||
if (com.open()) { | |||
e.caption(code); | |||
e.run(); | |||
com.close(); | |||
} | |||
if (line.hasOption("echo")) { | |||
byte[] code = line.getOptionValues("echo")[0].getBytes(); | |||
Echo e = new Echo(com, log, code, | |||
Integer.valueOf(line.getOptionValues("echo")[1])); | |||
if (com.open()) { | |||
e.caption(code); | |||
e.run(); | |||
com.close(); | |||
} | |||
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])); | |||
if (com.open()) { | |||
a.caption(ack, nack); | |||
a.run(); | |||
com.close(); | |||
} | |||
} | |||
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])); | |||
if (com.open()) { | |||
a.caption(ack, nack); | |||
a.run(); | |||
com.close(); | |||
} | |||
else if (line.hasOption("img")) { | |||
byte[] code = line.getOptionValues("img")[0].getBytes(); | |||
Image im = new Image (com, log, code, | |||
line.getOptionValues("img")[1], | |||
Integer.valueOf(line.getOptionValues("img")[2])); | |||
if (com.open()) { | |||
im.caption(code); | |||
im.run(); | |||
com.close(); | |||
} | |||
} | |||
else if (line.hasOption("img")) { | |||
byte[] code = line.getOptionValues("img")[0].getBytes(); | |||
Image im = new Image (com, log, code, | |||
line.getOptionValues("img")[1], | |||
Integer.valueOf(line.getOptionValues("img")[2])); | |||
if (com.open()) { | |||
im.caption(code); | |||
im.run(); | |||
com.close(); | |||
} | |||
else if (line.hasOption("gps")) { | |||
byte[] code = line.getOptionValues("gps")[0].getBytes(); | |||
GPS g = new GPS (com, log, code, | |||
Integer.valueOf(line.getOptionValues("gps")[1]), | |||
Integer.valueOf(line.getOptionValues("gps")[2]), | |||
Integer.valueOf(line.getOptionValues("gps")[3])); | |||
Image im = new Image (com, log, null, | |||
line.getOptionValues("gps")[4], 1); | |||
if (com.open()) { | |||
g.caption(); | |||
im.code(g.run().getBytes()); | |||
im.run(); | |||
com.close(); | |||
} | |||
} | |||
else if (line.hasOption("gps")) { | |||
byte[] code = line.getOptionValues("gps")[0].getBytes(); | |||
GPS g = new GPS (com, log, code, | |||
Integer.valueOf(line.getOptionValues("gps")[1]), | |||
Integer.valueOf(line.getOptionValues("gps")[2]), | |||
Integer.valueOf(line.getOptionValues("gps")[3])); | |||
Image im = new Image (com, log, null, | |||
line.getOptionValues("gps")[4], 1); | |||
if (com.open()) { | |||
g.caption(); | |||
im.code(g.run().getBytes()); | |||
im.run(); | |||
com.close(); | |||
} | |||
} while (false); | |||
} | |||
log.close(); | |||
return true; | |||
} | |||
/**@}*/ | |||
/** | |||
* @brief Main | |||
* | |||
* @brief Main function | |||
*/ | |||
public static void main(String[] args) { | |||
// allocate the main object | |||
@@ -199,9 +228,8 @@ public class VirtualModem { | |||
// prepare command line input | |||
if (vmodem.getCmdOptions (args) != true) | |||
return; | |||
// Call the requested functionality | |||
if (vmodem.commandDispatcher() != true) | |||
return; | |||
} | |||
} |