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.
 
 
 
 

259 lines
8.1 KiB

  1. /**
  2. * @file Com.java
  3. *
  4. * @author Christos Choutouridis AEM:8997
  5. * @email cchoutou@ece.auth.gr
  6. */
  7. package net.hoo2.auth.vmodem;
  8. /** @name imports */
  9. /** @{ */
  10. import java.util.Arrays;
  11. import ithakimodem.*;
  12. /** @} */
  13. /**
  14. * @class Com
  15. *
  16. * Wrapper object of the provided Modem class to provide
  17. * a convenient and common API for all the session functionalities
  18. */
  19. class Com {
  20. static final int SPEED_DEFAULT = 48000; /** default communication speed [bps] */
  21. static final int TIMEOUT_DEFAULT = 2000; /** default timeout values [sec] */
  22. static final String URL_DEFAULT = "ithaki"; /** Default destination. Ithaki of-course */
  23. private Modem modem_; /** Ref to Modem */
  24. private int speed_; /** Communication speed [bps] */
  25. private int timeout_; /** communication timeout [sec] */
  26. /**
  27. * Basic constructor
  28. */
  29. Com () {
  30. modem_ = new Modem();
  31. speed_ = SPEED_DEFAULT;
  32. timeout_ = TIMEOUT_DEFAULT;
  33. modem_.setSpeed(speed_);
  34. modem_.setTimeout(timeout_);
  35. }
  36. /** A more fancy constructor
  37. *
  38. * @param log Reference to Log to use
  39. * @param speed The desired speed [bps]
  40. * @param timeout The desired timeout [sec]
  41. * @note
  42. * Currently not used
  43. */
  44. Com (Log log, int speed, int timeout) {
  45. modem_ = new Modem();
  46. speed_ = speed;
  47. timeout_ = timeout;
  48. modem_.setSpeed(speed_);
  49. modem_.setTimeout(timeout_);
  50. }
  51. /** @name Mutator interface */
  52. /**@{ */
  53. /** Get the current timeout value [sec] */
  54. int timeout () { return timeout_; }
  55. /** Set the timeout value [sec] */
  56. void timeout (int timeout) {
  57. if (timeout_ != timeout) {
  58. timeout_ = timeout;
  59. modem_.setTimeout(timeout_);
  60. }
  61. }
  62. /** Get the current speed [bps] */
  63. int speed () { return speed_; }
  64. /** Set the speed [bps] */
  65. void speed (int speed) {
  66. if (speed_ != speed) {
  67. speed_ = speed;
  68. modem_.setSpeed(speed_);
  69. }
  70. }
  71. /**@} */
  72. /** @name Public API of the class */
  73. /**@{ */
  74. /** Open a communication channel with a URL */
  75. boolean open (String url) { return modem_.open(url); }
  76. /** Open a communication channel with Ithaki */
  77. boolean open () { return modem_.open(URL_DEFAULT); }
  78. /** Close the connection */
  79. boolean close() { return modem_.close(); }
  80. /**
  81. * @grief The basic communication functionality
  82. *
  83. * This function sends a request to server and return the response. In order to
  84. * do that, the main reading loop seeks for the starting pattern and use the data
  85. * from that point up to the ending pattern. This is very helpful for binary incoming
  86. * data.
  87. * @note
  88. * Blocking mode
  89. * @param data Reference to Transaction data to use @see Transaction
  90. * @param code The request code to send
  91. * @param begin The starting pattern of the response data
  92. * @param end The ending pattern of the response data
  93. * @param bin A flag to indicate that the data are in binary form
  94. * @return Reference to Transaction object with the response data. @see Transaction
  95. */
  96. Transaction request (Transaction data, byte[] code, byte[] begin, byte[] end, boolean bin) {
  97. int ch =0;
  98. boolean have_begin = (begin != null) ? false : true;
  99. boolean incoming = false;
  100. // Clear the receive buffer first
  101. _clear (data.response, 0, data.response.length);
  102. if (code != null) {
  103. // if we have a request
  104. data.code = code; // store the request code for the transaction
  105. modem_.write(data.code); // send the code and mark the time
  106. modem_.write((int)'\r');
  107. data.departure = System.currentTimeMillis();// - (long)((8*(data.code.length+1))*(1000.0/speed_));
  108. }
  109. // main receive loop
  110. data.size =0;
  111. do {
  112. // escape guard for memory protection
  113. if (data.size >= data.response.length) {
  114. data.size =0;
  115. return data;
  116. }
  117. // read the data byte from server
  118. try {
  119. ch = modem_.read();
  120. }
  121. catch (Exception e) {
  122. // Oops!!!! something went wrong. Break and return :(
  123. System.err.println (e.getMessage());
  124. data.size =0;
  125. return data;
  126. }
  127. if (!incoming) {
  128. // first byte triggered. mark the time
  129. incoming = true;
  130. data.arrival = System.currentTimeMillis();// - (long)(8*(1000.0/speed_));
  131. }
  132. data.response [data.size++] = (byte)ch; // store the byte
  133. if (!have_begin && (detect(data.response, begin, data.size) != -1)) {
  134. // If begin pattern detected, start over.
  135. _clear(data.response, 0, data.size);
  136. data.size = _copy (data.response, begin);
  137. have_begin = true;
  138. }
  139. } while (
  140. ch != -1 && (
  141. !have_begin || (
  142. (bin || (detect (data.response, "\r\n\n\n".getBytes(), data.size) == -1))
  143. && (bin || (detect (data.response, "NO CARRIER".getBytes(), data.size) == -1))
  144. && (detect (data.response, end, data.size) == -1)
  145. )
  146. )
  147. );
  148. /*^
  149. * We loop until:
  150. * 1) server returns -1
  151. * 2) A end pattern arrives
  152. * 3) A "\r\n\n\n" sequence arrives (in character mode, not for binary files)
  153. * 4) A "NO CARRIER" sequence arrives (in character mode, not for binary files)
  154. */
  155. return data;
  156. }
  157. /**
  158. * @brief
  159. * A pattern detect functionality.
  160. *
  161. * Search in data input for the pattern and return its position if found.
  162. * @note
  163. * O(n^2) in time.
  164. * @param data The data buffer to search into
  165. * @param pattern The pattern to search for
  166. * @param max The maximum length to search
  167. * @return The position of pattern in data, or -1 if not found
  168. */
  169. static int detect (byte[] data, byte[] pattern, int max) {
  170. if (pattern != null) {
  171. for (int i =0 ; i<max && i<data.length - pattern.length; ++i) {
  172. boolean detected = true;
  173. for (int j=0 ; j<pattern.length ; ++j) {
  174. if (data[i+j] != pattern[j]) {
  175. detected = false;
  176. break;
  177. }
  178. }
  179. if (detected)
  180. return i;
  181. }
  182. }
  183. return -1;
  184. }
  185. /**@} */
  186. /** @name Private helper api */
  187. /**@{*/
  188. /**
  189. * Clear a buffer segment
  190. * @param buffer Buffer to clear
  191. * @param begin The starting point
  192. * @param end The ending point
  193. */
  194. private void _clear (byte[] buffer, int begin, int end) {
  195. for (int i=begin ; i<end && i<buffer.length ; ++i)
  196. buffer[i] = 0;
  197. }
  198. /**
  199. * Copy a buffer to another
  200. * @param dest The destination buffer
  201. * @param src The source buffer
  202. * @return The number of bytes copied
  203. */
  204. private int _copy (byte[] dest, byte[] src) {
  205. if (dest.length >= src.length) {
  206. for (int i=0 ; i<src.length ; ++i)
  207. dest[i] = src[i];
  208. return src.length;
  209. }
  210. return 0;
  211. }
  212. /**@}*/
  213. }
  214. /**
  215. * @class
  216. * Class to represent client-server transaction data
  217. */
  218. class Transaction {
  219. byte[] code; /** request code from client */
  220. byte[] response; /** response data from server */
  221. long departure; /** request time */
  222. long arrival; /** response time */
  223. int size; /** size of response data in bytes */
  224. /**
  225. * Basic constructor
  226. * @param code Code to use
  227. * @param response Response buffer to use
  228. */
  229. Transaction (byte[] code, byte[] response) {
  230. this.code = code;
  231. this.response = response;
  232. departure = arrival = 0;
  233. size = 0;
  234. }
  235. /**
  236. * Get a copy of the response
  237. */
  238. byte[] getResponse() {
  239. return Arrays.copyOf(response, size);
  240. }
  241. }