summaryrefslogtreecommitdiff
path: root/src/server.c
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2026-07-20 20:59:27 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2026-07-20 21:27:48 +0300
commitdd6314503f02dde966adce06e27105f547300077 (patch)
tree6aeba0c967aed6cda50de7d88d5ae75effd1f657 /src/server.c
parentbe647e6f781421600bfb172a7b7ad73a106398a4 (diff)
downloadlark-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.c113
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;