chibipub

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

commit 9a39254b3de99148c6509e7c4d52f769a303e255
parent 3dd0ec81b9f72f86005f543ac8fe577bb3ad09a0
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 17 Jan 2021 11:26:08 -0800

remove remaining wolfsocks references

Diffstat:
MMakefile | 6+++---
Mdefault.nix | 2+-
Asrc/chibipub.c | 493+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/wolfsocks.c | 493-------------------------------------------------------------------------------
4 files changed, 497 insertions(+), 497 deletions(-)

diff --git a/Makefile b/Makefile @@ -23,7 +23,7 @@ BLAKE3_OBJS = deps/blake3/blake3.o \ HEADERS = $(wildcard src/*.h) deps/sha256/sha256.h -all: wolfsocks +all: chibipub %.o: %.c @echo "cc $<" @@ -44,7 +44,7 @@ deps/blake3/blake3.a: $(BLAKE3_OBJS) corpus/math.json: curl --compressed -sL 'https://jb55.com/s/5aaaae6d64be61fd.json' > $@ -wolfsocks: src/wolfsocks.c $(OBJS) $(HEADERS) +chibipub: src/chibipub.c $(OBJS) $(HEADERS) @echo "ld $@" @$(CC) $(CFLAGS) $< $(OBJS) $(LDFLAGS) -o $@ @@ -55,7 +55,7 @@ check: src/test_json ./src/test_json clean: fake - rm -f $(OBJS) $(BLAKE3_OBJS) deps/blake3/blake3.a wolfsocks src/test_json + rm -f $(OBJS) $(BLAKE3_OBJS) deps/blake3/blake3.a chibipub src/test_json tags: fake ctags src/*.c deps/sha256/sha256.c $(HEADERS) diff --git a/default.nix b/default.nix @@ -1,7 +1,7 @@ { pkgs ? import <nixpkgs> {} }: with pkgs; stdenv.mkDerivation { - name = "wolfsocks"; + name = "chibipub"; nativeBuildInputs = [ gdb pkg-config ngrok clib ]; buildInputs = [ openssl ]; } diff --git a/src/chibipub.c b/src/chibipub.c @@ -0,0 +1,493 @@ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <ctype.h> +#include <assert.h> +#include <base64.h> + +#include "http.h" +#include "ap_json.h" +#include "inbox.h" +#include "json.h" +#include "sigcheck.h" + +#define BUF_SIZE 1048576 +#define ARENA_SIZE 134217728 /* 128 MB virtual mem arena */ +#define streq(a,b) (!strcmp(a,b)) +#define patheq(req, x) (streq(x, req->path) || streq(x "/", req->path)) + +struct webfinger { + const char *acct; + const char *alias; + const char *profile_page; + const char *self; +}; + +static void error(char *msg) +{ + perror(msg); + exit(1); +} + +static inline const char *get_hostname() +{ + return getenv("CHIBIPUB_HOST"); +} + + +#define SCHEMA "https://" + +static void init_test_webfinger(struct webfinger *finger) +{ + static unsigned char buf[512]; + struct cursor c; + make_cursor(buf, buf+sizeof(buf), &c); + + const char *host = get_hostname(); + assert(host); + + finger->acct = (char*)c.p; + + assert( + push_str(&c, "jb55@") && push_c_str(&c, host) + ); + + finger->alias = (char*)c.p; + + assert( + push_str(&c, SCHEMA) && push_str(&c, host) && + push_c_str(&c, "/alias") + ); + + finger->profile_page = (char*)c.p; + + assert( + push_str(&c, SCHEMA) && push_str(&c, host) && + push_c_str(&c, "/profile") + ); + + finger->self = (char*)c.p; + + assert( + push_str(&c, SCHEMA) && push_str(&c, host) && + push_c_str(&c, "/") + ); +} + +static inline void write_status(struct http_req *req, const char *status) +{ + fprintf(req->client.socket_file, "HTTP/1.1 %s\r\n", status); +} + +static inline void write_resp_header(struct http_req *req, const char *status) +{ + write_status(req, status); + fprintf(req->client.socket_file, "Connection: close\r\n"); + fprintf(req->client.socket_file, "\r\n"); +} + +static int handle_webfinger(struct http_req *req) +{ + struct webfinger finger; + + init_test_webfinger(&finger); + + write_resp_header(req, "200 OK"); + + fprintf(req->client.socket_file, + "{\"subject\": \"acct:%s\"," + " \"aliases\": [\"%s\"]," + " \"links\": [{" + " \"rel\": \"http://webfinger.net/rel/profile-page\"," + " \"type\": \"text/html\"," + " \"href\": \"%s\"" + " },{" + " \"rel\":\"self\"," + " \"type\": \"application/activity+json\"," + " \"href\": \"%s\"" + " }]}\r\n", + finger.acct, + finger.alias, + finger.profile_page, + finger.self); + + return 1; +} + + +static inline int starts_with(const char *str, const char *prefix) +{ + unsigned int prefix_size; + prefix_size = strlen(prefix); + + if (prefix_size > strlen(str)) { + return 0; + } + + return !memcmp(str, prefix, prefix_size); +} + +static void http_log(struct http_req *req) +{ + printf("%s - \"%s %s %s\"\n", + req->client.addr_str, + req->method, + req->path, + req->ver); +} + +static int handle_inbox_request(struct http_req *req, struct cursor *arena) +{ + const char *signature; + unsigned char *start; + FILE *out; + int len; + struct sig_header sig; + struct json_parser pull; + struct json_pusher push; + struct ap_json apjson; + + struct json_handlers compact; + struct json_handlers ap_handler; + + make_compact_handlers(&compact, &push); + make_ap_json_pusher(&ap_handler, &apjson); + init_ap_json(&apjson, &compact); + + memset(&sig, 0, sizeof(sig)); + + if (!get_header(req->headers, "signature", &signature)) { + note_error(&req->errs, "signature"); + return 0; + } + + printf("signature: %s\n", signature); + + if (!parse_signature_header(&req->errs, arena, signature, strlen(signature), &sig)) { + note_error(&req->errs, "parse signature header"); + return 0; + } + + apjson.sig = &sig; + apjson.req = req; + + // TODO: defer this check + if (!verify_signature_header(&sig)) { + note_error(&req->errs, "verify"); + return 0; + } + + start = arena->p; + init_json_pusher_with(&push, arena); + + init_json_parser(&pull, req->body, req->body_len, &ap_handler); + if (!parse_json(&pull)) { + note_error(&req->errs, "json parse failed"); + return 0; + } + + if (!(out = fopen("activities.json", "a"))) { + note_error(&req->errs, "could not open activities.json"); + return 0; + } + + len = push.cur.p - start; + + // 128 KB + if (len >= 131072) { + note_error(&req->errs, "ActivityPub message too big"); + return 0; + } + + fwrite(start, len, 1, out); + fwrite("\n", 1, 1, out); + fclose(out); + + write_resp_header(req, "200 OK"); + return 1; +} + +static inline int is_get(struct http_req *req) +{ + return streq(req->method, "GET"); +} + +static inline int is_post(struct http_req *req) +{ + return streq(req->method, "POST"); +} + + +static inline int is_accept_activity(struct http_req *req) +{ + const char *accept; + + if (!get_header(req->headers, "accept", &accept)) { + note_error(&req->errs, "accept"); + return 0; + } + + if (!strstr(accept, "application/activity+json")) { + note_error(&req->errs, "not accept: '%s'", accept); + return 0; + } + + return 1; +} + +struct profile +{ + const char *id; + const char *type; + const char *username; + const char *name; + const char *summary; + const char *url; + int manually_approves_followers; + const char *image_mime_type; + const char *image_url; + const char *key_id; + const char *pubkey_pem; +}; + +static void test_profile(struct profile *p) +{ + static unsigned char buf[128]; + struct cursor c; + make_cursor(buf, buf + sizeof(buf), &c); + + const char *host = get_hostname(); + assert(host); + + p->id = (char*)c.p; + assert( + push_str(&c, SCHEMA) && push_str(&c, host) && push_c_str(&c, "/") + ); + + p->type = "Person"; + p->username = "jb55"; + p->name = "William Casarin"; + p->summary = "chibipub prototype"; + p->url = p->id; + p->manually_approves_followers = 0; + p->image_mime_type = "image/jpeg"; + p->image_url = "https://jb55.com/s/blue-me.jpg"; + p->key_id = "main-key"; + p->pubkey_pem = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnJOPxwmRGBBQYm7YgHRubTaYaKbMoEQiui+37nizXA73CRNeKblSXIaJnfOKfz/ttRG0GH43GzHTpghUDuZX+QBpyOk8UMmCW5gM0Y5c3IOv0zLezqLXrVEM8UXMUHE3hxf61r1NKl1+IG9MwhtHayx0Kaz6vT/V8nkotCSlb91lMT8X28bButwN86RCclZncecQXuVvgXnFeZCeBLM+qV2tBPnn14Ws+AqVvVnBW8xXwVfSPFHQchSLAusdWI7Kw/oWN/on2CqfRASoaVASqKG+uPuJ+1f92iH0ZY1wLB2/ITl7HKTiIMKNikXTWcUudkMlKxc5Iqb7HMHuaPZ9IQIDAQAB-----END PUBLIC KEY-----"; +} + +static int handle_self(struct http_req *req) +{ + struct profile profile; + test_profile(&profile); + + write_resp_header(req, "200 OK"); + + fprintf(req->client.socket_file, + "{" + "\"@context\": [" + "\"https://www.w3.org/ns/activitystreams\"" + "]," + "\"inbox\": \"%sinbox\"," + "\"id\": \"%s\"," + "\"type\": \"%s\"," + "\"preferredUsername\": \"%s\"," + "\"name\": \"%s\"," + "\"summary\": \"%s\"," + "\"url\": \"%s\"," + "\"manuallyApprovesFollowers\": %s," + "\"icon\": {" + "\"type\": \"Image\"," + "\"mediaType\": \"%s\"," + "\"url\": \"%s\"" + "}," + "\"publicKey\": {" + "\"id\": \"%s#%s\"," + "\"owner\": \"%s\"," + "\"publicKeyPem\": \"%s\"" + "}" + "}\n", + profile.id, + profile.id, + profile.type, + profile.username, + profile.name, + profile.summary, + profile.url, + profile.manually_approves_followers ? "true" : "false", + profile.image_mime_type, + profile.image_url, + profile.id, profile.key_id, + profile.id, + profile.pubkey_pem); + + return 1; +} + +static int handle_request(struct http_req *req, struct cursor *arena) +{ + http_log(req); + + if (starts_with(req->path, "/.well-known/webfinger?resource=acct:")) { + return handle_webfinger(req); + } else if (is_post(req) && patheq(req, "/inbox")) { + return handle_inbox_request(req, arena); + } else if (is_get(req) && + is_accept_activity(req) && + streq(req->path, "/")) { + return handle_self(req); + } + + return 0; +} + +static int http_accept_client(struct http_req *req, int parent) +{ + struct sockaddr_in *addr; + socklen_t client_len; + struct hostent *client_host; + + client_len = sizeof(addr); + + addr = &req->client.sockaddr; + + req->client.socket = + accept(parent, (struct sockaddr *) &req->client.sockaddr, + &client_len); + + if (req->client.socket < 0) { + note_error(&req->errs, "bad socket"); + return 0; + } + + req->client.socket_file = fdopen(req->client.socket, "wb"); + + client_host = gethostbyaddr((const char *)&addr->sin_addr.s_addr, + sizeof(addr->sin_addr.s_addr), AF_INET); + + if (!client_host) { + note_error(&req->errs, "gethostbyaddr"); + return 0; + } + + req->client.addr_str = inet_ntoa(addr->sin_addr); + + if (!req->client.addr_str) { + note_error(&req->errs, "inet_htoa"); + return 0; + } + + return 1; +} + +void run_http_server() +{ + static unsigned char buffer[BUF_SIZE]; + unsigned char *arena; + + ssize_t len, size; + + int parent; + struct sockaddr_in server_addr; + int optval; + + struct http_req req; + + struct parser parser; + + const int port = 5188; + arena = malloc(ARENA_SIZE); + assert(arena); + + if ((parent = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + error("socket"); + } + + optval = 1; + setsockopt(parent, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, + sizeof(optval)); + + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = htonl(INADDR_ANY); + server_addr.sin_port = htons(port); + + if (bind(parent, (struct sockaddr *)&server_addr, + sizeof(server_addr)) < 0) { + error("bind"); + } + + printf("listening for activities on 0.0.0.0:%d\n", port); + + if (listen(parent, 5) < 0) { + error("listen"); + } + + while (1) { + init_http_req(&req); + make_cursor(buffer, buffer + BUF_SIZE, &parser.cur); + make_cursor(arena, arena + ARENA_SIZE, &parser.arena); + + http_accept_client(&req, parent); + + for(size = 0;1;) { + len = read(req.client.socket, (void*)(buffer+size), BUF_SIZE-size); + size += len; + if (len == 0) { + break; + } + + if (len != (BUF_SIZE-size)) { + break; + } + } + + if (parse_http_request(&req, &parser, size)) { + handle_request(&req, &parser.arena); + } + + fclose(req.client.socket_file); + close(req.client.socket); + } + + free(arena); +} + +static void load_config() +{ + if (!get_hostname()) { + printf("CHIBIPUB_HOST env not set\n"); + exit(2); + } +} + +static int checksigs() +{ + struct sigcheck check; + check.activity_file = "activities.json"; + if (!sigcheck(&check)) { + printf("sigcheck failed\n"); + return 1; + } + printf("ok\n"); + return 0; +} + +int main(int argc, char *argv[]) +{ + if (argc >= 2 && !strcmp(argv[1], "checksigs")) { + return checksigs(); + } + + load_config(); + run_http_server(); + + return 0; +} diff --git a/src/wolfsocks.c b/src/wolfsocks.c @@ -1,493 +0,0 @@ - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <netdb.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <ctype.h> -#include <assert.h> -#include <base64.h> - -#include "http.h" -#include "ap_json.h" -#include "inbox.h" -#include "json.h" -#include "sigcheck.h" - -#define BUF_SIZE 1048576 -#define ARENA_SIZE 134217728 /* 128 MB virtual mem arena */ -#define streq(a,b) (!strcmp(a,b)) -#define patheq(req, x) (streq(x, req->path) || streq(x "/", req->path)) - -struct webfinger { - const char *acct; - const char *alias; - const char *profile_page; - const char *self; -}; - -static void error(char *msg) -{ - perror(msg); - exit(1); -} - -static inline const char *get_hostname() -{ - return getenv("CHIBIPUB_HOST"); -} - - -#define SCHEMA "https://" - -static void init_test_webfinger(struct webfinger *finger) -{ - static unsigned char buf[512]; - struct cursor c; - make_cursor(buf, buf+sizeof(buf), &c); - - const char *host = get_hostname(); - assert(host); - - finger->acct = (char*)c.p; - - assert( - push_str(&c, "jb55@") && push_c_str(&c, host) - ); - - finger->alias = (char*)c.p; - - assert( - push_str(&c, SCHEMA) && push_str(&c, host) && - push_c_str(&c, "/alias") - ); - - finger->profile_page = (char*)c.p; - - assert( - push_str(&c, SCHEMA) && push_str(&c, host) && - push_c_str(&c, "/profile") - ); - - finger->self = (char*)c.p; - - assert( - push_str(&c, SCHEMA) && push_str(&c, host) && - push_c_str(&c, "/") - ); -} - -static inline void write_status(struct http_req *req, const char *status) -{ - fprintf(req->client.socket_file, "HTTP/1.1 %s\r\n", status); -} - -static inline void write_resp_header(struct http_req *req, const char *status) -{ - write_status(req, status); - fprintf(req->client.socket_file, "Connection: close\r\n"); - fprintf(req->client.socket_file, "\r\n"); -} - -static int handle_webfinger(struct http_req *req) -{ - struct webfinger finger; - - init_test_webfinger(&finger); - - write_resp_header(req, "200 OK"); - - fprintf(req->client.socket_file, - "{\"subject\": \"acct:%s\"," - " \"aliases\": [\"%s\"]," - " \"links\": [{" - " \"rel\": \"http://webfinger.net/rel/profile-page\"," - " \"type\": \"text/html\"," - " \"href\": \"%s\"" - " },{" - " \"rel\":\"self\"," - " \"type\": \"application/activity+json\"," - " \"href\": \"%s\"" - " }]}\r\n", - finger.acct, - finger.alias, - finger.profile_page, - finger.self); - - return 1; -} - - -static inline int starts_with(const char *str, const char *prefix) -{ - unsigned int prefix_size; - prefix_size = strlen(prefix); - - if (prefix_size > strlen(str)) { - return 0; - } - - return !memcmp(str, prefix, prefix_size); -} - -static void http_log(struct http_req *req) -{ - printf("%s - \"%s %s %s\"\n", - req->client.addr_str, - req->method, - req->path, - req->ver); -} - -static int handle_inbox_request(struct http_req *req, struct cursor *arena) -{ - const char *signature; - unsigned char *start; - FILE *out; - int len; - struct sig_header sig; - struct json_parser pull; - struct json_pusher push; - struct ap_json apjson; - - struct json_handlers compact; - struct json_handlers ap_handler; - - make_compact_handlers(&compact, &push); - make_ap_json_pusher(&ap_handler, &apjson); - init_ap_json(&apjson, &compact); - - memset(&sig, 0, sizeof(sig)); - - if (!get_header(req->headers, "signature", &signature)) { - note_error(&req->errs, "signature"); - return 0; - } - - printf("signature: %s\n", signature); - - if (!parse_signature_header(&req->errs, arena, signature, strlen(signature), &sig)) { - note_error(&req->errs, "parse signature header"); - return 0; - } - - apjson.sig = &sig; - apjson.req = req; - - // TODO: defer this check - if (!verify_signature_header(&sig)) { - note_error(&req->errs, "verify"); - return 0; - } - - start = arena->p; - init_json_pusher_with(&push, arena); - - init_json_parser(&pull, req->body, req->body_len, &ap_handler); - if (!parse_json(&pull)) { - note_error(&req->errs, "json parse failed"); - return 0; - } - - if (!(out = fopen("activities.json", "a"))) { - note_error(&req->errs, "could not open activities.json"); - return 0; - } - - len = push.cur.p - start; - - // 128 KB - if (len >= 131072) { - note_error(&req->errs, "ActivityPub message too big"); - return 0; - } - - fwrite(start, len, 1, out); - fwrite("\n", 1, 1, out); - fclose(out); - - write_resp_header(req, "200 OK"); - return 1; -} - -static inline int is_get(struct http_req *req) -{ - return streq(req->method, "GET"); -} - -static inline int is_post(struct http_req *req) -{ - return streq(req->method, "POST"); -} - - -static inline int is_accept_activity(struct http_req *req) -{ - const char *accept; - - if (!get_header(req->headers, "accept", &accept)) { - note_error(&req->errs, "accept"); - return 0; - } - - if (!strstr(accept, "application/activity+json")) { - note_error(&req->errs, "not accept: '%s'", accept); - return 0; - } - - return 1; -} - -struct profile -{ - const char *id; - const char *type; - const char *username; - const char *name; - const char *summary; - const char *url; - int manually_approves_followers; - const char *image_mime_type; - const char *image_url; - const char *key_id; - const char *pubkey_pem; -}; - -static void test_profile(struct profile *p) -{ - static unsigned char buf[128]; - struct cursor c; - make_cursor(buf, buf + sizeof(buf), &c); - - const char *host = get_hostname(); - assert(host); - - p->id = (char*)c.p; - assert( - push_str(&c, SCHEMA) && push_str(&c, host) && push_c_str(&c, "/") - ); - - p->type = "Person"; - p->username = "jb55"; - p->name = "William Casarin"; - p->summary = "wolfsocks prototype"; - p->url = p->id; - p->manually_approves_followers = 0; - p->image_mime_type = "image/jpeg"; - p->image_url = "https://jb55.com/s/blue-me.jpg"; - p->key_id = "main-key"; - p->pubkey_pem = "-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnJOPxwmRGBBQYm7YgHRubTaYaKbMoEQiui+37nizXA73CRNeKblSXIaJnfOKfz/ttRG0GH43GzHTpghUDuZX+QBpyOk8UMmCW5gM0Y5c3IOv0zLezqLXrVEM8UXMUHE3hxf61r1NKl1+IG9MwhtHayx0Kaz6vT/V8nkotCSlb91lMT8X28bButwN86RCclZncecQXuVvgXnFeZCeBLM+qV2tBPnn14Ws+AqVvVnBW8xXwVfSPFHQchSLAusdWI7Kw/oWN/on2CqfRASoaVASqKG+uPuJ+1f92iH0ZY1wLB2/ITl7HKTiIMKNikXTWcUudkMlKxc5Iqb7HMHuaPZ9IQIDAQAB-----END PUBLIC KEY-----"; -} - -static int handle_self(struct http_req *req) -{ - struct profile profile; - test_profile(&profile); - - write_resp_header(req, "200 OK"); - - fprintf(req->client.socket_file, - "{" - "\"@context\": [" - "\"https://www.w3.org/ns/activitystreams\"" - "]," - "\"inbox\": \"%sinbox\"," - "\"id\": \"%s\"," - "\"type\": \"%s\"," - "\"preferredUsername\": \"%s\"," - "\"name\": \"%s\"," - "\"summary\": \"%s\"," - "\"url\": \"%s\"," - "\"manuallyApprovesFollowers\": %s," - "\"icon\": {" - "\"type\": \"Image\"," - "\"mediaType\": \"%s\"," - "\"url\": \"%s\"" - "}," - "\"publicKey\": {" - "\"id\": \"%s#%s\"," - "\"owner\": \"%s\"," - "\"publicKeyPem\": \"%s\"" - "}" - "}\n", - profile.id, - profile.id, - profile.type, - profile.username, - profile.name, - profile.summary, - profile.url, - profile.manually_approves_followers ? "true" : "false", - profile.image_mime_type, - profile.image_url, - profile.id, profile.key_id, - profile.id, - profile.pubkey_pem); - - return 1; -} - -static int handle_request(struct http_req *req, struct cursor *arena) -{ - http_log(req); - - if (starts_with(req->path, "/.well-known/webfinger?resource=acct:")) { - return handle_webfinger(req); - } else if (is_post(req) && patheq(req, "/inbox")) { - return handle_inbox_request(req, arena); - } else if (is_get(req) && - is_accept_activity(req) && - streq(req->path, "/")) { - return handle_self(req); - } - - return 0; -} - -static int http_accept_client(struct http_req *req, int parent) -{ - struct sockaddr_in *addr; - socklen_t client_len; - struct hostent *client_host; - - client_len = sizeof(addr); - - addr = &req->client.sockaddr; - - req->client.socket = - accept(parent, (struct sockaddr *) &req->client.sockaddr, - &client_len); - - if (req->client.socket < 0) { - note_error(&req->errs, "bad socket"); - return 0; - } - - req->client.socket_file = fdopen(req->client.socket, "wb"); - - client_host = gethostbyaddr((const char *)&addr->sin_addr.s_addr, - sizeof(addr->sin_addr.s_addr), AF_INET); - - if (!client_host) { - note_error(&req->errs, "gethostbyaddr"); - return 0; - } - - req->client.addr_str = inet_ntoa(addr->sin_addr); - - if (!req->client.addr_str) { - note_error(&req->errs, "inet_htoa"); - return 0; - } - - return 1; -} - -void run_http_server() -{ - static unsigned char buffer[BUF_SIZE]; - unsigned char *arena; - - ssize_t len, size; - - int parent; - struct sockaddr_in server_addr; - int optval; - - struct http_req req; - - struct parser parser; - - const int port = 5188; - arena = malloc(ARENA_SIZE); - assert(arena); - - if ((parent = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - error("socket"); - } - - optval = 1; - setsockopt(parent, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, - sizeof(optval)); - - memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = htonl(INADDR_ANY); - server_addr.sin_port = htons(port); - - if (bind(parent, (struct sockaddr *)&server_addr, - sizeof(server_addr)) < 0) { - error("bind"); - } - - printf("listening for activities on 0.0.0.0:%d\n", port); - - if (listen(parent, 5) < 0) { - error("listen"); - } - - while (1) { - init_http_req(&req); - make_cursor(buffer, buffer + BUF_SIZE, &parser.cur); - make_cursor(arena, arena + ARENA_SIZE, &parser.arena); - - http_accept_client(&req, parent); - - for(size = 0;1;) { - len = read(req.client.socket, (void*)(buffer+size), BUF_SIZE-size); - size += len; - if (len == 0) { - break; - } - - if (len != (BUF_SIZE-size)) { - break; - } - } - - if (parse_http_request(&req, &parser, size)) { - handle_request(&req, &parser.arena); - } - - fclose(req.client.socket_file); - close(req.client.socket); - } - - free(arena); -} - -static void load_config() -{ - if (!get_hostname()) { - printf("CHIBIPUB_HOST env not set\n"); - exit(2); - } -} - -static int checksigs() -{ - struct sigcheck check; - check.activity_file = "activities.json"; - if (!sigcheck(&check)) { - printf("sigcheck failed\n"); - return 1; - } - printf("ok\n"); - return 0; -} - -int main(int argc, char *argv[]) -{ - if (argc >= 2 && !strcmp(argv[1], "checksigs")) { - return checksigs(); - } - - load_config(); - run_http_server(); - - return 0; -}