diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2026-07-20 20:59:27 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2026-07-20 21:27:48 +0300 |
| commit | dd6314503f02dde966adce06e27105f547300077 (patch) | |
| tree | 6aeba0c967aed6cda50de7d88d5ae75effd1f657 /src/server.c | |
| parent | be647e6f781421600bfb172a7b7ad73a106398a4 (diff) | |
| download | lark-dd6314503f02dde966adce06e27105f547300077.tar.gz lark-dd6314503f02dde966adce06e27105f547300077.zip | |
better command format
+ Each command start with <STRING> <NUMBER> with possible leading/trailing
whitespace. <STRING> specifies the command name, <NUMBER> the size of
the command header, which uses a key-value format, kind of like ini.
Key-value parser is not yet implemented, but should be fairly simple to do.
+ The content of the message should be lark-encoded, essentially just that
each '=' in the text is replaced by '>=' (or something) so that the stream
of headers + message becomes self-synchronizing (kind of at least?)
Diffstat (limited to 'src/server.c')
| -rw-r--r-- | src/server.c | 113 |
1 files changed, 95 insertions, 18 deletions
diff --git a/src/server.c b/src/server.c index f643386..187e600 100644 --- a/src/server.c +++ b/src/server.c @@ -3,6 +3,7 @@ #include <stdio.h> #include <errno.h> #include <fcntl.h> +#include <ctype.h> #include <unistd.h> #include <stdlib.h> #include <string.h> @@ -17,6 +18,7 @@ enum que_op { LARK_KILL, LARK_NEW, + LARK_NEXT, LARK_POLL, }; @@ -50,6 +52,7 @@ struct server_conn { socklen_t addrlen; struct strbuf strbuf; + size_t headerlen; enum server_cmd cmd; union { @@ -150,11 +153,12 @@ static int new_connection(struct server_ctx *ctx, int new_conn_fd) } struct server_conn conn = { - .fd = fd, - .addr = addr, - .addrlen = addrlen, - .cmd = META_PARSE_CMD, - .strbuf = strbuf_create(0) + .fd = fd, + .addr = addr, + .addrlen = addrlen, + .cmd = META_PARSE_CMD, + .strbuf = strbuf_create(0), + .headerlen = 0 }; memset(&conn.u, 0, sizeof(conn.u)); @@ -216,7 +220,7 @@ static ssize_t reread_cmd(struct server_conn *conn, size_t max) return -1; if (strbuf->buf[n + i] == '\n') - return r; + return n + i + 1; } /* no command as of yet, but try again later */ @@ -241,6 +245,79 @@ static void set_timeout(struct server_ctx *ctx, int timeout) ctx->timeout = timeout; } +/* return 0 on success, !0 on failure */ +static int parse_cmd(char *buf, char **cmd, size_t *len) +{ + char *keystart = buf; + while (*keystart && isblank(*keystart)) + keystart++; + + /* empty string */ + if (!*keystart) + return -1; + + char *keyend = keystart + 1; + while (*keyend && isalnum(*keyend)) + keyend++; + + /* nothing after key */ + if (!*keyend) + return -1; + + /* split off cmd from rest */ + *keyend = '\0'; + if (cmd) + *cmd = keystart; + + if (!len) + return 0; + + char *lenstart = keyend + 1; + while (*lenstart && isblank(*lenstart)) + lenstart++; + + /* space after key but no len value */ + if (!*lenstart) + return -1; + + char *lenend = lenstart + 1; + while (*lenend && isdigit(*lenend)) + lenend++; + + if (!*lenend) { + /* end of string, nothing after digits but there doesn't need to be */ + char *check = NULL; + *len = strtoull(lenstart, &check, 10); + + /* sanity check of sorts, if they're equal we return 0 (which we + * want), otherwise -1 */ + return check == lenend ? 0 : -1; + } + + /* something following length, trailing spaces are allowed but nothing + * else */ + char *linend = lenend + 1; + while (*linend && isblank(*linend)) + linend++; + + /* there was other stuff besides spaces, error */ + if (*linend) + return -1; + + *lenend = '\0'; + + char *check = NULL; + *len = strtoull(lenstart, &check, 10); + return check == lenend ? 0 : -1; +} + +static void strbuf_shift(struct strbuf *strbuf, size_t i) +{ + assert(i <= strbuf->n); + memmove(strbuf->buf, strbuf->buf + i, strbuf->n - i); + strbuf_shrink(strbuf, strbuf->n - i); +} + static enum que_op meta_parse_cmd(struct server_ctx *ctx, struct server_conn *conn) { int r = reread_cmd(conn, MAX_CMD_LEN); @@ -256,14 +333,16 @@ static enum que_op meta_parse_cmd(struct server_ctx *ctx, struct server_conn *co return LARK_POLL; } - /* r > 0, we have a command and its length */ + /* r > 0, we (should) have a command and its headerlen */ + char *cmd = NULL; + conn->strbuf.buf[r - 1] = '\0'; + if (parse_cmd(conn->strbuf.buf, &cmd, &conn->headerlen)) + return LARK_KILL; + if (strneq(conn->strbuf.buf, "SYNC", 4)) { syslog(LOG_DEBUG, "parsed SYNC command start\n"); conn->cmd = SYNC_CMD; - - /* we want to immediately run the next command since we know - * that we've placed it into the strbuf */ - set_timeout(ctx, 0); + strbuf_shift(&conn->strbuf, r); return LARK_NEW; } @@ -271,13 +350,6 @@ static enum que_op meta_parse_cmd(struct server_ctx *ctx, struct server_conn *co return LARK_KILL; } -static void strbuf_shift(struct strbuf *strbuf, size_t i) -{ - assert(i <= strbuf->n); - memmove(strbuf->buf, strbuf->buf + i, strbuf->n - i); - strbuf_shrink(strbuf, strbuf->n - i); -} - static int sync_parse(struct sync_cmd *cmd, struct strbuf *strbuf) { char *buf = strbuf->buf; @@ -519,7 +591,12 @@ static int event_loop(int tcp_sock) conn_idx--; break; + case LARK_NEXT: + set_timeout(&ctx, 0); + break; + case LARK_NEW: + set_timeout(&ctx, 0); /* reset union for next command */ memset(&conn->u, 0, sizeof(conn->u)); break; |
