/at_read.c

http://datacard.googlecode.com/ · C · 238 lines · 177 code · 39 blank · 22 comment · 50 complexity · f46cb1e8badf7639de10afd48375f52e MD5 · raw file

  1. /*
  2. Copyright (C) 2009 - 2010
  3. Artem Makhutov <artem@makhutov.org>
  4. http://www.makhutov.org
  5. Dmitry Vagin <dmitry2004@yandex.ru>
  6. bg <bg_one@mail.ru>
  7. */
  8. #ifdef HAVE_CONFIG_H
  9. #include <config.h>
  10. #endif /* HAVE_CONFIG_H */
  11. #ifndef _GNU_SOURCE
  12. #define _GNU_SOURCE /* vasprintf() in asterisk/utils.h */
  13. #endif /* #ifndef _GNU_SOURCE */
  14. #include <sys/types.h>
  15. #include <errno.h>
  16. #include <asterisk.h>
  17. #include <asterisk/channel.h> /* ast_waitfor_n_fd() */
  18. #include <asterisk/logger.h> /* ast_debug() */
  19. #include "chan_datacard.h"
  20. #include "at_read.h"
  21. #include "ringbuffer.h"
  22. /*!
  23. * \brief Wait for activity on an socket
  24. * \param fd -- file descriptor
  25. * \param ms -- pointer to an int containing a timeout in ms
  26. * \return 0 on timeout and the socket fd (non-zero) otherwise
  27. * \retval 0 timeout
  28. */
  29. EXPORT_DEF int at_wait (int fd, int* ms)
  30. {
  31. int exception, outfd;
  32. outfd = ast_waitfor_n_fd (&fd, 1, ms, &exception);
  33. if (outfd < 0)
  34. {
  35. outfd = 0;
  36. }
  37. return outfd;
  38. }
  39. #/* return number of bytes readed */
  40. EXPORT_DEF ssize_t at_read (int fd, const char * dev, struct ringbuffer* rb)
  41. {
  42. struct iovec iov[2];
  43. int iovcnt;
  44. ssize_t n = -1;
  45. /* TODO: read until major error */
  46. iovcnt = rb_write_iov (rb, iov);
  47. if (iovcnt > 0)
  48. {
  49. n = readv (fd, iov, iovcnt);
  50. if (n < 0)
  51. {
  52. if (errno != EINTR && errno != EAGAIN)
  53. {
  54. ast_debug (1, "[%s] readv() error: %d\n", dev, errno);
  55. return n;
  56. }
  57. return 0;
  58. }
  59. else if (n > 0)
  60. {
  61. rb_write_upd (rb, n);
  62. ast_debug (5, "[%s] receive %zu byte, used %zu, free %zu, read %zu, write %zu\n",
  63. dev, n, rb_used (rb), rb_free (rb), rb->read, rb->write);
  64. iovcnt = rb_read_all_iov (rb, iov);
  65. if (iovcnt > 0)
  66. {
  67. if (iovcnt == 2)
  68. {
  69. ast_debug (5, "[%s] [%.*s%.*s]\n", dev,
  70. (int) iov[0].iov_len, (char*) iov[0].iov_base,
  71. (int) iov[1].iov_len, (char*) iov[1].iov_base);
  72. }
  73. else
  74. {
  75. ast_debug (5, "[%s] [%.*s]\n", dev,
  76. (int) iov[0].iov_len, (char*) iov[0].iov_base);
  77. }
  78. }
  79. }
  80. }
  81. else
  82. ast_log (LOG_ERROR, "[%s] at cmd receive buffer overflow\n", dev);
  83. return n;
  84. }
  85. EXPORT_DEF int at_read_result_iov (const char * dev, int * read_result, struct ringbuffer* rb, struct iovec iov[2])
  86. {
  87. int iovcnt = 0;
  88. int res;
  89. size_t s;
  90. s = rb_used (rb);
  91. if (s > 0)
  92. {
  93. /* ast_debug (5, "[%s] d_read_result %d len %d input [%.*s]\n", dev, *read_result, s, MIN(s, rb->size - rb->read), (char*)rb->buffer + rb->read);
  94. */
  95. if (*read_result == 0)
  96. {
  97. res = rb_memcmp (rb, "\r\n", 2);
  98. if (res == 0)
  99. {
  100. rb_read_upd (rb, 2);
  101. *read_result = 1;
  102. return at_read_result_iov (dev, read_result, rb, iov);
  103. }
  104. else if (res > 0)
  105. {
  106. if (rb_memcmp (rb, "\n", 1) == 0)
  107. {
  108. ast_debug (5, "[%s] multiline response\n", dev);
  109. rb_read_upd (rb, 1);
  110. return at_read_result_iov (dev, read_result, rb, iov);
  111. }
  112. if (rb_read_until_char_iov (rb, iov, '\r') > 0)
  113. {
  114. s = iov[0].iov_len + iov[1].iov_len + 1;
  115. }
  116. rb_read_upd (rb, s);
  117. return at_read_result_iov (dev, read_result, rb, iov);
  118. }
  119. return 0;
  120. }
  121. else
  122. {
  123. if (rb_memcmp (rb, "+CSSI:", 6) == 0)
  124. {
  125. iovcnt = rb_read_n_iov (rb, iov, 8);
  126. if (iovcnt > 0)
  127. {
  128. *read_result = 0;
  129. }
  130. return iovcnt;
  131. }
  132. else if (rb_memcmp (rb, "\r\n+CSSU:", 8) == 0 || rb_memcmp (rb, "\r\n+CMS ERROR:", 13) == 0 || rb_memcmp (rb, "\r\n+CMGS:", 8) == 0)
  133. {
  134. rb_read_upd (rb, 2);
  135. return at_read_result_iov (dev, read_result, rb, iov);
  136. }
  137. else if (rb_memcmp (rb, "> ", 2) == 0)
  138. {
  139. *read_result = 0;
  140. return rb_read_n_iov (rb, iov, 2);
  141. }
  142. else if (rb_memcmp (rb, "+CMGR:", 6) == 0 || rb_memcmp (rb, "+CNUM:", 6) == 0 || rb_memcmp (rb, "ERROR+CNUM:", 11) == 0 || rb_memcmp (rb, "+CLCC:", 6) == 0)
  143. {
  144. iovcnt = rb_read_until_mem_iov (rb, iov, "\n\r\nOK\r\n", 7);
  145. if (iovcnt > 0)
  146. {
  147. *read_result = 0;
  148. }
  149. return iovcnt;
  150. }
  151. else
  152. {
  153. iovcnt = rb_read_until_mem_iov (rb, iov, "\r\n", 2);
  154. if (iovcnt > 0)
  155. {
  156. *read_result = 0;
  157. s = iov[0].iov_len + iov[1].iov_len + 1;
  158. return rb_read_n_iov (rb, iov, s);
  159. }
  160. }
  161. }
  162. }
  163. return 0;
  164. }
  165. EXPORT_DEF at_res_t at_read_result_classification (struct ringbuffer * rb, size_t len)
  166. {
  167. at_res_t at_res = RES_UNKNOWN;
  168. unsigned idx;
  169. for(idx = at_responses.ids_first; idx < at_responses.ids; idx++)
  170. {
  171. if (rb_memcmp (rb, at_responses.responses[idx].id, at_responses.responses[idx].idlen) == 0)
  172. {
  173. at_res = at_responses.responses[idx].res;
  174. break;
  175. }
  176. }
  177. switch (at_res)
  178. {
  179. case RES_SMS_PROMPT:
  180. len = 2;
  181. break;
  182. case RES_CMGR:
  183. len += 7;
  184. break;
  185. case RES_CSSI:
  186. len = 8;
  187. break;
  188. default:
  189. len += 1;
  190. break;
  191. }
  192. rb_read_upd (rb, len);
  193. /* ast_debug (5, "receive result '%s'\n", at_res2str (at_res));
  194. */
  195. return at_res;
  196. }