|
- %
- % Network programming Lab report source code
- %
- % authors:
- % Χρήστος Χουτουρίδης ΑΕΜ 8997
- % cchoutou@ece.auth.gr
-
-
- % Document configuration
- \newcommand{\ClassName}{Δίκτυα Υπολογιστών Ι}
- \newcommand{\DocTitle}{Κώδικας εφαρμογής}
- \newcommand{\InstructorName}{Δημήτριος Μητράκος}
- \newcommand{\InstructorMail}{mitrakos@eng.auth.gr}
- \newcommand{\CurrentDate}{\today}
-
- \input{AuthReport.tex}
-
- %\renewcommand{\AuthorName}{Χρήστος Χουτουρίδης}
- %\renewcommand{\AuthorMail}{cchoutou@ece.auth.gr}
- %\renewcommand{\AuthorAEM}{8997}
-
- \fancyhead[L]{\ClassName}
- \fancyhead[R]{Χρήστος Χουτουρίδης 8997}
-
- % Document
- % =================
- \begin{document}
-
- \FirstPage
-
- \tableofcontents
-
- \section{Περιγραφή}
- Για την ανάπτυξη του κώδικα χρησιμοποιήσαμε το περιβάλλον \eng{eclipse} και το \eng{openjdk} στην έκδοση 11.
- Επειδή η εφαρμογή λειτουργεί ως \eng{command line tool,} χρησιμοποιήσαμε ακόμα το \eng{commons-cli} από \href{http://commons.apache.org/proper/commons-cli/}{\eng{apache commons}} ώς εργαλείο ανάγνωσης των ορισμάτων του χρήστη.
- Η υλοποίηση της εφαρμογής είναι πολύ απλή.
- Δεν χρησιμοποιούμε \eng{interfaces} ή κληρονομικότητα.
- Αντίθετα έχουμε χωρίσει την εφαρμογή σε αυτόνομα αντικείμενα.
- Τα αντικείμενα \eng{Com} και \eng{Log} παρέχουν τις βασικές λειτουργίες για την επικοινωνία με τον \eng{server} και την έξοδο του προγράμματος αντίστοιχα.
- Τα αντικείμενα αυτά χρησιμοποιούνται απλώς μέσα υπόλοιπα.
- Χρησιμοποιούμε δηλαδή την απλούστερη δυνατή τεχνική (\eng{build by composition}).
-
- \par Τον κώδικα καθώς και την παραγόμενη τεκμηρίωσή του μέσω \eng{JavaDoc} μπορείτε να την βρείτε στο παραδοτέο αρχείο στους καταλόγους \eng{src} και \eng{doc.}
- Τέλος στο \href{https://git.hoo2.net/hoo2/virtualModem}{προσωπικό αποθετήριο} του συντάκτη υπάρχει όλος ο κώδικας της εφαρμογής, της εργασίας και της επεξεργασίας των αποτελεσμάτων.
- Παραθέτουμε παρακάτω τον κώδικα της εφαρμογής σε μορφή !!κειμένου!!, όπως αυτό ζητήθηκε από την εκφώνηση της εργασίας.
- Το κάθε κεφάλαιο αντιστοιχεί σε ξεχωριστό αρχείο του κώδικα.
-
- \selectlanguage{english}
- \titleformat{\section}[block]{\large\textbf}{\thesection.}{1em}{}
- \small
- \section{virtualModem.java}
- \begin{verbatim}
- /**
- * @file VirtualModem.java
- * @brief
- * Contain the Main class for the project VirtualModem
- *
- * Usage examples:
- * ==========================
- * java -jar ./VirtualModem.jar -v -l Exxxx-$(date +%F-%T).log -e Exxxx 600
- * java -jar ./VirtualModem.jar -v -l Qxxx-Rxxxx-$(date +%F-%T).log -a Qxxxx Rxxxx 600
- * java -jar ./VirtualModem.jar -v -l Pxxxx_600_80_8p-$(date +%F-%T).log -p Pxxxx 600 80 8 P1124-$(date +%F-%T)
- * java -jar ./VirtualModem.jar -v -l Mxxxx-$(date +%F-%T).log -g Mxxxx Mxxxx-$(date +%F-%T) 2
- * java -jar ./VirtualModem.jar -v -l Gxxxx-$(date +%F-%T).log -g Gxxxx Gxxxx-$(date +%F-%T) 2
- *
- * @author Christos Choutouridis AEM:8997
- * @email cchoutou@ece.auth.gr
- */
- package net.hoo2.auth.vmodem;
-
- /** @name imports */
- /** @{ */
- import org.apache.commons.cli.*; /** command line utility */
- /** @} */
-
-
- /**
- * @class VirtualModem
- *
- * @brief This is the main control class of the program.
- *
- * This class includes the main function which read the user input
- * and create the appropriate object for the requested sequence to
- * retrieve data.
- */
- public class VirtualModem {
-
- /** @name Data */
- /** @{ */
- 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 basic logging module */
- /** @} */
-
- /**
- * @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();
-
- // 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")
- .hasArg()
- .valueSeparator('=')
- .desc("Select timeout in [sec]")
- .build();
- Option speed = Option.builder("s")
- .longOpt("speed")
- .hasArg()
- .valueSeparator('=')
- .desc("Select speed in [bps]")
- .build();
- Option log = Option.builder("l")
- .longOpt("log")
- .hasArg()
- .desc("Log file name to use")
- .build();
- Option echo = Option.builder("e")
- .longOpt("echo")
- .numberOfArgs(2)
- .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 arq = Option.builder("a")
- .longOpt("arq")
- .numberOfArgs(3)
- .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]")
- .build();
- Option img = Option.builder("g")
- .longOpt("img")
- .numberOfArgs(3)
- .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) // 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);
- options.addOption(timeout);
- options.addOption(speed);
- options.addOption(log);
- options.addOption(echo);
- options.addOption(arq);
- 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
- line = parser.parse (options, args);
- }
- catch( ParseException exp ) {
- // oops, something went wrong
- System.err.println( "Parsing command line failed: " + exp.getMessage() );
- return false;
- }
- 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;
- if (line.hasOption("log"))
- log = new Log (line.getOptionValue("log"), verbose);
- else
- log = new Log (null, verbose);
- if (log.open() != true)
- return false;
-
- // get other options
- if (line.hasOption("timeout")) {
- com.timeout(Integer.parseInt(line.getOptionValue("timeout")));
- }
- if (line.hasOption("speed")) {
- com.speed(Integer.parseInt(line.getOptionValue("speed")));
- }
-
- // Execution dispatcher
- 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("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();
- 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();
- }
- }
-
- log.close();
- return true;
- }
- /**@}*/
-
-
- /**
- * @brief Main function
- */
- public static void main(String[] args) {
- // allocate the main object
- VirtualModem vmodem = new VirtualModem();
-
- // prepare command line input
- if (vmodem.getCmdOptions (args) != true)
- return;
- // Call the requested functionality
- if (vmodem.commandDispatcher() != true)
- return;
- }
- }
- \end{verbatim}
-
- \section{Com.java}
- \begin{verbatim}
- /**
- * @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; /** 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_; /** Ref to Modem */
- private int speed_; /** Communication speed [bps] */
- private int timeout_; /** communication timeout [sec] */
-
- /**
- * Basic constructor
- */
- Com () {
- modem_ = new Modem();
- speed_ = SPEED_DEFAULT;
- timeout_ = TIMEOUT_DEFAULT;
- 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;
- timeout_ = timeout;
- modem_.setSpeed(speed_);
- modem_.setTimeout(timeout_);
- }
-
- /** @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) {
- // 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; // 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;
- }
- } while (
- ch != -1 && (
- !have_begin || (
- (bin || (detect (data.response, "\r\n\n\n".getBytes(), data.size) == -1))
- && (bin || (detect (data.response, "NO CARRIER".getBytes(), data.size) == -1))
- && (detect (data.response, end, data.size) == -1)
- )
- )
- );
- /*^
- * 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) {
- boolean detected = true;
- for (int j=0 ; j<pattern.length ; ++j) {
- if (data[i+j] != pattern[j]) {
- detected = false;
- break;
- }
- }
- if (detected)
- return i;
- }
- }
- 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)
- dest[i] = src[i];
- return src.length;
- }
- return 0;
- }
- /**@}*/
- }
-
- /**
- * @class
- * Class to represent client-server transaction data
- */
- class Transaction {
- 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);
- }
- }
- \end{verbatim}
-
- \section{Log.java}
- \begin{verbatim}
- /**
- * @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_; /** 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 {
- writer_ = new PrintWriter(logfile_);
- }
- catch (IOException exp) {
- System.err.println( "Open log file failed: " + exp.getMessage() );
- return false;
- }
- }
- 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)
- writer_.close();
- } catch (Exception ex) {
- return false;
- }
- 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);
- }
- }
- \end{verbatim}
-
- \section{ARQ.java}
- \begin{verbatim}
- /**
- * @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;
- }
- /**@} */
- }
- \end{verbatim}
-
-
- \section{Echo.java}
- \begin{verbatim}
- /**
- * @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; /** 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;
-
- line = "Running ECHO with: " + new String(code);
- 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;
- String line;
-
- start = System.currentTimeMillis();
- do {
- transaction_ = com_.request(transaction_, code_, ECHO_BEGIN.getBytes(), ECHO_END.getBytes(), false);
- line = new String(transaction_.code) + ": "
- + new String(transaction_.getResponse())
- + " Tr= " + (transaction_.arrival - transaction_.departure) + " [msec]";
- log_.write(line);
- now = System.currentTimeMillis();
- } while (now - start < duration_*1000);
- }
-
- }
- \end{verbatim}
-
- \section{GPS.java}
- \begin{verbatim}
- /**
- * @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; /** 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; /** 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_; /** 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;
- transaction_= new Transaction(null, new byte[GPS_BUFFER_SIZE]);
- code_ = code;
- start_ = start;
- duration_ = duration;
- points_ = (points <= GPS_MAX_POINTS) ? points : GPS_MAX_POINTS;
- coordinates_= new byte[GPS_COORDINATES_SIZE];
- }
-
- /**
- * Functionality to drain the response buffer for the welcome message
- * from the server
- */
- void caption () {
- String line;
-
- line = "Running GPS with: " + new String(code_)
- + " time [" + start_ + " - " +(start_+duration_) + ") sec" + " [" + points_ + " points]";
- 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.
- * @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_) {
- code = new String(code_) + GPS_TRACK_PREFIX + GPS_USE_TRACK + String.format("%04d", trace) + "01";
- transaction_ = com_.request(transaction_, code.getBytes(), GPS_BEGIN.getBytes(), GPS_END.getBytes(), false);
- line = new String(transaction_.code) + ": "
- + new String(transaction_.getResponse())
- + " Tr= " + (transaction_.arrival - transaction_.departure) + " [msec]";
- log_.write(line);
-
- _get_coordinates(transaction_.getResponse());
- image_code += GPS_IMAGE_PREFIX +
- String.format("%02d%02d%02d%02d%02d%02d", coordinates_[0], coordinates_[1],
- coordinates_[2], coordinates_[3],
- coordinates_[4], coordinates_[5]);
-
- }
- 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(
- new String (Arrays.copyOfRange(stream,
- start+GPS_LATITUDE_BEGIN,
- start+GPS_LATITUDE_END-2))));
- double longitude = _nmea2dec (Double.valueOf(
- new String(Arrays.copyOfRange(stream,
- start+GPS_LONGITUDE_BEGIN,
- start+GPS_LONGITUDE_END-2))));
-
- coordinates_[0] = (byte)(longitude); // longitude deg
- coordinates_[1] = (byte)((longitude - coordinates_[0]) * 60.0); // longitude '
- coordinates_[2] = (byte)((longitude - coordinates_[0]
- - coordinates_[1]/60.0)*3600); // longitude "
-
- coordinates_[3] = (byte)(latitude); // latitude deg
- coordinates_[4] = (byte)((latitude - coordinates_[3]) * 60.0); // latitude '
- coordinates_[5] = (byte)((latitude - coordinates_[3]
- - 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);
- }
- /** @} */
- }
- \end{verbatim}
-
- \section{Image.java}
- \begin{verbatim}
- /**
- * @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; /** 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_; /** 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;
-
- line = "Running video decoder with: " + new String(code);
- 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 () {
- String file, line;
- BufferedOutputStream ostream;
-
- for (int i =1 ; i<= items_ ; ++i) {
- // Make the filename string
- if (items_>1)
- file = filename_ + "_" + i + ".jpg";
- else
- file = filename_ + ".jpg";
- line = new String(code_) + ": ";
- log_.write(line);
- transaction_ = com_.request(transaction_, code_, IMAGE_BEGIN, IMAGE_END, true);
- line = "File= " + file
- + " Tr= " + (transaction_.arrival - transaction_.departure) + " [msec]"
- + " Tt= " + (System.currentTimeMillis() - transaction_.departure) + " [msec]";
- log_.write(line);
- try {
- ostream = new BufferedOutputStream(new FileOutputStream(file));
- ostream.write(transaction_.response);
- ostream.flush();
- ostream.close();
- }
- catch (Exception exp) {
- System.err.println ("Error creating " + file + exp.getMessage());
- return;
- }
- }
- }
- }
- \end{verbatim}
-
- \end{document}
|