chibipub

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 88b7b87269ddeb58c0fe2dfe1e546c30a330f69d
parent 7e273f2e59a9dc7cc7408264e80f19f6c719c6ed
Author: William Casarin <jb55@jb55.com>
Date:   Tue, 15 Dec 2020 10:47:07 -0800

refactor errors

Diffstat:
MMakefile | 2++
Asrc/errors.h | 30++++++++++++++++++++++++++++++
Msrc/http.c | 7+++++++
Msrc/http.h | 4+++-
Msrc/inbox.c | 23++++++++++++++++-------
Msrc/inbox.h | 3++-
Msrc/json.c | 105++++++++++++++++++++++++++++++++++---------------------------------------------
Msrc/json.h | 2++
Msrc/util.h | 2--
Msrc/wolfsocks.c | 39+++++++++++++++++++++------------------
10 files changed, 128 insertions(+), 89 deletions(-)

diff --git a/Makefile b/Makefile @@ -5,6 +5,8 @@ OBJS = src/http.o src/base64.o src/inbox.o src/json.o HEADERS = $(wildcard src/*.h) +all: wolfsocks + wolfsocks: src/wolfsocks.c $(OBJS) $(HEADERS) $(CC) $(CFLAGS) $< $(OBJS) $(LDFLAGS) -o $@ diff --git a/src/errors.h b/src/errors.h @@ -0,0 +1,30 @@ + +#ifndef WOLFSOCKS_ERRORS +#define WOLFSOCKS_ERRORS + +#include <stdarg.h> + +#define note_error(p, msg, ...) note_error_(p, "%s: " msg "\n", __FUNCTION__, ##__VA_ARGS__); + +struct errors { + int record; +}; + +static inline void init_errors(struct errors *errs) +{ + errs->record = 1; +} + +static inline void note_error_(struct errors *errs, const char *fmt, ...) +{ + if (!errs->record) + return; + + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + + +#endif /* WOLFSOCKS_ERRORS */ diff --git a/src/http.c b/src/http.c @@ -5,6 +5,13 @@ #include <stdio.h> #include <assert.h> + +void init_http_req(struct http_req *req) +{ + memset(req, 0, sizeof(*req)); + init_errors(&req->errs); +} + static int parse_segment_with(struct parser *p, char **seg, char delim) { char c; diff --git a/src/http.h b/src/http.h @@ -2,6 +2,7 @@ #define WOLFSOCKS_HTTP #include "cursor.h" +#include "errors.h" struct parser { struct cursor cur; @@ -19,9 +20,10 @@ struct http_req { char *path; char *ver; struct http_header *headers; + struct errors errs; }; - +void init_http_req(struct http_req *req); int get_header(struct http_header *header, const char *match, const char **result); int parse_http_request(struct http_req *req, struct parser *p); void print_http_request(struct http_req *req); diff --git a/src/inbox.c b/src/inbox.c @@ -33,11 +33,11 @@ static int parse_until(struct cursor *cur, struct cursor *arena, char match, return 0; } -static int parse_kv(struct cursor *cur, struct cursor *arena, - const char **key, const char **val) +static int parse_kv(struct errors *errs, struct cursor *cur, + struct cursor *arena, const char **key, const char **val) { if (!parse_until(cur, arena, '=', key)) { - note_error(cur, "= not found"); + note_error(errs, "= not found"); return 0; } @@ -49,16 +49,25 @@ static int parse_kv(struct cursor *cur, struct cursor *arena, return 1; } -int parse_signature_header(struct cursor *arena, const char *value, struct sig_header *out) +int parse_signature_header(struct errors *errs, struct cursor *arena, + const char *value, struct sig_header *out) { const char *key; const char *val; struct cursor cur; size_t out_len; make_cursor((unsigned char*)value, (unsigned char*)value + strlen(value), &cur); + memset(out, 0, sizeof(*out)); while (1) { - if (!parse_kv(&cur, arena, &key, &val)) { + if (out->key_id && out->headers && out->signature) + break; + + if (!parse_kv(errs, &cur, arena, &key, &val)) { + note_error(errs, "keyid:%s headers:%s sig:%s", + out->key_id, + out->headers, + out->signature); break; } @@ -72,7 +81,7 @@ int parse_signature_header(struct cursor *arena, const char *value, struct sig_h if (!base64_decode((const unsigned char*)val, strlen(val), arena->p, arena->end - arena->p, &out_len)) { - note_error(arena, "base64 decode signature"); + note_error(errs, "base64 decode signature"); return 0; } @@ -80,7 +89,7 @@ int parse_signature_header(struct cursor *arena, const char *value, struct sig_h arena->p += out_len; if (!push_byte(arena, 0)) { - note_error(arena, "oom"); + note_error(errs, "oom"); return 0; } } diff --git a/src/inbox.h b/src/inbox.h @@ -2,6 +2,7 @@ #define WOLFSOCKS_INBOX #include "cursor.h" +#include "errors.h" struct sig_header { const char *key_id; @@ -11,7 +12,7 @@ struct sig_header { }; -int parse_signature_header(struct cursor *arena, const char *value, struct sig_header *out); +int parse_signature_header(struct errors *errs, struct cursor *arena, const char *value, struct sig_header *out); int verify_signature_header(struct sig_header *sig); #endif diff --git a/src/json.c b/src/json.c @@ -5,27 +5,12 @@ #include <ctype.h> -#define note_error(p, msg, ...) note_error_(p, "%s: " msg "\n", __FUNCTION__, ##__VA_ARGS__); - -struct errors { - int record_errors; -} - struct json_parser { struct cursor cur; struct cursor ubjson; - struct errors errors; + struct errors errs; }; -static void note_error_(struct json_parser *p, const char *fmt, ...) -{ - if (!p->errors.record_errors) - return; - - - int record_errors; -} - static void consume_whitespace(struct cursor *cur) { for (; cur->p < cur->end; cur->p++) { @@ -153,7 +138,7 @@ static int push_ubjson_str(struct cursor *ubjson, unsigned char *text, static int parse_escape(struct json_parser *p) { (void)p; - note_error(p, "implement parse_escape"); + note_error(&p->errs, "implement parse_escape"); return 0; } @@ -168,13 +153,13 @@ static int parse_string(struct json_parser *p) start = p->cur.p; if (!parse_char(&p->cur, &c, '"')) { - note_error(p, "expected '\"', got '%c'", c); + note_error(&p->errs, "expected '\"', got '%c'", c); return 0; } while (1) { if (!parse_utf8_char(&p->cur, &chr)) { - note_error(p, "invalid utf-8 codepoint"); + note_error(&p->errs, "invalid utf-8 codepoint"); break; } @@ -184,7 +169,7 @@ static int parse_string(struct json_parser *p) } if (chr == '\\' && !parse_escape(p)) { - note_error(p, "invalid escape char '%c'", c); + note_error(&p->errs, "invalid escape char '%c'", c); break; } } @@ -196,7 +181,7 @@ static int parse_string(struct json_parser *p) static int parse_number(struct json_parser *p) { (void)p; - note_error(p, "not implemented"); + note_error(&p->errs, "not implemented"); return 0; } @@ -208,14 +193,14 @@ static int parse_kv(struct json_parser *p) c = 0; if (!parse_string(p)) { - note_error(p, "key"); + note_error(&p->errs, "key"); return 0; } consume_whitespace(&p->cur); if (!parse_char(&p->cur, &c, ':')) { - note_error(p, "expected ':', got %c", c); + note_error(&p->errs, "expected ':', got %c", c); return 0; } @@ -235,7 +220,7 @@ static int parse_object(struct json_parser *p) c = 0; if (!parse_char(&p->cur, &c, '{')) { - note_error(p, "expected '{' got '%c'", c); + note_error(&p->errs, "expected '{' got '%c'", c); return 0; } @@ -255,7 +240,7 @@ static int parse_object(struct json_parser *p) consume_whitespace(&p->cur); if (!peek_char(&p->cur, &c)) { - note_error(p, "oob"); + note_error(&p->errs, "oob"); return 0; } @@ -265,17 +250,17 @@ static int parse_object(struct json_parser *p) } if (c != '"') { - note_error(p, "expected '\"' or '}', got '%c'", c); + note_error(&p->errs, "expected '\"' or '}', got '%c'", c); return 0; } if (!parse_kv(p)) { - note_error(p, "expected key value pair"); + note_error(&p->errs, "expected key value pair"); return 0; } if (!peek_char(&p->cur, &c)) { - note_error(p, "oob"); + note_error(&p->errs, "oob"); return 0; } @@ -289,18 +274,18 @@ static int parse_object(struct json_parser *p) return finalize_object(p, len); } - note_error(p, "expected ',' or '}', got '%c'", c); + note_error(&p->errs, "expected ',' or '}', got '%c'", c); return 0; } - note_error(p, "impossibru"); + note_error(&p->errs, "impossibru"); return 0; } static int parse_array(struct json_parser *p) { (void)p; - note_error(p, "implement parse_array"); + note_error(&p->errs, "implement parse_array"); return 0; } @@ -327,7 +312,7 @@ static int parse_null(struct json_parser *p) { if (!parse_str(&p->cur, "null")) { fprintf(stderr, "got %.*s instead of null\n", 4, p->cur.p); - note_error(p, "not null"); + note_error(&p->errs, "not null"); return 0; } @@ -341,7 +326,7 @@ static int parse_value(struct json_parser *p) consume_whitespace(&p->cur); - p->record_errors = 0; + p->errs.record = 0; res = parse_string(p) || parse_object(p) || @@ -350,10 +335,10 @@ static int parse_value(struct json_parser *p) parse_bool(p) || parse_null(p); - p->record_errors = 1; + p->errs.record = 1; if (!res) { - note_error(p, "couldn't parse json value"); + note_error(&p->errs, "couldn't parse json value"); return 0; } @@ -369,7 +354,7 @@ static int parse_array_or_object(struct json_parser *p) consume_whitespace(&p->cur); if (!peek_char(&p->cur, &c)) { - note_error(p, "oob"); + note_error(&p->errs, "oob"); return 0; } @@ -380,7 +365,7 @@ static int parse_array_or_object(struct json_parser *p) if (c == '[') return parse_array(p); - note_error(p, "expected '{' or '[', got '%c'", c); + note_error(&p->errs, "expected '{' or '[', got '%c'", c); return 0; } @@ -393,29 +378,29 @@ static int parse_ubjson_size(struct ubjson *ubjson, unsigned int *len) start = ubjson->cur.p; if (!pull_byte(&ubjson->cur, &byte)) { - note_error(ubjson->errors, "oob"); + note_error(&ubjson->errs, "oob"); } else if (byte == 'U' || byte == 'i') { if (!pull_byte(&ubjson->cur, &byte)) { - note_error(ubjson->errors, "pull byte after u8 int"); + note_error(&ubjson->errs, "pull byte after u8 int"); } else { *len = byte; return 1; } } else if (byte == 'I') { if (!pull_data(&ubjson->cur, (unsigned char*)&u16, sizeof(u16))) { - note_error(ubjson->errors, "pull byte after u16 int"); + note_error(&ubjson->errs, "pull byte after u16 int"); } else { *len = u16; return 1; } } else if (byte == 'l' || byte == 'L') { if (!pull_int(&ubjson->cur, (int*)len)) { - note_error(ubjson->errors, "pull byte after u16 int"); + note_error(&ubjson->errs, "pull byte after u16 int"); } else { return 1; } } else { - note_error(ubjson->errors, "unhandled number tag '%c'", byte); + note_error(&ubjson->errs, "unhandled number tag '%c'", byte); } ubjson->cur.p = start; @@ -428,12 +413,12 @@ static int parse_ubjson_string(struct ubjson *ubjson, struct json *val) byte = 0; if (!parse_char(&ubjson->cur, &byte, 'S')) { - note_error(ubjson->errors, "expected S tag, got '%c'", byte); + note_error(&ubjson->errs, "expected S tag, got '%c'", byte); return 0; } if (!parse_ubjson_size(ubjson, &val->len)) { - note_error(ubjson->errors, "size"); + note_error(&ubjson->errs, "size"); return 0; } @@ -458,23 +443,23 @@ static int consume_ubjson_value(struct ubjson *u) c = 0; if (!pull_byte(&u->cur, &c)) { - note_error(u->errors, "oob"); + note_error(&u->errs, "oob"); return 0; } if (!valid_ubjson_tag(c)) { - note_error(u->errors, "invalid value tag '%c'", c); + note_error(&u->errs, "invalid value tag '%c'", c); return 0; } if (c == 'Z') { len = 0; } else if (!parse_ubjson_size(u, &len)) { - note_error(u->errors, "value size for tag '%c'", c); + note_error(&u->errs, "value size for tag '%c'", c); return 0; } if (u->cur.p + len > u->cur.end) { - note_error(u->errors, "value size oob"); + note_error(&u->errs, "value size oob"); return 0; } @@ -496,21 +481,21 @@ static int parse_ubjson_object(struct ubjson *ubjson, struct json *val) copy_ubjson(ubjson, &val->container); if (!parse_char(&ubjson->cur, &c, '{')) { - note_error(ubjson->errors, "expected '{' tag, got '%c'", c); + note_error(&ubjson->errs, "expected '{' tag, got '%c'", c); return 0; } if (!parse_ubjson_size(ubjson, &val->len)) { /* reset */ ubjson->cur.p = val->container.cur.p; - note_error(ubjson->errors, "object len"); + note_error(&ubjson->errs, "object len"); return 0; } if (ubjson->cur.p + val->len >= ubjson->data_end) { /* reset */ ubjson->cur.p = val->container.cur.p; - note_error(ubjson->errors, "invalid len %d", val->len); + note_error(&ubjson->errs, "invalid len %d", val->len); return 0; } @@ -523,7 +508,7 @@ int parse_ubjson_value(struct ubjson *ubjson, struct json *val) { char tag; if (!peek_char(&ubjson->cur, &tag)) { - note_error(ubjson->errors, "peek value tag oob"); + note_error(&ubjson->errs, "peek value tag oob"); return 0; } @@ -537,7 +522,7 @@ int parse_ubjson_value(struct ubjson *ubjson, struct json *val) return parse_ubjson_object(ubjson, val); } - note_error(ubjson->errors, "unhandled type '%c'", tag); + note_error(&ubjson->errs, "unhandled type '%c'", tag); return 0; } @@ -548,18 +533,18 @@ static int ubjson_obj_lookup(struct ubjson *ubjson, const char *path, struct jso byte = 0; if (!parse_char(&ubjson->cur, &byte, '{')) { - note_error(ubjson->errors, "no object tag, got '%c'", byte); + note_error(&ubjson->errs, "no object tag, got '%c'", byte); return 0; } if (!parse_ubjson_size(ubjson, &len)) { - note_error(ubjson->errors, "object size"); + note_error(&ubjson->errs, "object size"); return 0; } while (1) { if (!peek_char(&ubjson->cur, &byte)) { - note_error(ubjson->errors, "oob"); + note_error(&ubjson->errs, "oob"); break; } @@ -568,7 +553,7 @@ static int ubjson_obj_lookup(struct ubjson *ubjson, const char *path, struct jso } if (!parse_ubjson_string(ubjson, val)) { - note_error(ubjson->errors, "string"); + note_error(&ubjson->errs, "string"); break; } @@ -578,7 +563,7 @@ static int ubjson_obj_lookup(struct ubjson *ubjson, const char *path, struct jso memcmp(path, val->string, val->len)) { /* skip over value */ if (!consume_ubjson_value(ubjson)) { - note_error(p, "skip value"); + note_error(&ubjson->errs, "skip value"); return 0; } continue; @@ -605,13 +590,13 @@ int ubjson_lookup(struct ubjson *ubjson, const char **path, int path_len, struct seg = path[i]; if (!ubjson_obj_lookup(next, seg, val)) { - note_error(ubjson->errors, "lookup path segment: '%s'", seg); + note_error(&ubjson->errs, "lookup path segment: '%s'", seg); return 0; } /* not at the last segment and don't have an object or array */ if (i != path_len-1 && val->type != JSON_OBJECT) { - note_error(ubjson->errors, + note_error(&ubjson->errs, "segment '%s' not an object, got '%c'", seg, byte); return 0; } else if (val->type == JSON_OBJECT) { diff --git a/src/json.h b/src/json.h @@ -3,11 +3,13 @@ #define WOLFSOCKS_JSON #include "cursor.h" +#include "errors.h" #include <stddef.h> struct ubjson { struct cursor cur; unsigned char *data_end; + struct errors errs; }; enum json_value_type { diff --git a/src/util.h b/src/util.h @@ -5,8 +5,6 @@ #include <ctype.h> #include <string.h> -#define note_error(a, msg) fprintf(stderr, "%s: %s\n", __FUNCTION__, msg) - static inline int stricmp(const char *a, const char *b) { int len, i; diff --git a/src/wolfsocks.c b/src/wolfsocks.c @@ -18,8 +18,6 @@ #define BUF_SIZE 4096 #define ARENA_SIZE 134217728 /* 128 MB virtual mem arena */ -#define note_error(a, msg) fprintf(stderr, "%s: %s\n", __FUNCTION__, msg) - static void error(char *msg) { perror(msg); @@ -29,29 +27,34 @@ static void error(char *msg) static int handle_request(struct http_req *req, struct cursor *arena) { struct sig_header sig; + int inbox_req; const char *signature; memset(&sig, 0, sizeof(sig)); - if (!strcmp(req->method, "POST") && + inbox_req = !strcmp(req->method, "POST") && (!strcmp(req->path, "/inbox") || - !strcmp(req->path, "/inbox/"))) { + !strcmp(req->path, "/inbox/")); - if (!get_header(req->headers, "signature", &signature)) { - note_error(req, "signature"); - return 0; - } + if (!inbox_req) { + note_error(&req->errs, "404"); + return 0; + } + + if (!get_header(req->headers, "signature", &signature)) { + note_error(&req->errs, "signature"); + return 0; + } - printf("signature: %s\n", signature); + printf("signature: %s\n", signature); - if (!parse_signature_header(arena, signature, &sig)) { - note_error(req, "parse signature header"); - return 0; - } + if (!parse_signature_header(&req->errs, arena, signature, &sig)) { + note_error(&req->errs, "parse signature header"); + return 0; + } - if (!verify_signature_header(&sig)) { - note_error(req, "verify"); - return 0; - } + if (!verify_signature_header(&sig)) { + note_error(&req->errs, "verify"); + return 0; } return 1; @@ -105,7 +108,7 @@ void run_http_server() client_len = sizeof(client_addr); while (1) { - memset(&req, 0, sizeof(req)); + init_http_req(&req); make_cursor(buffer, buffer + BUF_SIZE, &parser.cur); make_cursor(arena, arena + ARENA_SIZE, &parser.arena);