Network programming assignment for University
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

258 líneas
8.2 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 (ch != -1 &&
  140. (!have_begin ||
  141. ( (bin || (detect (data.response, "\r\n\n\n".getBytes(), data.size) == -1))
  142. && (bin || (detect (data.response, "NO CARRIER".getBytes(), data.size) == -1))
  143. && (detect (data.response, end, data.size) == -1)
  144. )
  145. )
  146. );
  147. /*^
  148. * We loop until:
  149. * 1) server returns -1
  150. * 2) A end pattern arrives
  151. * 3) A "\r\n\n\n" sequence arrives (in character mode, not for binary files)
  152. * 4) A "NO CARRIER" sequence arrives (in character mode, not for binary files)
  153. */
  154. return data;
  155. }
  156. /**
  157. * @brief
  158. * A pattern detect functionality.
  159. *
  160. * Search in data input for the pattern and return its position if found.
  161. * @note
  162. * O(n^2) in time.
  163. * @param data The data buffer to search into
  164. * @param pattern The pattern to search for
  165. * @param max The maximum length to search
  166. * @return The position of pattern in data, or -1 if not found
  167. */
  168. static int detect (byte[] data, byte[] pattern, int max) {
  169. if (pattern != null) {
  170. for (int i =0 ; i<max && i<data.length - pattern.length; ++i) {
  171. boolean detected = true;
  172. for (int j=0 ; j<pattern.length ; ++j) {
  173. if (data[i+j] != pattern[j]) {
  174. detected = false;
  175. break;
  176. }
  177. }
  178. if (detected)
  179. return i;
  180. }
  181. }
  182. return -1;
  183. }
  184. /**@} */
  185. /** @name Private helper api */
  186. /**@{*/
  187. /**
  188. * Clear a buffer segment
  189. * @param buffer Buffer to clear
  190. * @param begin The starting point
  191. * @param end The ending point
  192. */
  193. private void _clear (byte[] buffer, int begin, int end) {
  194. for (int i=begin ; i<end && i<buffer.length ; ++i)
  195. buffer[i] = 0;
  196. }
  197. /**
  198. * Copy a buffer to another
  199. * @param dest The destination buffer
  200. * @param src The source buffer
  201. * @return The number of bytes copied
  202. */
  203. private int _copy (byte[] dest, byte[] src) {
  204. if (dest.length >= src.length) {
  205. for (int i=0 ; i<src.length ; ++i)
  206. dest[i] = src[i];
  207. return src.length;
  208. }
  209. return 0;
  210. }
  211. /**@}*/
  212. }
  213. /**
  214. * @class
  215. * Class to represent client-server transaction data
  216. */
  217. class Transaction {
  218. byte[] code; /**< request code from client */
  219. byte[] response; /**< response data from server */
  220. long departure; /**< request time */
  221. long arrival; /**< response time */
  222. int size; /**< size of response data in bytes */
  223. /**
  224. * Basic constructor
  225. * @param code Code to use
  226. * @param response Response buffer to use
  227. */
  228. Transaction (byte[] code, byte[] response) {
  229. this.code = code;
  230. this.response = response;
  231. departure = arrival = 0;
  232. size = 0;
  233. }
  234. /**
  235. * Get a copy of the response
  236. */
  237. byte[] getResponse() {
  238. return Arrays.copyOf(response, size);
  239. }
  240. }