summaryrefslogtreecommitdiffstats
path: root/gatchat/gatserver.c
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2010-03-24 19:37:18 -0500
committerDenis Kenzior <denkenz@gmail.com>2010-03-24 19:37:18 -0500
commita9c089ab345f06435c08ed87c86affb1c953ce71 (patch)
tree6114afba162155cda80f510eb3c4f8f301a0b677 /gatchat/gatserver.c
parent1f99435a4234d4247cd43d1890bd30c1362782e8 (diff)
downloadofono-a9c089ab345f06435c08ed87c86affb1c953ce71.tar.bz2
Refactor basic command parsing
Make more bullet proof and efficient
Diffstat (limited to 'gatchat/gatserver.c')
-rw-r--r--gatchat/gatserver.c105
1 files changed, 46 insertions, 59 deletions
diff --git a/gatchat/gatserver.c b/gatchat/gatserver.c
index 71e366dd..711bf785 100644
--- a/gatchat/gatserver.c
+++ b/gatchat/gatserver.c
@@ -308,68 +308,58 @@ next:
return i + 1;
}
-static gboolean get_basic_prefix(const char *buf, char *out_prefix)
+static int get_basic_prefix_size(const char *buf)
{
- char c = *buf;
- char prefix[4];
-
- if (g_ascii_isalpha(c)) {
- c = g_ascii_toupper(c);
-
- if (c == 'S') {
- int i;
-
- prefix[0] = 'S';
+ if (g_ascii_isalpha(buf[0])) {
+ if (g_ascii_toupper(buf[0]) == 'S') {
+ int size;
/* V.250 5.3.2 'S' command follows with a parameter
- * number. Limited to two digits since 100
- * S-registers should be enough.
+ * number.
*/
- for (i = 1; i < 3 && g_ascii_isdigit(buf[i]); i++)
- prefix[i] = buf[i];
-
- prefix[i] = '\0';
+ for (size = 1; g_ascii_isdigit(buf[size]); size++)
+ ;
/*
* Do some basic sanity checking, don't accept 00, 01,
* etc or empty S values
*/
- if (prefix[1] == '\0')
- return FALSE;
-
- if (prefix[1] == '0' && prefix[2] != '\0')
- return FALSE;
- } else {
- prefix[0] = c;
- prefix[1] = '\0';
- }
- } else if (c == '&') {
- prefix[0] = '&';
+ if (size == 1)
+ return 0;
- if (g_ascii_isalpha(buf[1] == FALSE))
- return FALSE;
+ if (size > 2 && buf[1] == '0')
+ return 0;
- prefix[1] = g_ascii_toupper(buf[1]);
- prefix[2] = '\0';
+ return size;
+ }
+
+ /* All other cases it is a simple 1 character prefix */
+ return 1;
}
+
+ if (buf[0] == '&') {
+ if (g_ascii_isalpha(buf[0] == FALSE))
+ return 0;
- memcpy(out_prefix, prefix, sizeof(prefix));
+ return 2;
+ }
- return TRUE;
+ return 0;
}
static unsigned int parse_basic_command(GAtServer *server, char *buf)
{
- char *command;
- char prefix[4];
- unsigned int i;
- GAtServerRequestType type;
gboolean seen_equals = FALSE;
+ char prefix[4], tmp;
+ unsigned int i, prefix_size;
+ GAtServerRequestType type;
- if (!get_basic_prefix(buf, prefix))
+ prefix_size = get_basic_prefix_size(buf);
+ if (prefix_size == 0)
return 0;
- i = strlen(prefix);
+ i = prefix_size;
+ prefix[0] = g_ascii_toupper(buf[0]);
if (prefix[0] == 'D') {
type = G_AT_SERVER_REQUEST_TYPE_SET;
@@ -384,18 +374,7 @@ static unsigned int parse_basic_command(GAtServer *server, char *buf)
goto done;
}
- if (buf[i] == '\0' || buf[i] == ';') {
- type = G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY;
- goto done;
- }
-
- /* Additional commands may follow a command without any character
- * required for separation.
- */
- if (is_basic_command_prefix(&buf[i])) {
- type = G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY;
- goto done;
- }
+ type = G_AT_SERVER_REQUEST_TYPE_COMMAND_ONLY;
/* Match '?', '=', '=?' and '=xxx' */
if (buf[i] == '=') {
@@ -411,19 +390,27 @@ static unsigned int parse_basic_command(GAtServer *server, char *buf)
else
type = G_AT_SERVER_REQUEST_TYPE_QUERY;
} else {
+ int before = i;
+
/* V.250 5.3.1 The subparameter (if any) are all digits */
while (g_ascii_isdigit(buf[i]))
i++;
- type = G_AT_SERVER_REQUEST_TYPE_SET;
+ if (i - before > 0)
+ type = G_AT_SERVER_REQUEST_TYPE_SET;
}
done:
- command = g_strndup(buf, i);
-
- at_command_notify(server, command, prefix, type);
-
- g_free(command);
+ if (prefix_size <= 3) {
+ memcpy(prefix + 1, buf + 1, prefix_size - 1);
+ prefix[prefix_size] = '\0';
+
+ tmp = buf[i];
+ buf[i] = '\0';
+ at_command_notify(server, buf, prefix, type);
+ buf[i] = tmp;
+ } else /* Handle S-parameter with 100+ */
+ g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR);
/* Commands like ATA, ATZ cause the remainder line
* to be ignored.
@@ -431,7 +418,7 @@ done:
if (prefix[0] == 'A' || prefix[0] == 'Z')
return strlen(buf);
- /* Consumed the seperator ';' */
+ /* Consume the seperator ';' */
if (buf[i] == ';')
i += 1;