~jb55/chibipub

88b7b87269ddeb58c0fe2dfe1e546c30a330f69d — William Casarin a month ago 7e273f2
refactor errors
10 files changed, 128 insertions(+), 89 deletions(-)

M Makefile
A src/errors.h
M src/http.c
M src/http.h
M src/inbox.c
M src/inbox.h
M src/json.c
M src/json.h
M src/util.h
M src/wolfsocks.c
M Makefile => Makefile +2 -0
@@ 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 $@


A src/errors.h => src/errors.h +30 -0
@@ 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 */

M src/http.c => src/http.c +7 -0
@@ 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;

M src/http.h => src/http.h +3 -1
@@ 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);

M src/inbox.c => src/inbox.c +16 -7
@@ 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;
			}
		}

M src/inbox.h => src/inbox.h +2 -1
@@ 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

M src/json.c => src/json.c +45 -60
@@ 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) {

M src/json.h => src/json.h +2 -0
@@ 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 {

M src/util.h => src/util.h +0 -2
@@ 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;


M src/wolfsocks.c => src/wolfsocks.c +21 -18
@@ 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);