[asterisk-addons-commits] mnicholson: branch mnicholson/chan-mobile-refactor r795 - /team/mnicholson/ch...
SVN commits to the Asterisk addons project
asterisk-addons-commits at lists.digium.com
Tue Feb 24 15:58:08 CST 2009
Author: mnicholson
Date: Tue Feb 24 15:58:08 2009
New Revision: 795
URL: http://svn.digium.com/svn-view/asterisk-addons?view=rev&rev=795
Log:
This commit includes a rewrite of the rfcomm parse into some what of a
recursive decendent fashion. This was prompted by the need to support reading
+CMGR responses which are used when reading SMS messages, and to make the code
easier to understand.
Modified:
team/mnicholson/chan-mobile-refactor/channels/chan_mobile.c
Modified: team/mnicholson/chan-mobile-refactor/channels/chan_mobile.c
URL: http://svn.digium.com/svn-view/asterisk-addons/team/mnicholson/chan-mobile-refactor/channels/chan_mobile.c?view=diff&rev=795&r1=794&r2=795
==============================================================================
--- team/mnicholson/chan-mobile-refactor/channels/chan_mobile.c (original)
+++ team/mnicholson/chan-mobile-refactor/channels/chan_mobile.c Tue Feb 24 15:58:08 2009
@@ -1203,7 +1203,183 @@
return outfd;
}
-/*
+#ifdef RFCOMM_READ_DEBUG
+#define rfcomm_read_debug(c) __rfcomm_read_debug(c)
+static void __rfcomm_read_debug(char c)
+{
+ if (c == '\r')
+ ast_debug(2, "rfcomm_read: \\r\n");
+ else if (c == '\n')
+ ast_debug(2, "rfcomm_read: \\n\n");
+ else
+ ast_debug(2, "rfcomm_read: %c\n", c);
+}
+#else
+#define rfcomm_read_debug(c)
+#endif
+
+/*!
+ * \brief Append the given character to the given buffer and increase the
+ * in_count.
+ */
+static void inline rfcomm_append_buf(char **buf, size_t count, size_t *in_count, char c)
+{
+ if (*in_count < count) {
+ (*in_count)++;
+ *(*buf)++ = c;
+ }
+}
+
+/*!
+ * \brief Read a character from the given stream and check if it matches what
+ * we expected.
+ */
+static int rfcomm_read_and_expect_char(int rsock, char *result, char expected)
+{
+ int res;
+ char c;
+
+ if (!result)
+ result = &c;
+
+ if ((res = read(rsock, result, 1)) < 1) {
+ return res;
+ }
+ rfcomm_read_debug(*result);
+
+ if (*result != expected) {
+ return -2;
+ }
+
+ return 1;
+}
+
+/*!
+ * \brief Read a character from the given stream and append it to the given
+ * buffer if it matches the expected character.
+ */
+static int rfcomm_read_and_append_char(int rsock, char **buf, size_t count, size_t *in_count, char *result, char expected)
+{
+ int res;
+ char c;
+
+ if (!result)
+ result = &c;
+
+ if ((res = rfcomm_read_and_expect_char(rsock, result, expected)) < 1) {
+ return res;
+ }
+
+ rfcomm_append_buf(buf, count, in_count, *result);
+ return 1;
+}
+
+/*!
+ * \brief Read until '\r\n'.
+ * This function consumes the '\r\n' but does not add it to buf.
+ */
+static int rfcomm_read_until_crlf(int rsock, char **buf, size_t count, size_t *in_count)
+{
+ int res;
+ char c;
+
+ while ((res = read(rsock, &c, 1)) == 1) {
+ rfcomm_read_debug(c);
+ if (c == '\r') {
+ if ((res = rfcomm_read_and_expect_char(rsock, &c, '\n')) == 1) {
+ break;
+ } else if (res == -2) {
+ rfcomm_append_buf(buf, count, in_count, '\r');
+ } else {
+ rfcomm_append_buf(buf, count, in_count, '\r');
+ break;
+ }
+ }
+
+ rfcomm_append_buf(buf, count, in_count, c);
+ }
+ return res;
+}
+
+/*!
+ * \brief Read the remainder of an AT SMS prompt.
+ * \note the entire parsed string is '\r\n> '
+ *
+ * By the time this function is executed, only a ' ' is left to read.
+ */
+static int rfcomm_read_sms_prompt(int rsock, char **buf, size_t count, size_t *in_count)
+{
+ int res;
+ if ((res = rfcomm_read_and_append_char(rsock, buf, count, in_count, NULL, ' ')) < 1)
+ goto e_return;
+
+ return 1;
+
+e_return:
+ ast_log(LOG_ERROR, "error parsing SMS prompt on rfcomm socket\n");
+ return res;
+}
+
+/*!
+ * \brief Read and AT result code.
+ * \note the entire parsed string is '\r\n<result code>\r\n'
+ */
+static int rfcomm_read_result(int rsock, char **buf, size_t count, size_t *in_count)
+{
+ int res;
+ char c;
+
+ if ((res = rfcomm_read_and_expect_char(rsock, &c, '\n')) < 1) {
+ goto e_return;
+ }
+
+ if ((res = rfcomm_read_and_append_char(rsock, buf, count, in_count, &c, '>')) == 1) {
+ return rfcomm_read_sms_prompt(rsock, buf, count, in_count);
+ } else if (res != -2) {
+ goto e_return;
+ }
+
+ rfcomm_append_buf(buf, count, in_count, c);
+ res = rfcomm_read_until_crlf(rsock, buf, count, in_count);
+
+ if (res != 1)
+ return res;
+
+ /* check for CMGR, which contains an embedded \r\n */
+ if (*in_count >= 5 && !strncmp(*buf - *in_count, "+CMGR", 5)) {
+ rfcomm_append_buf(buf, count, in_count, '\r');
+ rfcomm_append_buf(buf, count, in_count, '\n');
+ return rfcomm_read_until_crlf(rsock, buf, count, in_count);
+ }
+
+ return 1;
+
+e_return:
+ ast_log(LOG_ERROR, "error parsing AT result on rfcomm socket");
+ return res;
+}
+
+/*!
+ * \brief Read the remainder of an AT command.
+ * \note the entire parsed string is '<at command>\r'
+ */
+static int rfcomm_read_command(int rsock, char **buf, size_t count, size_t *in_count)
+{
+ int res;
+ char c;
+
+ while ((res = read(rsock, &c, 1)) == 1) {
+ rfcomm_read_debug(c);
+ /* stop when we get to '\r' */
+ if (c == '\r')
+ break;
+
+ rfcomm_append_buf(buf, count, in_count, c);
+ }
+ return res;
+}
+
+/*!
* \brief Read one Hayes AT message from an rfcomm socket.
* \param rsock the rfcomm socket to read from
* \param buf the buffer to store the result in
@@ -1218,68 +1394,31 @@
* \r\n>
* \endverbatim
*
- * These formats corispond to AT result codes, AT commands, and the AT SMS
+ * These formats correspond to AT result codes, AT commands, and the AT SMS
* prompt respectively. When messages are read the leading and trailing '\r'
* and '\n' characters are discarded. If the given buffer is not large enough
* to hold the response, what does not fit in the buffer will be dropped.
*
* \note The rfcomm connection to the device is asynchronous, so there is no
* guarantee that responses will be returned in a single read() call. We handle
- * this by blocking until we can read an entire response. *
+ * this by blocking until we can read an entire response.
+ *
+ * \retval 0 end of file
+ * \retval -1 read error
+ * \retval -2 parse error
+ * \retval other the number of characters added to buf
*/
static ssize_t rfcomm_read(int rsock, char *buf, size_t count)
{
-
ssize_t res;
- int have_msg = 0, got_cr = 0, in_count = 0;
+ size_t in_count = 0;
char c;
- /* messages are in the form '\r\nMSG\r\n'. We read one character at a
- * time and parse out the \r\n pairs as we go. */
- while ((res = read(rsock, &c, 1)) != -1) {
- /* check for EOF */
- if (res == 0)
- break;
-
- /* check for '\r\n' or '\r'*/
- if (got_cr && c == '\n' && have_msg) {
- break;
- } else if (got_cr) {
- if (c != '\r')
- got_cr = 0;
-
- /* insert a '\r', because we ignored one above */
- if (in_count < count) {
- in_count++;
- *buf++ = '\r';
- }
- } else if (c == '\r') {
- if (have_msg) {
- /* possible start of ending '\r\n' */
- got_cr = 1;
- continue;
- } else if (in_count) {
- /* end of at command */
- break;
- }
- }
-
- /* store this character, if there is space in the buffer */
- if (in_count < count) {
- in_count++;
- *buf++ = c;
- }
-
- /* check for sms prompt */
- if (in_count == 2 && !strncmp(buf - 2, "> ", 2)) {
- break;
- } else if (in_count == 2 && !strncmp(buf - 2, "\r\n", 2)) {
- /* got initial \r\n */
- buf -= 2;
- in_count = 0;
- have_msg = 1;
- got_cr = 0;
- }
+ if ((res = rfcomm_read_and_expect_char(rsock, &c, '\r')) == 1) {
+ res = rfcomm_read_result(rsock, &buf, count, &in_count);
+ } else if (res == -2) {
+ rfcomm_append_buf(&buf, count, &in_count, c);
+ res = rfcomm_read_command(rsock, &buf, count, &in_count);
}
if (res < 1)
More information about the asterisk-addons-commits
mailing list