atd

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/atd
Log | Files | Refs

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:
Matc.c | 58++++++++++++++++++++++------------------------------------
Matd.c | 67++++++++++++++++++++++++++-----------------------------------------
Matd.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} }, };