Code comments

This commit is contained in:
Christos Houtouridis 2018-12-08 20:35:58 +02:00
parent b212aa07d4
commit fb39a2633b
17 changed files with 14982 additions and 174 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
*.project *.project
*.classpath *.classpath
*.pdf *.pdf
*.doc

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,47 @@
/**
* @file AQR.java
*
* @author Christos Choutouridis AEM:8997
* @email cchoutou@ece.auth.gr
*/
package net.hoo2.auth.vmodem; package net.hoo2.auth.vmodem;
/** @name imports */
/** @{ */
import java.util.*; import java.util.*;
/** @} */
/**
* @class AQR
*
* Class to used for the ACK-NACK sequence
*/
class AQR { class AQR {
static final int AQ_DURATION_DEFAULT = 240; static final int AQ_DURATION_DEFAULT = 240; /**< Default duration for the sequence */
static final int AQR_BUFFER_SIZE = 256; static final int AQR_BUFFER_SIZE = 256; /**< AQR buffer size */
static final String AQR_BEGIN = "PSTART"; static final String AQR_BEGIN = "PSTART"; /**< Begin pattern of the response */
static final String AQR_END = "PSTOP"; static final String AQR_END = "PSTOP"; /**< End pattern of the response */
static final int AQR_SEQUENCE_BEGIN = 31; static final int AQR_SEQUENCE_BEGIN = 31; /**< The response sequence string position */
static final int AQR_SEQUENCE_END = 47; static final int AQR_SEQUENCE_END = 47; /**< The end of response sequence string position */
static final int AQR_CRC_BEGIN = 49; static final int AQR_CRC_BEGIN = 49; /**< The response crc string position */
static final int AQR_CRC_END = 52; static final int AQR_CRC_END = 52; /**< The end of response crc string position */
private Com com_; private Com com_; /**< Reference to communication module */
private Log log_; private Log log_; /**< Reference to logging module */
private Transaction transaction_; private Transaction transaction_; /**< A transaction object to used as a buffer for all requests */
private int duration_; private int duration_; /**< The desired duration for the session */
private byte[] ack_; private byte[] ack_; /**< The desired ACK code for the session */
private byte[] nack_; 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) { AQR (Com com, Log log, byte[] ack, byte[] nack, int duration) {
com_ = com; com_ = com;
log_ = log; log_ = log;
@ -29,6 +51,12 @@ class AQR {
nack_ = nack; 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) { void caption (byte[] ack, byte[] nack) {
String line; String line;
@ -40,6 +68,10 @@ class AQR {
log_.out(line); log_.out(line);
} }
/**
* Main transaction loop. It send requests to server, get the response
* and log the procedure while doing it.
*/
void run () { void run () {
long start; long start;
long now; long now;
@ -51,12 +83,13 @@ class AQR {
start = System.currentTimeMillis(); start = System.currentTimeMillis();
do { do {
// Check if the previous transaction was error-free
if (good) if (good)
transaction_ = com_.request(transaction_, ack_, AQR_BEGIN.getBytes(), AQR_END.getBytes(), false); transaction_ = com_.request(transaction_, ack_, AQR_BEGIN.getBytes(), AQR_END.getBytes(), false);
else else
transaction_ = com_.request(transaction_, nack_, AQR_BEGIN.getBytes(), AQR_END.getBytes(), false); transaction_ = com_.request(transaction_, nack_, AQR_BEGIN.getBytes(), AQR_END.getBytes(), false);
good = (_crc_check(transaction_.response)) ? true : false; good = (_crc_check(transaction_.response)) ? true : false; // crc check the response
bads = (good) ? 0 : bads+1; bads = (good) ? 0 : bads+1; // count the error strike
// delay calculation // delay calculation
if (prev && !good) mark = transaction_.departure; if (prev && !good) mark = transaction_.departure;
@ -74,6 +107,14 @@ class AQR {
} while (now - start < duration_*1000); } 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) { private boolean _crc_check (byte[] data) {
byte[] seq = Arrays.copyOfRange(data, AQR_SEQUENCE_BEGIN, AQR_SEQUENCE_END); byte[] seq = Arrays.copyOfRange(data, AQR_SEQUENCE_BEGIN, AQR_SEQUENCE_END);
int crc = Integer.valueOf( int crc = Integer.valueOf(
@ -81,10 +122,17 @@ class AQR {
return (crc == _crc(seq)) ? true : false; 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) { private int _crc (byte[] data) {
int calc =0; int calc =0;
for (int i=0 ; i<data.length ; ++i) for (int i=0 ; i<data.length ; ++i)
calc ^= data[i]; calc ^= data[i];
return calc; return calc;
} }
/**@} */
} }

View File

@ -1,17 +1,35 @@
/**
* @file Com.java
*
* @author Christos Choutouridis AEM:8997
* @email cchoutou@ece.auth.gr
*/
package net.hoo2.auth.vmodem; package net.hoo2.auth.vmodem;
/** @name imports */
/** @{ */
import java.util.Arrays; import java.util.Arrays;
import ithakimodem.*; 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 { class Com {
static final int SPEED_DEFAULT = 48000; static final int SPEED_DEFAULT = 48000; /**< default communication speed [bps] */
static final int TIMEOUT_DEFAULT = 2000; static final int TIMEOUT_DEFAULT = 2000; /**< default timeout values [sec] */
static final String URL_DEFAULT = "ithaki"; static final String URL_DEFAULT = "ithaki"; /**< Default destination. Ithaki of-course */
private Modem modem_; private Modem modem_; /**< Ref to Modem */
private int speed_; private int speed_; /**< Communication speed [bps] */
private int timeout_; private int timeout_; /**< communication timeout [sec] */
/**
* Basic constructor
*/
Com () { Com () {
modem_ = new Modem(); modem_ = new Modem();
speed_ = SPEED_DEFAULT; speed_ = SPEED_DEFAULT;
@ -19,6 +37,14 @@ class Com {
modem_.setSpeed(speed_); modem_.setSpeed(speed_);
modem_.setTimeout(timeout_); 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) { Com (Log log, int speed, int timeout) {
modem_ = new Modem(); modem_ = new Modem();
speed_ = speed; speed_ = speed;
@ -27,62 +53,95 @@ class Com {
modem_.setTimeout(timeout_); modem_.setTimeout(timeout_);
} }
// get/set /** @name Mutator interface */
/**@{ */
/** Get the current timeout value [sec] */
int timeout () { return timeout_; } int timeout () { return timeout_; }
/** Set the timeout value [sec] */
void timeout (int timeout) { void timeout (int timeout) {
if (timeout_ != timeout) { if (timeout_ != timeout) {
timeout_ = timeout; timeout_ = timeout;
modem_.setTimeout(timeout_); modem_.setTimeout(timeout_);
} }
} }
/** Get the current speed [bps] */
int speed () { return speed_; } int speed () { return speed_; }
/** Set the speed [bps] */
void speed (int speed) { void speed (int speed) {
if (speed_ != speed) { if (speed_ != speed) {
speed_ = speed; speed_ = speed;
modem_.setSpeed(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); } boolean open (String url) { return modem_.open(url); }
/** Open a communication channel with Ithaki */
boolean open () { return modem_.open(URL_DEFAULT); } boolean open () { return modem_.open(URL_DEFAULT); }
/** Close the connection */
boolean close() { return modem_.close(); } 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) { Transaction request (Transaction data, byte[] code, byte[] begin, byte[] end, boolean bin) {
int ch =0; int ch =0;
boolean have_begin = (begin != null) ? false : true; boolean have_begin = (begin != null) ? false : true;
boolean incoming = false; boolean incoming = false;
// Clear the receive buffer first
_clear (data.response, 0, data.response.length); _clear (data.response, 0, data.response.length);
if (code != null) { if (code != null) {
data.code = code; // if we have a request
modem_.write(data.code); 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'); modem_.write((int)'\r');
data.departure = System.currentTimeMillis();// - (long)((8*(data.code.length+1))*(1000.0/speed_)); data.departure = System.currentTimeMillis();// - (long)((8*(data.code.length+1))*(1000.0/speed_));
} }
// main receive loop
data.size =0; data.size =0;
do { do {
// escape guard for memory protection
if (data.size >= data.response.length) { if (data.size >= data.response.length) {
data.size =0; data.size =0;
return data; return data;
} }
// read the data byte from server
try { try {
ch = modem_.read(); ch = modem_.read();
} }
catch (Exception e) { catch (Exception e) {
// Oops!!!! something went wrong. Break and return :(
System.err.println (e.getMessage()); System.err.println (e.getMessage());
data.size =0; data.size =0;
return data; return data;
} }
if (!incoming) { if (!incoming) {
// first byte triggered. mark the time
incoming = true; incoming = true;
data.arrival = System.currentTimeMillis();// - (long)(8*(1000.0/speed_)); 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 (!have_begin && (detect(data.response, begin, data.size) != -1)) {
// If begin pattern detected, start over.
_clear(data.response, 0, data.size); _clear(data.response, 0, data.size);
data.size = _copy (data.response, begin); data.size = _copy (data.response, begin);
have_begin = true; 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; 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) { static int detect (byte[] data, byte[] pattern, int max) {
if (pattern != null) { if (pattern != null) {
for (int i =0 ; i<max && i<data.length - pattern.length; ++i) { for (int i =0 ; i<max && i<data.length - pattern.length; ++i) {
@ -114,12 +192,27 @@ class Com {
} }
return -1; 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) { private void _clear (byte[] buffer, int begin, int end) {
for (int i=begin ; i<end && i<buffer.length ; ++i) for (int i=begin ; i<end && i<buffer.length ; ++i)
buffer[i] = 0; 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) { private int _copy (byte[] dest, byte[] src) {
if (dest.length >= src.length) { if (dest.length >= src.length) {
for (int i=0 ; i<src.length ; ++i) for (int i=0 ; i<src.length ; ++i)
@ -128,17 +221,25 @@ class Com {
} }
return 0; return 0;
} }
/**@}*/
} }
/**
* @class
* Class to represent client-server transaction data
*/
class Transaction { class Transaction {
byte[] code; byte[] code; /**< request code from client */
byte[] response; byte[] response; /**< response data from server */
long departure; long departure; /**< request time */
long arrival; long arrival; /**< response time */
int size; 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) { Transaction (byte[] code, byte[] response) {
this.code = code; this.code = code;
this.response = response; this.response = response;
@ -146,6 +247,9 @@ class Transaction {
size = 0; size = 0;
} }
/**
* Get a copy of the response
*/
byte[] getResponse() { byte[] getResponse() {
return Arrays.copyOf(response, size); return Arrays.copyOf(response, size);
} }

View File

@ -1,25 +1,49 @@
/**
* @file Echo.java
*
* @author Christos Choutouridis AEM:8997
* @email cchoutou@ece.auth.gr
*/
package net.hoo2.auth.vmodem; package net.hoo2.auth.vmodem;
/**
* @class Echo
*
* Class to used for the echo sequence
*/
class Echo { class Echo {
static final int ECHO_DURATION_DEFAULT = 240; static final int ECHO_DURATION_DEFAULT = 240; /**< Default duration for the sequence */
static final int ECHO_BUFFER_SIZE = 256; static final int ECHO_BUFFER_SIZE = 256; /**< Echo buffer size */
static final String ECHO_BEGIN = "PSTART"; static final String ECHO_BEGIN = "PSTART"; /**< Begin pattern of the response */
static final String ECHO_END = "PSTOP"; static final String ECHO_END = "PSTOP"; /**< End pattern of the response */
private Com com_; private Com com_; /**< Reference to communication module */
private Log log_; private Log log_; /**< Reference to logging module */
private Transaction transaction_; private Transaction transaction_; /**< A transaction object to used as a buffer for all requests */
private int duration_; private int duration_; /**< The desired duration for the session */
private byte[] code_; 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) { Echo (Com com, Log log, byte[] code, int duration) {
com_ = com; com_ = com;
log_ = log; log_ = log;
duration_ = duration; duration_ = duration;
// Allocate memory for the response
transaction_= new Transaction(null, new byte[ECHO_BUFFER_SIZE]); transaction_= new Transaction(null, new byte[ECHO_BUFFER_SIZE]);
code_ = 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) { void caption (byte[] code) {
String line; String line;
@ -31,6 +55,10 @@ class Echo {
log_.out(line); log_.out(line);
} }
/**
* Main transaction loop. It send requests to server, get the response
* and log the procedure while doing it.
*/
void run () { void run () {
long start; long start;
long now; long now;

View File

@ -1,31 +1,48 @@
/**
* @file GPS.java
*
* @author Christos Choutouridis AEM:8997
* @email cchoutou@ece.auth.gr
*/
package net.hoo2.auth.vmodem; package net.hoo2.auth.vmodem;
/** @name imports */
/** @{ */
import java.util.Arrays; import java.util.Arrays;
/** @} */
/**
* @class GPS
*
* Class to used for the GPS session
*/
class GPS { class GPS {
static final int GPS_BUFFER_SIZE = 256; static final int GPS_BUFFER_SIZE = 256; /**< GPS trace buffer size */
static final String GPS_BEGIN = "START ITHAKI GPS TRACKING"; static final String GPS_BEGIN = "START ITHAKI GPS TRACKING"; /**< starting pattern */
static final String GPS_END = "STOP ITHAKI GPS TRACKING"; static final String GPS_END = "STOP ITHAKI GPS TRACKING"; /**< ending pattern */
static final int GPS_USE_TRACK = 1; static final int GPS_USE_TRACK = 1; /**< Which track to use (given) */
static final String GPS_TRACK_PREFIX = "R="; static final String GPS_TRACK_PREFIX = "R="; /**< GPS command track request prefix */
static final String GPS_IMAGE_PREFIX = "T="; static final String GPS_IMAGE_PREFIX = "T="; /**< GPS command image request prefix */
static final int GPS_MAX_POINTS = 9; static final int GPS_MAX_POINTS = 9; /**< Maximum points (given) */
static final int GPS_COORDINATES_SIZE = 6; static final int GPS_COORDINATES_SIZE = 6; /**< Coordinates size */
static final int GPS_LATITUDE_BEGIN = 17; static final int GPS_LATITUDE_BEGIN = 17; /**< The latitude sequence string position */
static final int GPS_LATITUDE_END = 28; static final int GPS_LATITUDE_END = 28; /**< The end of latitude sequence string position */
static final int GPS_LONGITUDE_BEGIN= 29; static final int GPS_LONGITUDE_BEGIN= 29; /**< The longitude sequence string position */
static final int GPS_LONGITUDE_END = 41; static final int GPS_LONGITUDE_END = 41; /**< The end of longitude sequence string position */
private Com com_; private Com com_; /**< Reference to communication module */
private Log log_; private Log log_; /**< Reference to logging module */
private Transaction transaction_; private Transaction transaction_; /**< A transaction object to used as a buffer for all requests */
private byte[] code_; private byte[] code_; /**< The desired code for the session */
private int start_; private int start_; /**< Starting point [sec] */
private int duration_; private int duration_; /**< Duration of requested trace */
private int points_; private int points_; /**< Number of points to fetch from the above trace */
private byte[] coordinates_; private byte[] coordinates_; /**< Coordinates buffer */
/**
* Basic constructor
*/
GPS (Com com, Log log, byte[] code, int start, int duration, int points) { GPS (Com com, Log log, byte[] code, int start, int duration, int points) {
com_ = com; com_ = com;
log_ = log; log_ = log;
@ -37,6 +54,10 @@ class GPS {
coordinates_= new byte[GPS_COORDINATES_SIZE]; coordinates_= new byte[GPS_COORDINATES_SIZE];
} }
/**
* Functionality to drain the response buffer for the welcome message
* from the server
*/
void caption () { void caption () {
String line; String line;
@ -49,6 +70,11 @@ class GPS {
log_.out(line); 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 run () {
String code, image_code; String code, image_code;
String line; String line;
@ -73,6 +99,14 @@ class GPS {
return image_code; 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) { private byte[] _get_coordinates (byte[] stream) {
int start = Com.detect(stream, "GPGGA".getBytes(), stream.length); int start = Com.detect(stream, "GPGGA".getBytes(), stream.length);
double latitude = _nmea2dec (Double.valueOf( double latitude = _nmea2dec (Double.valueOf(
@ -96,9 +130,14 @@ class GPS {
return coordinates_; return coordinates_;
} }
/**
* A helper to convert the NMEA format to canonical
* decimal coordinate format
*/
double _nmea2dec (double c) { double _nmea2dec (double c) {
int d = (int)c/100; int d = (int)c/100;
c -= d*100; c -= d*100;
return d + (c/60); return d + (c/60);
} }
/** @} */
} }

View File

@ -1,30 +1,59 @@
/**
* @file Image.java
*
* @author Christos Choutouridis AEM:8997
* @email cchoutou@ece.auth.gr
*/
package net.hoo2.auth.vmodem; package net.hoo2.auth.vmodem;
/** @name imports */
/** @{ */
import java.io.*; import java.io.*;
/** @} */
/**
* @class Image
*
* Class to used for the error free and non error free image requests
*/
class Image { class Image {
static final int IMAGE_BUFFER_SIZE = 256*1024; static final int IMAGE_BUFFER_SIZE = 256*1024; /**< image buffer size */
static final byte[] IMAGE_BEGIN = {(byte)0xFF, (byte)0xD8}; static final byte[] IMAGE_BEGIN = {(byte)0xFF, (byte)0xD8}; /**< jpeg image begin pattern */
static final byte[] IMAGE_END = {(byte)0xFF, (byte)0xD9}; static final byte[] IMAGE_END = {(byte)0xFF, (byte)0xD9}; /**< jpeg image end pattern */
private Com com_; private Com com_; /**< Reference to communication module */
private Log log_; private Log log_; /**< Reference to logging module */
private Transaction transaction_; private Transaction transaction_; /**< A transaction object to used as a buffer for all requests */
private String filename_; private String filename_; /**< The filename to store */
private int items_; private int items_; /**< how many images to fetch */
private byte[] code_; 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) { Image (Com com, Log log, byte[] code, String filename, int items) {
com_ = com; com_ = com;
log_ = log; log_ = log;
// Allocate memory for the response
transaction_= new Transaction(null, new byte[IMAGE_BUFFER_SIZE]); transaction_= new Transaction(null, new byte[IMAGE_BUFFER_SIZE]);
filename_ = filename; filename_ = filename;
items_ = items; items_ = items;
code_ = code; code_ = code;
} }
/** Get function for the code */
void code (byte[] code) { code_ = 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) { void caption (byte[] code) {
String line; String line;
@ -36,11 +65,16 @@ class Image {
log_.out(line); log_.out(line);
} }
/**
* Main transaction loop. It send requests to server, get the response
* and log the procedure while doing it.
*/
void run () { void run () {
String file, line; String file, line;
BufferedOutputStream ostream; BufferedOutputStream ostream;
for (int i =1 ; i<= items_ ; ++i) { for (int i =1 ; i<= items_ ; ++i) {
// Make the filename string
if (items_>1) if (items_>1)
file = filename_ + "_" + i + ".jpg"; file = filename_ + "_" + i + ".jpg";
else else

View File

@ -1,19 +1,42 @@
/**
* @file Log.java
*
* @author Christos Choutouridis AEM:8997
* @email cchoutou@ece.auth.gr
*/
package net.hoo2.auth.vmodem; package net.hoo2.auth.vmodem;
/** @name imports */
/** @{ */
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
/** @} */
/**
* @class Log
*
* A common log functionality class for all sessions
*/
class Log { class Log {
private String logfile_; private String logfile_; /**< The log file name */
private boolean verbose_; private boolean verbose_; /**< The desired verbosity (for the console)*/
private PrintWriter writer_; 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) { Log (String logfile, boolean verbose) {
logfile_ = logfile; logfile_ = logfile;
verbose_ = verbose; verbose_ = verbose;
} }
/**
* Try to open the log file
* @return The status of the operation
*/
boolean open () { boolean open () {
if (logfile_ != null) { if (logfile_ != null) {
try { try {
@ -26,11 +49,20 @@ class Log {
} }
return true; 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) { boolean open (String logfile) {
logfile_ = logfile; logfile_ = logfile;
return open(); return open();
} }
/**
* Close the opened file
* @return The status of the operation
*/
boolean close () { boolean close () {
try { try {
if (writer_ != null) if (writer_ != null)
@ -41,16 +73,29 @@ class Log {
return true; 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) { void write (String line, boolean out) {
if (logfile_ != null) writer_.println(line); if (logfile_ != null) writer_.println(line);
if (verbose_ || out) System.out.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) { void write (String line) {
if (logfile_ != null) writer_.println(line); if (logfile_ != null) writer_.println(line);
if (verbose_) System.out.println(line); if (verbose_) System.out.println(line);
} }
/**
* Echo the line to console
* @param line The line to print
*/
void out (String line) { void out (String line) {
if (verbose_) System.out.println(line); if (verbose_) System.out.println(line);
} }

View File

@ -10,7 +10,7 @@ package net.hoo2.auth.vmodem;
/** @name imports */ /** @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. * @brief This is the main control class of the program.
* *
* This class includes the main function.Using this class's api * This class includes the main function which read the user input
* the user can ... * and create the apropriate object for the requested sequence to
* retrieve data.
*/ */
public class VirtualModem { public class VirtualModem {
/** @name Data */ /** @name Data */
/** @{ */ /** @{ */
CommandLine line; CommandLine line; /**< Command line for the argument list */
CommandLineParser parser; CommandLineParser parser; /**< Parser for the argument list */
Options options; Options options; /**< Option configuration container */
HelpFormatter formatter; HelpFormatter formatter; /**< An extra helper for -h */
Com com; Com com; /**< Reference to basic configuration module */
Log log; 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 () { public VirtualModem () {
parser = new DefaultParser(); parser = new DefaultParser();
options = new Options(); options = new Options();
formatter = new HelpFormatter(); formatter = new HelpFormatter();
com = new Com(); com = new Com();
// Create argument options and a basic help file
Option verb = new Option ("v", "verbose", false, "Be more verbose"); // 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 help = new Option ("h", "help", false, "Print this message");
Option timeout = Option.builder("t") Option timeout = Option.builder("t")
.longOpt("timeout") .longOpt("timeout")
@ -60,27 +64,40 @@ public class VirtualModem {
Option log = Option.builder("l") Option log = Option.builder("l")
.longOpt("log") .longOpt("log")
.hasArg() .hasArg()
.desc("Log file name") .desc("Log file name to use")
.build(); .build();
Option echo = Option.builder("e") Option echo = Option.builder("e")
.longOpt("echo") .longOpt("echo")
.numberOfArgs(2) .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(); .build();
Option aqr = Option.builder("a") Option aqr = Option.builder("a")
.longOpt("aqr") .longOpt("aqr")
.numberOfArgs(3) .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(); .build();
Option img = Option.builder("g") Option img = Option.builder("g")
.longOpt("img") .longOpt("img")
.numberOfArgs(3) .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(); .build();
Option gps = Option.builder("p") Option gps = Option.builder("p")
.longOpt("gps") .longOpt("gps")
.numberOfArgs(5) .numberOfArgs(5) // G8164 10 800 8 gps_10_800
.desc("Request a GPS sequence") .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(); .build();
options.addOption(verb); options.addOption(verb);
options.addOption(help); options.addOption(help);
@ -92,8 +109,15 @@ public class VirtualModem {
options.addOption(img); options.addOption(img);
options.addOption(gps); 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) { private boolean getCmdOptions (String[] args) {
try { try {
// parse the command line arguments // parse the command line arguments
@ -107,9 +131,18 @@ public class VirtualModem {
return true; return true;
} }
/**
* Dispatch the correct functionality based on arguments
* @return the status of the operation (currently true)
*/
private boolean commandDispatcher () { private boolean commandDispatcher () {
boolean verbose = false; boolean verbose = false;
if (line.hasOption("help")) {
formatter.printHelp( "virtualModem", options );
return true;
}
// Get log and verbose options first // Get log and verbose options first
if (line.hasOption("verbose")) if (line.hasOption("verbose"))
verbose = true; verbose = true;
@ -129,11 +162,6 @@ public class VirtualModem {
} }
// Execution dispatcher // Execution dispatcher
do {
if (line.hasOption("help")) {
formatter.printHelp( "virtualModem", options );
break;
}
if (line.hasOption("echo")) { if (line.hasOption("echo")) {
byte[] code = line.getOptionValues("echo")[0].getBytes(); byte[] code = line.getOptionValues("echo")[0].getBytes();
Echo e = new Echo(com, log, code, Echo e = new Echo(com, log, code,
@ -183,14 +211,15 @@ public class VirtualModem {
com.close(); com.close();
} }
} }
} while (false);
log.close(); log.close();
return true; return true;
} }
/**@}*/
/** /**
* @brief Main * @brief Main function
*
*/ */
public static void main(String[] args) { public static void main(String[] args) {
// allocate the main object // allocate the main object
@ -199,9 +228,8 @@ public class VirtualModem {
// prepare command line input // prepare command line input
if (vmodem.getCmdOptions (args) != true) if (vmodem.getCmdOptions (args) != true)
return; return;
// Call the requested functionality
if (vmodem.commandDispatcher() != true) if (vmodem.commandDispatcher() != true)
return; return;
} }
} }