[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