Network programming assignment for University
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1160 lines
42 KiB

  1. %
  2. % Network programming Lab report source code
  3. %
  4. % authors:
  5. % Χρήστος Χουτουρίδης ΑΕΜ 8997
  6. % cchoutou@ece.auth.gr
  7. % Document configuration
  8. \newcommand{\ClassName}{Δίκτυα Υπολογιστών Ι}
  9. \newcommand{\DocTitle}{Κώδικας εφαρμογής}
  10. \newcommand{\InstructorName}{Δημήτριος Μητράκος}
  11. \newcommand{\InstructorMail}{mitrakos@eng.auth.gr}
  12. \newcommand{\CurrentDate}{\today}
  13. \input{AuthReport.tex}
  14. %\renewcommand{\AuthorName}{Χρήστος Χουτουρίδης}
  15. %\renewcommand{\AuthorMail}{cchoutou@ece.auth.gr}
  16. %\renewcommand{\AuthorAEM}{8997}
  17. \fancyhead[L]{\ClassName}
  18. \fancyhead[R]{Χρήστος Χουτουρίδης 8997}
  19. % Document
  20. % =================
  21. \begin{document}
  22. \FirstPage
  23. \tableofcontents
  24. \section{Περιγραφή}
  25. Για την ανάπτυξη του κώδικα χρησιμοποιήσαμε το περιβάλλον \eng{eclipse} και το \eng{openjdk} στην έκδοση 11.
  26. Επειδή η εφαρμογή λειτουργεί ως \eng{command line tool,} χρησιμοποιήσαμε ακόμα το \eng{commons-cli} από \href{http://commons.apache.org/proper/commons-cli/}{\eng{apache commons}} ώς εργαλείο ανάγνωσης των ορισμάτων του χρήστη.
  27. Η υλοποίηση της εφαρμογής είναι πολύ απλή.
  28. Δεν χρησιμοποιούμε \eng{interfaces} ή κληρονομικότητα.
  29. Αντίθετα έχουμε χωρίσει την εφαρμογή σε αυτόνομα αντικείμενα.
  30. Τα αντικείμενα \eng{Com} και \eng{Log} παρέχουν τις βασικές λειτουργίες για την επικοινωνία με τον \eng{server} και την έξοδο του προγράμματος αντίστοιχα.
  31. Τα αντικείμενα αυτά χρησιμοποιούνται απλώς μέσα υπόλοιπα.
  32. Χρησιμοποιούμε δηλαδή την απλούστερη δυνατή τεχνική (\eng{build by composition}).
  33. \par Τον κώδικα καθώς και την παραγόμενη τεκμηρίωσή του μέσω \eng{JavaDoc} μπορείτε να την βρείτε στο παραδοτέο αρχείο στους καταλόγους \eng{src} και \eng{doc.}
  34. Τέλος στο \href{https://git.hoo2.net/hoo2/virtualModem}{προσωπικό αποθετήριο} του συντάκτη υπάρχει όλος ο κώδικας της εφαρμογής, της εργασίας και της επεξεργασίας των αποτελεσμάτων.
  35. Παραθέτουμε παρακάτω τον κώδικα της εφαρμογής σε μορφή !!κειμένου!!, όπως αυτό ζητήθηκε από την εκφώνηση της εργασίας.
  36. Το κάθε κεφάλαιο αντιστοιχεί σε ξεχωριστό αρχείο του κώδικα.
  37. \selectlanguage{english}
  38. \titleformat{\section}[block]{\large\textbf}{\thesection.}{1em}{}
  39. \small
  40. \section{virtualModem.java}
  41. \begin{verbatim}
  42. /**
  43. * @file VirtualModem.java
  44. * @brief
  45. * Contain the Main class for the project VirtualModem
  46. *
  47. * Usage examples:
  48. * ==========================
  49. * java -jar ./VirtualModem.jar -v -l Exxxx-$(date +%F-%T).log -e Exxxx 600
  50. * java -jar ./VirtualModem.jar -v -l Qxxx-Rxxxx-$(date +%F-%T).log -a Qxxxx Rxxxx 600
  51. * java -jar ./VirtualModem.jar -v -l Pxxxx_600_80_8p-$(date +%F-%T).log -p Pxxxx 600 80 8 P1124-$(date +%F-%T)
  52. * java -jar ./VirtualModem.jar -v -l Mxxxx-$(date +%F-%T).log -g Mxxxx Mxxxx-$(date +%F-%T) 2
  53. * java -jar ./VirtualModem.jar -v -l Gxxxx-$(date +%F-%T).log -g Gxxxx Gxxxx-$(date +%F-%T) 2
  54. *
  55. * @author Christos Choutouridis AEM:8997
  56. * @email cchoutou@ece.auth.gr
  57. */
  58. package net.hoo2.auth.vmodem;
  59. /** @name imports */
  60. /** @{ */
  61. import org.apache.commons.cli.*; /** command line utility */
  62. /** @} */
  63. /**
  64. * @class VirtualModem
  65. *
  66. * @brief This is the main control class of the program.
  67. *
  68. * This class includes the main function which read the user input
  69. * and create the appropriate object for the requested sequence to
  70. * retrieve data.
  71. */
  72. public class VirtualModem {
  73. /** @name Data */
  74. /** @{ */
  75. CommandLine line; /** Command line for the argument list */
  76. CommandLineParser parser; /** Parser for the argument list */
  77. Options options; /** Option configuration container */
  78. HelpFormatter formatter; /** An extra helper for -h */
  79. Com com; /** Reference to basic configuration module */
  80. Log log; /** Reference to basic logging module */
  81. /** @} */
  82. /**
  83. * @brief The main constructor of the class
  84. * We allocate memory for the data needed for the command line
  85. */
  86. public VirtualModem () {
  87. parser = new DefaultParser();
  88. options = new Options();
  89. formatter = new HelpFormatter();
  90. com = new Com();
  91. // Create argument options and a basic help file
  92. // for future use.
  93. Option verb = new Option ("v", "verbose", false, "Be more verbose to the console");
  94. Option help = new Option ("h", "help", false, "Print this message");
  95. Option timeout = Option.builder("t")
  96. .longOpt("timeout")
  97. .hasArg()
  98. .valueSeparator('=')
  99. .desc("Select timeout in [sec]")
  100. .build();
  101. Option speed = Option.builder("s")
  102. .longOpt("speed")
  103. .hasArg()
  104. .valueSeparator('=')
  105. .desc("Select speed in [bps]")
  106. .build();
  107. Option log = Option.builder("l")
  108. .longOpt("log")
  109. .hasArg()
  110. .desc("Log file name to use")
  111. .build();
  112. Option echo = Option.builder("e")
  113. .longOpt("echo")
  114. .numberOfArgs(2)
  115. .desc ("Request echo sequence where <arg> = <1> <2>\n"
  116. + " <1>: The echo requested code from virtual lab\n"
  117. + " <2>: The time duration of the session [sec]")
  118. .build();
  119. Option arq = Option.builder("a")
  120. .longOpt("arq")
  121. .numberOfArgs(3)
  122. .desc ("Request arq sequence where <arg> = <1> <2> <3>\n"
  123. + " <1>: The ACK requested code for virtual lab\n"
  124. + " <2>: The NACK requested code from virtual lab\n"
  125. + " <2>: The time duration for the session [sec]")
  126. .build();
  127. Option img = Option.builder("g")
  128. .longOpt("img")
  129. .numberOfArgs(3)
  130. .desc("Request an image sequence where <arg> = <1> <2> <3>\n"
  131. + " <1>: The image requested code from virtual lab\n"
  132. + " <2>: The filename to use for storing the image (without .jpg)\n"
  133. + " <3>: The requested images to fetch.")
  134. .build();
  135. Option gps = Option.builder("p")
  136. .longOpt("gps")
  137. .numberOfArgs(5) // G8164 10 800 8 gps_10_800
  138. .desc("Request a GPS sequence where <arg> = <1> <2> <3> <4>\n"
  139. + " <1>: The gps requested code from virtual lab\n"
  140. + " <2>: The time from trace to use as starting point [sec]\n"
  141. + " <3>: The time duration for the trace to fetch [sec]\n"
  142. + " <4>: The number of points to fetch from the above trace\n"
  143. + " <5>: The filename to use for storing the image (without .jpg)")
  144. .build();
  145. options.addOption(verb);
  146. options.addOption(help);
  147. options.addOption(timeout);
  148. options.addOption(speed);
  149. options.addOption(log);
  150. options.addOption(echo);
  151. options.addOption(arq);
  152. options.addOption(img);
  153. options.addOption(gps);
  154. }
  155. /** @name private api */
  156. /**@{*/
  157. /**
  158. * parse the command line arguments
  159. * @param args the arguments to parse
  160. * @return the status of the operation
  161. */
  162. private boolean getCmdOptions (String[] args) {
  163. try {
  164. // parse the command line arguments
  165. line = parser.parse (options, args);
  166. }
  167. catch( ParseException exp ) {
  168. // oops, something went wrong
  169. System.err.println( "Parsing command line failed: " + exp.getMessage() );
  170. return false;
  171. }
  172. return true;
  173. }
  174. /**
  175. * Dispatch the correct functionality based on arguments
  176. * @return the status of the operation (currently true)
  177. */
  178. private boolean commandDispatcher () {
  179. boolean verbose = false;
  180. if (line.hasOption("help")) {
  181. formatter.printHelp( "virtualModem", options );
  182. return true;
  183. }
  184. // Get log and verbose options first
  185. if (line.hasOption("verbose"))
  186. verbose = true;
  187. if (line.hasOption("log"))
  188. log = new Log (line.getOptionValue("log"), verbose);
  189. else
  190. log = new Log (null, verbose);
  191. if (log.open() != true)
  192. return false;
  193. // get other options
  194. if (line.hasOption("timeout")) {
  195. com.timeout(Integer.parseInt(line.getOptionValue("timeout")));
  196. }
  197. if (line.hasOption("speed")) {
  198. com.speed(Integer.parseInt(line.getOptionValue("speed")));
  199. }
  200. // Execution dispatcher
  201. if (line.hasOption("echo")) {
  202. byte[] code = line.getOptionValues("echo")[0].getBytes();
  203. Echo e = new Echo(com, log, code,
  204. Integer.valueOf(line.getOptionValues("echo")[1]));
  205. if (com.open()) {
  206. e.caption(code);
  207. e.run();
  208. com.close();
  209. }
  210. }
  211. else if (line.hasOption("arq")) {
  212. byte[] ack = line.getOptionValues("arq")[0].getBytes();
  213. byte[] nack = line.getOptionValues("arq")[1].getBytes();
  214. ARQ a = new ARQ(com, log, ack, nack,
  215. Integer.valueOf(line.getOptionValues("arq")[2]));
  216. if (com.open()) {
  217. a.caption(ack, nack);
  218. a.run();
  219. com.close();
  220. }
  221. }
  222. else if (line.hasOption("img")) {
  223. byte[] code = line.getOptionValues("img")[0].getBytes();
  224. Image im = new Image (com, log, code,
  225. line.getOptionValues("img")[1],
  226. Integer.valueOf(line.getOptionValues("img")[2]));
  227. if (com.open()) {
  228. im.caption(code);
  229. im.run();
  230. com.close();
  231. }
  232. }
  233. else if (line.hasOption("gps")) {
  234. byte[] code = line.getOptionValues("gps")[0].getBytes();
  235. GPS g = new GPS (
  236. com, log, code,
  237. Integer.valueOf(line.getOptionValues("gps")[1]),
  238. Integer.valueOf(line.getOptionValues("gps")[2]),
  239. Integer.valueOf(line.getOptionValues("gps")[3])
  240. );
  241. Image im = new Image (
  242. com, log, null,
  243. line.getOptionValues("gps")[4], 1
  244. );
  245. if (com.open()) {
  246. g.caption();
  247. im.code(g.run().getBytes());
  248. im.run();
  249. com.close();
  250. }
  251. }
  252. log.close();
  253. return true;
  254. }
  255. /**@}*/
  256. /**
  257. * @brief Main function
  258. */
  259. public static void main(String[] args) {
  260. // allocate the main object
  261. VirtualModem vmodem = new VirtualModem();
  262. // prepare command line input
  263. if (vmodem.getCmdOptions (args) != true)
  264. return;
  265. // Call the requested functionality
  266. if (vmodem.commandDispatcher() != true)
  267. return;
  268. }
  269. }
  270. \end{verbatim}
  271. \section{Com.java}
  272. \begin{verbatim}
  273. /**
  274. * @file Com.java
  275. *
  276. * @author Christos Choutouridis AEM:8997
  277. * @email cchoutou@ece.auth.gr
  278. */
  279. package net.hoo2.auth.vmodem;
  280. /** @name imports */
  281. /** @{ */
  282. import java.util.Arrays;
  283. import ithakimodem.*;
  284. /** @} */
  285. /**
  286. * @class Com
  287. *
  288. * Wrapper object of the provided Modem class to provide
  289. * a convenient and common API for all the session functionalities
  290. */
  291. class Com {
  292. static final int SPEED_DEFAULT = 48000; /** default communication speed [bps] */
  293. static final int TIMEOUT_DEFAULT = 2000; /** default timeout values [sec] */
  294. static final String URL_DEFAULT = "ithaki"; /** Default destination. Ithaki of-course */
  295. private Modem modem_; /** Ref to Modem */
  296. private int speed_; /** Communication speed [bps] */
  297. private int timeout_; /** communication timeout [sec] */
  298. /**
  299. * Basic constructor
  300. */
  301. Com () {
  302. modem_ = new Modem();
  303. speed_ = SPEED_DEFAULT;
  304. timeout_ = TIMEOUT_DEFAULT;
  305. modem_.setSpeed(speed_);
  306. modem_.setTimeout(timeout_);
  307. }
  308. /** A more fancy constructor
  309. *
  310. * @param log Reference to Log to use
  311. * @param speed The desired speed [bps]
  312. * @param timeout The desired timeout [sec]
  313. * @note
  314. * Currently not used
  315. */
  316. Com (Log log, int speed, int timeout) {
  317. modem_ = new Modem();
  318. speed_ = speed;
  319. timeout_ = timeout;
  320. modem_.setSpeed(speed_);
  321. modem_.setTimeout(timeout_);
  322. }
  323. /** @name Mutator interface */
  324. /**@{ */
  325. /** Get the current timeout value [sec] */
  326. int timeout () { return timeout_; }
  327. /** Set the timeout value [sec] */
  328. void timeout (int timeout) {
  329. if (timeout_ != timeout) {
  330. timeout_ = timeout;
  331. modem_.setTimeout(timeout_);
  332. }
  333. }
  334. /** Get the current speed [bps] */
  335. int speed () { return speed_; }
  336. /** Set the speed [bps] */
  337. void speed (int speed) {
  338. if (speed_ != speed) {
  339. speed_ = speed;
  340. modem_.setSpeed(speed_);
  341. }
  342. }
  343. /**@} */
  344. /** @name Public API of the class */
  345. /**@{ */
  346. /** Open a communication channel with a URL */
  347. boolean open (String url) { return modem_.open(url); }
  348. /** Open a communication channel with Ithaki */
  349. boolean open () { return modem_.open(URL_DEFAULT); }
  350. /** Close the connection */
  351. boolean close() { return modem_.close(); }
  352. /**
  353. * @grief The basic communication functionality
  354. *
  355. * This function sends a request to server and return the response. In order to
  356. * do that, the main reading loop seeks for the starting pattern and use the data
  357. * from that point up to the ending pattern. This is very helpful for binary incoming
  358. * data.
  359. * @note
  360. * Blocking mode
  361. * @param data Reference to Transaction data to use @see Transaction
  362. * @param code The request code to send
  363. * @param begin The starting pattern of the response data
  364. * @param end The ending pattern of the response data
  365. * @param bin A flag to indicate that the data are in binary form
  366. * @return Reference to Transaction object with the response data. @see Transaction
  367. */
  368. Transaction request (Transaction data, byte[] code, byte[] begin, byte[] end, boolean bin) {
  369. int ch =0;
  370. boolean have_begin = (begin != null) ? false : true;
  371. boolean incoming = false;
  372. // Clear the receive buffer first
  373. _clear (data.response, 0, data.response.length);
  374. if (code != null) {
  375. // if we have a request
  376. data.code = code; // store the request code for the transaction
  377. modem_.write(data.code); // send the code and mark the time
  378. modem_.write((int)'\r');
  379. data.departure = System.currentTimeMillis();// - (long)((8*(data.code.length+1))*(1000.0/speed_));
  380. }
  381. // main receive loop
  382. data.size =0;
  383. do {
  384. // escape guard for memory protection
  385. if (data.size >= data.response.length) {
  386. data.size =0;
  387. return data;
  388. }
  389. // read the data byte from server
  390. try {
  391. ch = modem_.read();
  392. }
  393. catch (Exception e) {
  394. // Oops!!!! something went wrong. Break and return :(
  395. System.err.println (e.getMessage());
  396. data.size =0;
  397. return data;
  398. }
  399. if (!incoming) {
  400. // first byte triggered. mark the time
  401. incoming = true;
  402. data.arrival = System.currentTimeMillis();// - (long)(8*(1000.0/speed_));
  403. }
  404. data.response [data.size++] = (byte)ch; // store the byte
  405. if (!have_begin && (detect(data.response, begin, data.size) != -1)) {
  406. // If begin pattern detected, start over.
  407. _clear(data.response, 0, data.size);
  408. data.size = _copy (data.response, begin);
  409. have_begin = true;
  410. }
  411. } while (
  412. ch != -1 && (
  413. !have_begin || (
  414. (bin || (detect (data.response, "\r\n\n\n".getBytes(), data.size) == -1))
  415. && (bin || (detect (data.response, "NO CARRIER".getBytes(), data.size) == -1))
  416. && (detect (data.response, end, data.size) == -1)
  417. )
  418. )
  419. );
  420. /*^
  421. * We loop until:
  422. * 1) server returns -1
  423. * 2) A end pattern arrives
  424. * 3) A "\r\n\n\n" sequence arrives (in character mode, not for binary files)
  425. * 4) A "NO CARRIER" sequence arrives (in character mode, not for binary files)
  426. */
  427. return data;
  428. }
  429. /**
  430. * @brief
  431. * A pattern detect functionality.
  432. *
  433. * Search in data input for the pattern and return its position if found.
  434. * @note
  435. * O(n^2) in time.
  436. * @param data The data buffer to search into
  437. * @param pattern The pattern to search for
  438. * @param max The maximum length to search
  439. * @return The position of pattern in data, or -1 if not found
  440. */
  441. static int detect (byte[] data, byte[] pattern, int max) {
  442. if (pattern != null) {
  443. for (int i =0 ; i<max && i<data.length - pattern.length; ++i) {
  444. boolean detected = true;
  445. for (int j=0 ; j<pattern.length ; ++j) {
  446. if (data[i+j] != pattern[j]) {
  447. detected = false;
  448. break;
  449. }
  450. }
  451. if (detected)
  452. return i;
  453. }
  454. }
  455. return -1;
  456. }
  457. /**@} */
  458. /** @name Private helper api */
  459. /**@{*/
  460. /**
  461. * Clear a buffer segment
  462. * @param buffer Buffer to clear
  463. * @param begin The starting point
  464. * @param end The ending point
  465. */
  466. private void _clear (byte[] buffer, int begin, int end) {
  467. for (int i=begin ; i<end && i<buffer.length ; ++i)
  468. buffer[i] = 0;
  469. }
  470. /**
  471. * Copy a buffer to another
  472. * @param dest The destination buffer
  473. * @param src The source buffer
  474. * @return The number of bytes copied
  475. */
  476. private int _copy (byte[] dest, byte[] src) {
  477. if (dest.length >= src.length) {
  478. for (int i=0 ; i<src.length ; ++i)
  479. dest[i] = src[i];
  480. return src.length;
  481. }
  482. return 0;
  483. }
  484. /**@}*/
  485. }
  486. /**
  487. * @class
  488. * Class to represent client-server transaction data
  489. */
  490. class Transaction {
  491. byte[] code; /** request code from client */
  492. byte[] response; /** response data from server */
  493. long departure; /** request time */
  494. long arrival; /** response time */
  495. int size; /** size of response data in bytes */
  496. /**
  497. * Basic constructor
  498. * @param code Code to use
  499. * @param response Response buffer to use
  500. */
  501. Transaction (byte[] code, byte[] response) {
  502. this.code = code;
  503. this.response = response;
  504. departure = arrival = 0;
  505. size = 0;
  506. }
  507. /**
  508. * Get a copy of the response
  509. */
  510. byte[] getResponse() {
  511. return Arrays.copyOf(response, size);
  512. }
  513. }
  514. \end{verbatim}
  515. \section{Log.java}
  516. \begin{verbatim}
  517. /**
  518. * @file Log.java
  519. *
  520. * @author Christos Choutouridis AEM:8997
  521. * @email cchoutou@ece.auth.gr
  522. */
  523. package net.hoo2.auth.vmodem;
  524. /** @name imports */
  525. /** @{ */
  526. import java.io.IOException;
  527. import java.io.PrintWriter;
  528. /** @} */
  529. /**
  530. * @class Log
  531. *
  532. * A common log functionality class for all sessions
  533. */
  534. class Log {
  535. private String logfile_; /** The log file name */
  536. private boolean verbose_; /** The desired verbosity (for the console)*/
  537. private PrintWriter writer_; /** A buffered writer to use for streaming */
  538. /**
  539. * Basic constructor
  540. * @param logfile The log filename
  541. * @param verbose The desired verbosity (for the console)
  542. */
  543. Log (String logfile, boolean verbose) {
  544. logfile_ = logfile;
  545. verbose_ = verbose;
  546. }
  547. /**
  548. * Try to open the log file
  549. * @return The status of the operation
  550. */
  551. boolean open () {
  552. if (logfile_ != null) {
  553. try {
  554. writer_ = new PrintWriter(logfile_);
  555. }
  556. catch (IOException exp) {
  557. System.err.println( "Open log file failed: " + exp.getMessage() );
  558. return false;
  559. }
  560. }
  561. return true;
  562. }
  563. /**
  564. * Try to open a log file
  565. * @param logfile The log file to open
  566. * @return The status of the operation
  567. */
  568. boolean open (String logfile) {
  569. logfile_ = logfile;
  570. return open();
  571. }
  572. /**
  573. * Close the opened file
  574. * @return The status of the operation
  575. */
  576. boolean close () {
  577. try {
  578. if (writer_ != null)
  579. writer_.close();
  580. } catch (Exception ex) {
  581. return false;
  582. }
  583. return true;
  584. }
  585. /**
  586. * Log to file and print to console
  587. * @param line The line to log
  588. * @param out Console output request flag. If true, echo the line to console
  589. */
  590. void write (String line, boolean out) {
  591. if (logfile_ != null) writer_.println(line);
  592. if (verbose_ || out) System.out.println(line);
  593. }
  594. /**
  595. * Log to file and print to console
  596. * @param line The line to log
  597. */
  598. void write (String line) {
  599. if (logfile_ != null) writer_.println(line);
  600. if (verbose_) System.out.println(line);
  601. }
  602. /**
  603. * Echo the line to console
  604. * @param line The line to print
  605. */
  606. void out (String line) {
  607. if (verbose_) System.out.println(line);
  608. }
  609. }
  610. \end{verbatim}
  611. \section{ARQ.java}
  612. \begin{verbatim}
  613. /**
  614. * @file ARQ.java
  615. *
  616. * @author Christos Choutouridis AEM:8997
  617. * @email cchoutou@ece.auth.gr
  618. */
  619. package net.hoo2.auth.vmodem;
  620. /** @name imports */
  621. /** @{ */
  622. import java.util.*;
  623. /** @} */
  624. /**
  625. * @class ARQ
  626. *
  627. * Class to used for the ACK-NACK sequence
  628. */
  629. class ARQ {
  630. static final int ARQ_DURATION_DEFAULT = 240; /** Default duration for the sequence */
  631. static final int ARQ_BUFFER_SIZE = 256; /** ARQ buffer size */
  632. static final String ARQ_BEGIN = "PSTART"; /** Begin pattern of the response */
  633. static final String ARQ_END = "PSTOP"; /** End pattern of the response */
  634. static final int ARQ_SEQUENCE_BEGIN = 31; /** The response sequence string position */
  635. static final int ARQ_SEQUENCE_END = 47; /** The end of response sequence string position */
  636. static final int ARQ_CRC_BEGIN = 49; /** The response crc string position */
  637. static final int ARQ_CRC_END = 52; /** The end of response crc string position */
  638. private Com com_; /** Reference to communication module */
  639. private Log log_; /** Reference to logging module */
  640. private Transaction transaction_; /** A transaction object to used as a buffer for all requests */
  641. private int duration_; /** The desired duration for the session */
  642. private byte[] ack_; /** The desired ACK code for the session */
  643. private byte[] nack_; /** The desired NACK code for the session */
  644. /**
  645. * Basic constructor
  646. * @param com The Com module to use
  647. * @param log The Log module to use
  648. * @param ack The desired ACK code
  649. * @param nack The desired NACK code
  650. * @param duration The desired duration for the session
  651. */
  652. ARQ (Com com, Log log, byte[] ack, byte[] nack, int duration) {
  653. com_ = com;
  654. log_ = log;
  655. duration_ = duration;
  656. transaction_= new Transaction(null, new byte[ARQ_BUFFER_SIZE]);
  657. ack_ = ack;
  658. nack_ = nack;
  659. }
  660. /**
  661. * Functionality to drain the response buffer for the welcome message
  662. * from the server
  663. * @param ack The ack code that we will use (for printing, not sending)
  664. * @param nack The nack code that we will use (for printing, not sending)
  665. */
  666. void caption (byte[] ack, byte[] nack) {
  667. String line;
  668. line = "Running ARQ with: " + new String(ack) + "/" + new String(nack);
  669. log_.write(line, true);
  670. transaction_ = com_.request (transaction_, null, null, null, false);
  671. line = new String(transaction_.getResponse());
  672. log_.out(line);
  673. }
  674. /**
  675. * Main transaction loop. It send requests to server, get the response
  676. * and log the procedure while doing it.
  677. */
  678. void run () {
  679. long start;
  680. long now;
  681. long mark =0, tr =0, ts =0, tt =0;
  682. String line;
  683. int errors = 0;
  684. boolean good = true;
  685. start = System.currentTimeMillis();
  686. do {
  687. // Check if the previous transaction was error-free
  688. if (good)
  689. transaction_ = com_.request(transaction_, ack_, ARQ_BEGIN.getBytes(), ARQ_END.getBytes(), false);
  690. else
  691. transaction_ = com_.request(transaction_, nack_, ARQ_BEGIN.getBytes(), ARQ_END.getBytes(), false);
  692. good = (_crc_check(transaction_.response)) ? true : false; // crc check the response
  693. // time calculations
  694. tr = transaction_.arrival - transaction_.departure;
  695. tt = 0;
  696. if ((errors == 0) && good) {
  697. tt = ts = tr;
  698. }
  699. if ((errors == 0) && !good) {
  700. mark = transaction_.departure;
  701. ts = tr;
  702. }
  703. if ((errors != 0) && good) {
  704. tt = transaction_.arrival - mark;
  705. ts += tr;
  706. }
  707. if ((errors !=0) && !good) {
  708. ts += tr;
  709. }
  710. errors = (good) ? 0 : errors+1; // update the error strike
  711. line = new String(transaction_.code) + ": "
  712. + new String(transaction_.getResponse())
  713. + " Er: " + errors
  714. + " Tr= " + tr + " [msec]";
  715. if (errors !=0)
  716. line += " Ts= 0 [msec] Tt= 0 [msec]";
  717. else
  718. line += " Ts= " + ts + " [msec]" + " Tt= " + tt + " [msec]";
  719. log_.write(line);
  720. now = System.currentTimeMillis();
  721. } while (now - start < duration_*1000);
  722. }
  723. /** @name private helper API */
  724. /**@{ */
  725. /**
  726. * A CRC check functionality
  727. * @param data The data to check for validity
  728. * @return The check result
  729. */
  730. private boolean _crc_check (byte[] data) {
  731. byte[] seq = Arrays.copyOfRange(data, ARQ_SEQUENCE_BEGIN, ARQ_SEQUENCE_END);
  732. int crc = Integer.valueOf(
  733. new String(Arrays.copyOfRange(data, ARQ_CRC_BEGIN, ARQ_CRC_END))
  734. );
  735. return (crc == _crc(seq)) ? true : false;
  736. }
  737. /**
  738. * A CRC calculation function. This primitive CRC calculator
  739. * does not use any known CRC polynomial. It just uses XOR
  740. * @param data Reference to buffer
  741. * @return The CRC result
  742. */
  743. private int _crc (byte[] data) {
  744. int calc =0;
  745. for (int i=0 ; i<data.length ; ++i)
  746. calc ^= data[i];
  747. return calc;
  748. }
  749. /**@} */
  750. }
  751. \end{verbatim}
  752. \section{Echo.java}
  753. \begin{verbatim}
  754. /**
  755. * @file Echo.java
  756. *
  757. * @author Christos Choutouridis AEM:8997
  758. * @email cchoutou@ece.auth.gr
  759. */
  760. package net.hoo2.auth.vmodem;
  761. /**
  762. * @class Echo
  763. *
  764. * Class to used for the echo sequence
  765. */
  766. class Echo {
  767. static final int ECHO_DURATION_DEFAULT = 240; /** Default duration for the sequence */
  768. static final int ECHO_BUFFER_SIZE = 256; /** Echo buffer size */
  769. static final String ECHO_BEGIN = "PSTART"; /** Begin pattern of the response */
  770. static final String ECHO_END = "PSTOP"; /** End pattern of the response */
  771. private Com com_; /** Reference to communication module */
  772. private Log log_; /** Reference to logging module */
  773. private Transaction transaction_; /** A transaction object to used as a buffer for all requests */
  774. private int duration_; /** The desired duration for the session */
  775. private byte[] code_; /** The desired code for the session */
  776. /**
  777. * Basic constructor
  778. * @param com The Communication module to use
  779. * @param log The logging module to use
  780. * @param code The code to use
  781. * @param duration The duration to use
  782. */
  783. Echo (Com com, Log log, byte[] code, int duration) {
  784. com_ = com;
  785. log_ = log;
  786. duration_ = duration;
  787. // Allocate memory for the response
  788. transaction_= new Transaction(null, new byte[ECHO_BUFFER_SIZE]);
  789. code_ = code;
  790. }
  791. /**
  792. * Functionality to drain the response buffer for the welcome message
  793. * from the server
  794. * @param code The code that we will use (for printing, not sending)
  795. */
  796. void caption (byte[] code) {
  797. String line;
  798. line = "Running ECHO with: " + new String(code);
  799. log_.write(line, true);
  800. transaction_ = com_.request (transaction_, null, null, null, false);
  801. line = new String(transaction_.getResponse());
  802. log_.out(line);
  803. }
  804. /**
  805. * Main transaction loop. It send requests to server, get the response
  806. * and log the procedure while doing it.
  807. */
  808. void run () {
  809. long start;
  810. long now;
  811. String line;
  812. start = System.currentTimeMillis();
  813. do {
  814. transaction_ = com_.request(transaction_, code_, ECHO_BEGIN.getBytes(), ECHO_END.getBytes(), false);
  815. line = new String(transaction_.code) + ": "
  816. + new String(transaction_.getResponse())
  817. + " Tr= " + (transaction_.arrival - transaction_.departure) + " [msec]";
  818. log_.write(line);
  819. now = System.currentTimeMillis();
  820. } while (now - start < duration_*1000);
  821. }
  822. }
  823. \end{verbatim}
  824. \section{GPS.java}
  825. \begin{verbatim}
  826. /**
  827. * @file GPS.java
  828. *
  829. * @author Christos Choutouridis AEM:8997
  830. * @email cchoutou@ece.auth.gr
  831. */
  832. package net.hoo2.auth.vmodem;
  833. /** @name imports */
  834. /** @{ */
  835. import java.util.Arrays;
  836. /** @} */
  837. /**
  838. * @class GPS
  839. *
  840. * Class to used for the GPS session
  841. */
  842. class GPS {
  843. static final int GPS_BUFFER_SIZE = 256; /** GPS trace buffer size */
  844. static final String GPS_BEGIN = "START ITHAKI GPS TRACKING"; /** starting pattern */
  845. static final String GPS_END = "STOP ITHAKI GPS TRACKING"; /** ending pattern */
  846. static final int GPS_USE_TRACK = 1; /** Which track to use (given) */
  847. static final String GPS_TRACK_PREFIX = "R="; /** GPS command track request prefix */
  848. static final String GPS_IMAGE_PREFIX = "T="; /** GPS command image request prefix */
  849. static final int GPS_MAX_POINTS = 9; /** Maximum points (given) */
  850. static final int GPS_COORDINATES_SIZE = 6; /** Coordinates size */
  851. static final int GPS_LATITUDE_BEGIN = 17; /** The latitude sequence string position */
  852. static final int GPS_LATITUDE_END = 28; /** The end of latitude sequence string position */
  853. static final int GPS_LONGITUDE_BEGIN= 29; /** The longitude sequence string position */
  854. static final int GPS_LONGITUDE_END = 41; /** The end of longitude sequence string position */
  855. private Com com_; /** Reference to communication module */
  856. private Log log_; /** Reference to logging module */
  857. private Transaction transaction_; /** A transaction object to used as a buffer for all requests */
  858. private byte[] code_; /** The desired code for the session */
  859. private int start_; /** Starting point [sec] */
  860. private int duration_; /** Duration of requested trace */
  861. private int points_; /** Number of points to fetch from the above trace */
  862. private byte[] coordinates_; /** Coordinates buffer */
  863. /**
  864. * Basic constructor
  865. */
  866. GPS (Com com, Log log, byte[] code, int start, int duration, int points) {
  867. com_ = com;
  868. log_ = log;
  869. transaction_= new Transaction(null, new byte[GPS_BUFFER_SIZE]);
  870. code_ = code;
  871. start_ = start;
  872. duration_ = duration;
  873. points_ = (points <= GPS_MAX_POINTS) ? points : GPS_MAX_POINTS;
  874. coordinates_= new byte[GPS_COORDINATES_SIZE];
  875. }
  876. /**
  877. * Functionality to drain the response buffer for the welcome message
  878. * from the server
  879. */
  880. void caption () {
  881. String line;
  882. line = "Running GPS with: " + new String(code_)
  883. + " time [" + start_ + " - " +(start_+duration_) + ") sec" + " [" + points_ + " points]";
  884. log_.write(line, true);
  885. transaction_ = com_.request (transaction_, null, null, null, false);
  886. line = new String(transaction_.getResponse());
  887. log_.out(line);
  888. }
  889. /**
  890. * Main transaction loop. It send requests to server, get the response
  891. * and log the procedure while doing it.
  892. * @return the image request code to pass to image module
  893. */
  894. String run () {
  895. String code, image_code;
  896. String line;
  897. log_.out("Get traces");
  898. image_code = new String(code_);
  899. for (int trace =start_ ; trace < start_+duration_ ; trace += duration_/points_) {
  900. code = new String(code_) + GPS_TRACK_PREFIX + GPS_USE_TRACK + String.format("%04d", trace) + "01";
  901. transaction_ = com_.request(transaction_, code.getBytes(), GPS_BEGIN.getBytes(), GPS_END.getBytes(), false);
  902. line = new String(transaction_.code) + ": "
  903. + new String(transaction_.getResponse())
  904. + " Tr= " + (transaction_.arrival - transaction_.departure) + " [msec]";
  905. log_.write(line);
  906. _get_coordinates(transaction_.getResponse());
  907. image_code += GPS_IMAGE_PREFIX +
  908. String.format("%02d%02d%02d%02d%02d%02d", coordinates_[0], coordinates_[1],
  909. coordinates_[2], coordinates_[3],
  910. coordinates_[4], coordinates_[5]);
  911. }
  912. return image_code;
  913. }
  914. /** @name private helper API */
  915. /** @{ */
  916. /**
  917. * Extract coordinates from response
  918. * @param stream The stream to search
  919. * @return The coordinates buffer
  920. */
  921. private byte[] _get_coordinates (byte[] stream) {
  922. int start = Com.detect(stream, "GPGGA".getBytes(), stream.length);
  923. double latitude = _nmea2dec (Double.valueOf(
  924. new String (Arrays.copyOfRange(stream,
  925. start+GPS_LATITUDE_BEGIN,
  926. start+GPS_LATITUDE_END-2))));
  927. double longitude = _nmea2dec (Double.valueOf(
  928. new String(Arrays.copyOfRange(stream,
  929. start+GPS_LONGITUDE_BEGIN,
  930. start+GPS_LONGITUDE_END-2))));
  931. coordinates_[0] = (byte)(longitude); // longitude deg
  932. coordinates_[1] = (byte)((longitude - coordinates_[0]) * 60.0); // longitude '
  933. coordinates_[2] = (byte)((longitude - coordinates_[0]
  934. - coordinates_[1]/60.0)*3600); // longitude "
  935. coordinates_[3] = (byte)(latitude); // latitude deg
  936. coordinates_[4] = (byte)((latitude - coordinates_[3]) * 60.0); // latitude '
  937. coordinates_[5] = (byte)((latitude - coordinates_[3]
  938. - coordinates_[4]/60.0)*3600); // latitude "
  939. return coordinates_;
  940. }
  941. /**
  942. * A helper to convert the NMEA format to canonical
  943. * decimal coordinate format
  944. */
  945. double _nmea2dec (double c) {
  946. int d = (int)c/100;
  947. c -= d*100;
  948. return d + (c/60);
  949. }
  950. /** @} */
  951. }
  952. \end{verbatim}
  953. \section{Image.java}
  954. \begin{verbatim}
  955. /**
  956. * @file Image.java
  957. *
  958. * @author Christos Choutouridis AEM:8997
  959. * @email cchoutou@ece.auth.gr
  960. */
  961. package net.hoo2.auth.vmodem;
  962. /** @name imports */
  963. /** @{ */
  964. import java.io.*;
  965. /** @} */
  966. /**
  967. * @class Image
  968. *
  969. * Class to used for the error free and non error free image requests
  970. */
  971. class Image {
  972. static final int IMAGE_BUFFER_SIZE = 256*1024; /** image buffer size */
  973. static final byte[] IMAGE_BEGIN = {(byte)0xFF, (byte)0xD8}; /** jpeg image begin pattern */
  974. static final byte[] IMAGE_END = {(byte)0xFF, (byte)0xD9}; /** jpeg image end pattern */
  975. private Com com_; /** Reference to communication module */
  976. private Log log_; /** Reference to logging module */
  977. private Transaction transaction_; /** A transaction object to used as a buffer for all requests */
  978. private String filename_; /** The filename to store */
  979. private int items_; /** how many images to fetch */
  980. private byte[] code_; /** The image request code for the virtual lab */
  981. /**
  982. * Basic constructor
  983. * @param com The com module to use
  984. * @param log The log module to use
  985. * @param code The request code
  986. * @param filename The filename
  987. * @param items How many items to fetch
  988. */
  989. Image (Com com, Log log, byte[] code, String filename, int items) {
  990. com_ = com;
  991. log_ = log;
  992. // Allocate memory for the response
  993. transaction_= new Transaction(null, new byte[IMAGE_BUFFER_SIZE]);
  994. filename_ = filename;
  995. items_ = items;
  996. code_ = code;
  997. }
  998. /** Get function for the code */
  999. void code (byte[] code) { code_ = code; }
  1000. /**
  1001. * Functionality to drain the response buffer for the welcome message
  1002. * from the server
  1003. * @param code The code that we will use (for printing, not sending)
  1004. */
  1005. void caption (byte[] code) {
  1006. String line;
  1007. line = "Running video decoder with: " + new String(code);
  1008. log_.write(line, true);
  1009. transaction_ = com_.request (transaction_, null, null, null, false);
  1010. line = new String(transaction_.getResponse());
  1011. log_.out(line);
  1012. }
  1013. /**
  1014. * Main transaction loop. It send requests to server, get the response
  1015. * and log the procedure while doing it.
  1016. */
  1017. void run () {
  1018. String file, line;
  1019. BufferedOutputStream ostream;
  1020. for (int i =1 ; i<= items_ ; ++i) {
  1021. // Make the filename string
  1022. if (items_>1)
  1023. file = filename_ + "_" + i + ".jpg";
  1024. else
  1025. file = filename_ + ".jpg";
  1026. line = new String(code_) + ": ";
  1027. log_.write(line);
  1028. transaction_ = com_.request(transaction_, code_, IMAGE_BEGIN, IMAGE_END, true);
  1029. line = "File= " + file
  1030. + " Tr= " + (transaction_.arrival - transaction_.departure) + " [msec]"
  1031. + " Tt= " + (System.currentTimeMillis() - transaction_.departure) + " [msec]";
  1032. log_.write(line);
  1033. try {
  1034. ostream = new BufferedOutputStream(new FileOutputStream(file));
  1035. ostream.write(transaction_.response);
  1036. ostream.flush();
  1037. ostream.close();
  1038. }
  1039. catch (Exception exp) {
  1040. System.err.println ("Error creating " + file + exp.getMessage());
  1041. return;
  1042. }
  1043. }
  1044. }
  1045. }
  1046. \end{verbatim}
  1047. \end{document}