commit 21bea582e5da39d4bba09627381790dd651c8653
parent e07587e3c3c55a4bbe8d6a1114c0e58c8e44d1ea
Author: Nihal Jere <nihal@nihaljere.xyz>
Date: Tue, 25 May 2021 16:20:55 -0500
add type system for wire protocol
Now the length of strings must be specified, and there is
no null terminator over the wire. This is a step making the wire
protocol more powerful
Diffstat:
M | atc.c | | | 58 | ++++++++++++++++++++++------------------------------------ |
M | atd.c | | | 67 | ++++++++++++++++++++++++++----------------------------------------- |
M | atd.h | | | 22 | ++++++++++++++++++---- |
3 files changed, 66 insertions(+), 81 deletions(-)
diff --git a/atc.c b/atc.c
@@ -9,54 +9,40 @@
int
sendcode(int fd, int code)
{
- int ret, left = 2;
- char buf[2];
- char *ptr = buf;
- buf[0] = code;
- buf[1] = '\0';
-
- while (left > 0) {
- ret = write(fd, ptr, left);
- if (ret == -1)
- return -1;
-
- ptr += ret;
- left -= ret;
- }
-
- return 0;
+ char c = code;
+ /* TODO make more robust */
+ int ret = write(fd, &c, 1);
+ if (ret == -1)
+ return -1;
}
int
dial(int fd, char *num)
{
- char dialcode = CMD_DIAL;
- int ret, left = strlen(num);
- do {
- ret = write(fd, &dialcode, 1);
- if (ret == -1)
- return -1;
- if (ret == 1)
- break;
- } while (ret);
+ int ret, len = strlen(num), left;
+ char buf[PHONE_NUMBER_MAX_LEN + 3];
+ char *ptr;
+
+ if (len > PHONE_NUMBER_MAX_LEN)
+ return -1;
+
+ buf[0] = CMD_DIAL;
+ buf[1] = len & 0xFF;
+ buf[2] = (len >> 8) & 0xFF;
+
+ memcpy(buf + 3, num, len);
+
+ left = len + 3;
+ ptr = buf;
do {
- ret = write(fd, num, left);
+ ret = write(fd, ptr, left);
if (ret == -1)
return -1;
- num += ret;
+ ptr += ret;
left -= ret;
} while (left);
- do {
- ret = write(fd, &"\0", 1);
- if (ret == -1)
- return -1;
- if (ret == 1)
- break;
- } while (ret);
-
-
return 0;
}
diff --git a/atd.c b/atd.c
@@ -44,72 +44,57 @@ struct fdbuf {
char *outptr;
};
+ssize_t
+parse_str(char *in, char **out)
+{
+ short len;
+ char *ptr = in;
+ len = ptr[0] + (ptr[1] << 8);
+ assert(len < BUFSIZE);
+ ptr += 2;
+
+ *out = malloc(len);
+ if (!(*out))
+ return -1;
+
+ memcpy(*out, ptr, len);
+ return len + 2;
+}
+
/* add one command to queue, returns the number of bytes intepreted if the
* command was validated and added successfully, -1 if the queue is full, -2 if
- * the command is invalid but terminated, and -3 if the command is invalid and
- * unterminated */
+ * the command is invalid but terminated */
ssize_t cmdadd(struct fdbuf fdbuf) {
struct command cmd = {0, CMD_NONE, NULL};
- char *end = memchr(fdbuf.out, '\0', fdbuf.outlen);
char *ptr = fdbuf.out;
size_t count = 0;
if (cmdq.count == QUEUE_SIZE)
return -1;
- /* given that we have a max length for a command, if the buffer does not
- * contain a terminated command, we can assume that the command is
- * incomplete and read more data from the fd until the buffer is full. If
- * it still doesn't contain a terminated command, then we know that we are
- * dealing with garbage, and we throw it out, and inform the client. In
- * case of garbage, two '\0' in a row flush the buffer */
- if (end == NULL)
- return -3;
-
cmd.op = *(ptr++);
switch (cmd.op) {
case CMD_DIAL:
- char num[PHONE_NUMBER_MAX_LEN];
- while (*ptr != '\0') {
- if (count > PHONE_NUMBER_MAX_LEN || strchr(DIALING_DIGITS, *ptr) == NULL)
- goto bad;
-
- num[count] = *(ptr++);
- count++;
- }
+ count = parse_str(ptr, &cmd.data.dial.num);
+ if (count == -1)
+ return -1;
- cmd.data.dial.num = malloc(count + 1);
- if (cmd.data.dial.num == NULL)
- goto bad;
-
- memcpy(cmd.data.dial.num, num, count);
- ((char*)cmd.data.dial.num)[count] = '\0';
-
- fprintf(stderr, "received dial with number %s\n", cmd.data);
+ fprintf(stderr, "received dial with number %*.*s\n", count, count, cmd.data.dial.num);
break;
case CMD_ANSWER:
- if (*ptr != '\0')
- goto bad;
fprintf(stderr, "received answer\n");
break;
case CMD_HANGUP:
fprintf(stderr, "received hangup\n");
- if (*ptr != '\0')
- goto bad;
- fprintf(stderr, "received hangup\n");
break;
default:
- fprintf(stderr, "got code: %d\n", *(ptr - 1));
+ fprintf(stderr, "got code: %d\n", cmd.op);
}
/* we already checked that the queue has enough capacity */
command_enqueue(cmd);
- return ptr - fdbuf.out;
-
-bad:
- fdbuf.outptr = end + 1;
- return -2;
+ return count + 1;
}
size_t
@@ -304,9 +289,9 @@ int main(int argc, char *argv[])
continue;
if (cmd.op == CMD_DIAL) {
- ret = snprintf(fdbufs[BACKEND].in, BUFSIZE, cmd_to_at[cmd.op], cmd.data.dial.num);
+ ret = snprintf(fdbufs[BACKEND].in, BUFSIZE, cmddata[cmd.op].atcmd, cmd.data.dial.num);
} else {
- ret = snprintf(fdbufs[BACKEND].in, BUFSIZE, cmd_to_at[cmd.op]);
+ ret = snprintf(fdbufs[BACKEND].in, BUFSIZE, cmddata[cmd.op].atcmd);
}
fprintf(stderr, "after data\n");
if (ret >= BUFSIZE) {
diff --git a/atd.h b/atd.h
@@ -1,6 +1,7 @@
#define PHONE_NUMBER_MAX_LEN 15
#define DIALING_DIGITS "0123456789*#+ABC"
+/* should have at most 256 things */
enum ops {
CMD_NONE = 0,
CMD_DIAL,
@@ -18,8 +19,21 @@ struct command {
} data;
};
-char *cmd_to_at[] = {
- [CMD_DIAL] = "ATD%s;\r\n",
- [CMD_ANSWER] = "ATA\r\n",
- [CMD_HANGUP] = "ATH\r\n",
+
+/* should have at most 256 things */
+enum types {
+ TYPE_NONE = 0,
+ TYPE_STRING,
+};
+
+#define MAX_PARAMS 1
+struct command_args {
+ char *atcmd;
+ char type[MAX_PARAMS + 1];
+};
+
+struct command_args cmddata[] = {
+ [CMD_DIAL] = { "ATD%s;\r", { TYPE_STRING, TYPE_NONE} },
+ [CMD_ANSWER] = { "ATA\r", { TYPE_NONE} },
+ [CMD_HANGUP] = { "ATH\r", { TYPE_NONE} },
};