From ca5105a6bb357267cd0f343bad10f3f83fe7abab Mon Sep 17 00:00:00 2001 From: Peter McGoron Date: Sun, 1 Jan 2023 21:10:02 +0000 Subject: [PATCH] start rewrite kernel --- software/src/buf.c | 6 +- software/src/buf.h | 2 + software/src/lsc.h | 112 +++++++++++++++++++++++++++++++++++++ software/src/main.c | 131 +++++++++++++++++++++++++++++++++++++------- software/src/sock.c | 62 +++++++++++++-------- software/src/sock.h | 16 ------ 6 files changed, 270 insertions(+), 59 deletions(-) create mode 100644 software/src/lsc.h diff --git a/software/src/buf.c b/software/src/buf.c index 901beab..8caccc5 100644 --- a/software/src/buf.c +++ b/software/src/buf.c @@ -6,12 +6,16 @@ bool buf_read_sock(int sock, struct bufptr *bp) { - ssize_t l = zsock_recv(sock, bp->p, bp->left, 0); + if (bp->left < 2) + return false; + + ssize_t l = zsock_recv(sock, bp->p, bp->left - 1, 0); if (l < 0) return false; bp->left -= l; bp->p += l; + *bp->p = 0; return true; } diff --git a/software/src/buf.h b/software/src/buf.h index 83b9711..d7555a4 100644 --- a/software/src/buf.h +++ b/software/src/buf.h @@ -2,6 +2,8 @@ /* This is a pointer _into_ a buffer. It is incremented (and the variable * "left" decremented) after each operation. + * + * Space is always left for a NUL terminator. */ struct bufptr { char *p; diff --git a/software/src/lsc.h b/software/src/lsc.h new file mode 100644 index 0000000..80090b6 --- /dev/null +++ b/software/src/lsc.h @@ -0,0 +1,112 @@ +#ifndef LSC +#define LSC +#include + +#ifndef LSC_MAXARG +# define LSC_MAXARG 32 +#endif + +#ifndef LSC_MAXBUF +# define LSC_MAXBUF 1024 +#endif + +struct lsc_line { + size_t name; + char *buf[LSC_MAXARG]; + size_t len; +}; + +struct lsc_parser { + int state; + + char intbuf[LSC_MAXBUF]; + size_t len; + + char *rptr; +}; + +enum lsc_r { + LSC_MORE, + LSC_OVERFLOW, + LSC_ARG_OVERFLOW, + LSC_INVALID_ARGUMENT, + LSC_COMPLETE +}; + +void lsc_reset(struct lsc_parser *, char *); +enum lsc_r lsc_read(struct lsc_parser *, + struct lsc_line *); +static void lsc_load_ptr(struct lsc_parser *in, char *p) { + in->rptr = p; +} + +#endif +#ifdef LSC_IMPLEMENTATION + +enum { LSC_READ, LSC_DISCARD }; + +static void reset_parse_state(struct lsc_parser *in) { + in->state = LSC_READ; + in->len = 0; +} + +void lsc_reset(struct lsc_parser *in, char *p) { + reset_parse_state(in); + in->rptr = p; +} + +static enum lsc_r lsc_parse(struct lsc_parser *in, + struct lsc_line *line) { + char *s = in->intbuf; + enum lsc_r r = LSC_ARG_OVERFLOW; + + line->name = (*s == ':'); + line->len = 0; + + while (line->len < LSC_MAXARG) { + line->buf[line->len++] = s; + for (; *s && *s != '\t'; s++); + + if (!*s) { + r = LSC_COMPLETE; + break; + } else { + *s = 0; + s++; + } + } + + reset_parse_state(in); + return r; +} + +enum lsc_r lsc_read(struct lsc_parser *psr, + struct lsc_line *line) { + char c; + + if (!psr || !psr->rptr || !line) + return LSC_INVALID_ARGUMENT; + + while ((c = *psr->rptr)) { + psr->rptr++; + if (psr->state == LSC_DISCARD) { + if (c == '\n') { + reset_parse_state(psr); + return LSC_OVERFLOW; + } + } else { + switch (c) { + case '\n': + psr->intbuf[psr->len] = 0; + return lsc_parse(psr, line); + default: + if (psr->len == LSC_MAXBUF) + psr->state = LSC_DISCARD; + psr->intbuf[psr->len++] = c; + } + } + } + + return LSC_MORE; +} +#endif diff --git a/software/src/main.c b/software/src/main.c index e38d2cf..f9f1478 100644 --- a/software/src/main.c +++ b/software/src/main.c @@ -5,23 +5,126 @@ #include #include "sock.h" +#include "buf.h" + +#define LSC_IMPLEMENTATION +#include "lsc.h" LOG_MODULE_REGISTER(main); #define PORT 6626 -enum fds { - CLIENT_FD, - SCANDATA_FD, - MAXFDS + +enum { + IDENT, + ADC, + DAC, + + CL_SETPT, + CL_P, + CL_I, + CL_ARM, + CL_ERR, + CL_Z, + CL_CYCLES, + CL_DELAY, + + RASTER_MAX_SAMPLES, + RASTER_MAX_LINES, + RASTER_SETTLE_TIME, + RASTER_DX, + RASTER_DY, + RASTER_USED_ADCS, + RASTER_ARM, + + ARGS_NUM }; +static int _strcmp(const void *p1, const void *p2) {return strcmp(p1,p2);} + +static int +client_exec(int sock, struct lsc_line *l) +{ + static char buf[4096]; +# define stringify(s) #s +# define mkid(s) [s] = stringify(s) + static const char *argnames[ARGS_NUM] = { + mkid(IDENT), + mkid(ADC), + mkid(DAC), + + mkid(CL_SETPT), + mkid(CL_P), + mkid(CL_I), + mkid(CL_ARM), + mkid(CL_ERR), + mkid(CL_Z), + mkid(CL_CYCLES), + mkid(CL_DELAY), + + mkid(RASTER_MAX_SAMPLES), + mkid(RASTER_MAX_LINES), + mkid(RASTER_SETTLE_TIME), + mkid(RASTER_DX), + mkid(RASTER_DY), + mkid(RASTER_USED_ADCS), + mkid(RASTER_ARM) + }; +# undef mkid +# undef stringify + + char **p = bsearch(l->buf[l->name], argnames, ARGS_NUM, + sizeof(argnames[0]), _strcmp); + if (!p) { + sock_name_printf(sock, l, buf, sizeof(buf), + "ERROR\tunknown command\n"); + return 0; + } + + switch (p - argnames) { + + } +} + +static void +client_parse(int cli) +{ + static char buf[LSC_MAXBUF]; + static struct bufptr bp = {buf, sizeof(buf)}; + static struct lsc_parser psr = {0}; + static bool first = true; + struct lsc_line l; + + if (first) { + lsc_reset(&psr, buf); + first = false; + } + + switch (lsc_read(&psr, &l)) { + case LSC_OVERFLOW: + LOG_ERR("client command overflow\n"); + break; + case LSC_OVERFLOW: + LOG_ERR("client command argument overflow\n"); + break; + case LSC_INVALID_ARGUMENT: + LOG_ERR("programmer misuse"); + break; + case LSC_COMPLETE: + // process + lsc_reset(&psr, buf); + break: + } +} + static void process_client(int cli) { + enum fds { + CLIENT_FD, + SCANDATA_FD, + MAXFDS + }; struct zsock_pollfd fds[MAXFDS] = {0}; - struct clireadbuf readbuf = {0}; - - client_buf_reset(&readbuf); fds[CLIENT_FD].fd = cli; fds[CLIENT_FD].events = ZSOCK_POLLIN; @@ -29,19 +132,9 @@ process_client(int cli) fds[SCANDATA_FD].fd = -1; while (zsock_poll(fds, MAXFDS, 0) >= 0) { - if (fds[CLIENT_FD].revents | POLLIN) { - if (!client_read_into_buf(cli, &readbuf)) { - INFO_WRN("client_read_into_buf: %d", errno); - goto cleanup; - } - - if (readbuf.st == MSG_READY) { - msg_parse_dispatch(cli, &readbuf); - client_buf_reset(&buf); - } - } + if (fds[CLIENT_FD].revents | POLLIN) + client_parse(cli); } -cleanup: } void diff --git a/software/src/sock.c b/software/src/sock.c index dcd8cf9..d2d86ba 100644 --- a/software/src/sock.c +++ b/software/src/sock.c @@ -3,6 +3,8 @@ #include #include #include +#include "sock.h" +#include "lsc.h" LOG_MODULE_REGISTER(sock); @@ -58,36 +60,50 @@ server_accept_client(int server) return client; } -bool -client_read_into_buf(int sock, struct clireadbuf *buf) +int +sock_vprintf(int sock, char *buf, int buflen, char *fmt, va_list va) { - if (buf->st == MSG_READY) { - LOG_WRN("%s called while MSG_READY: misuse", __func__); - return true; + int w = vsnprintk(buf, buflen, fmt, va); + if (w < 0) + return b; + else if (w <= buflen) + return w - buflen; + + ssize_t left = w; + char *p = buf; + while (left > 0) { + ssize_t i = zsock_send(sock, p, left, 0); + if (i < 0) + return 0; + p += i; + left -= i; } - if (!buf_read_sock(sock, &buf->b)) - return false; + return w; +} - if (buf->b.left == 0) switch (buf->st) { - case WAIT_ON_HEADER: { - uint16_t len; - memcpy(&len, buf->buf, sizeof(len)); - buf->b.left = ntohs(len); - buf->st = READING_CLIENT; - break; - } case READING_CLIENT: - buf->st = MSG_READY; - break; +int +sock_name_printf(int sock, struct lsc_line *l, char *buf, int buflen, char *fmt, ...) +{ + if (l->name) { + int r = sock_printf(sock, buf, buflen, "%s\t", l->buf[0]); + if (r < 0) + return r; } - return true; + va_list va; + va_start(va, fmt); + int r = sock_vprintf(sock, buf, buflen, fmt, va); + va_end(va); + return r; } -void -client_buf_reset(struct clireadbuf *buf) +int +sock_printf(int sock, char *buf, int buflen, char *fmt, ...) { - buf->st = WAIT_ON_HEADER; - buf->b.p = buf->buf; - buf->b.left = sizeof(uint16_t); + va_list va; + va_start(va, fmt); + int r = sock_vprintf(sock, buf, buflen, fmt, va); + va_end(va); + return r; } diff --git a/software/src/sock.h b/software/src/sock.h index d3147b7..052e211 100644 --- a/software/src/sock.h +++ b/software/src/sock.h @@ -1,19 +1,3 @@ #pragma once -#include "buf.h" int server_init_sock(int port); int server_accept_client(int server); - -#define CLIREADBUF_SIZ 1024 -enum clireadbuf_state { - WAIT_ON_HEADER, - READING_CLIENT, - MSG_READY -}; -struct clireadbuf { - struct bufptr b; - enum clireadbuf_state st; - char buf[CLIREADBUF_SIZ]; -}; - -bool client_read_into_buf(int sock, struct clireadbuf *buf); -void client_buf_reset(struct clireadbuf *buf);