chibipub

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

commit 23b7e828cd1e61c246a6f33ec1ef0db4cb50cb40
parent 1ead1d5bf6af5550782a16fa0c156b64bfca5fee
Author: William Casarin <jb55@jb55.com>
Date:   Wed, 18 Nov 2020 11:41:41 -0800

begin http parser

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
M.gitignore | 2++
MMakefile | 13++++++++++---
Acorpus/like.json | 12++++++++++++
Asrc/cursor.c | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/cursor.h | 34++++++++++++++++++++++++++++++++++
Asrc/wolfsocks.c | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dwolfsocks.c | 110-------------------------------------------------------------------------------
7 files changed, 351 insertions(+), 113 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,2 +1,4 @@ .build-result /wolfsocks +*.o +/tags diff --git a/Makefile b/Makefile @@ -1,5 +1,12 @@ -CFLAGS = -Wall -Werror -std=c89 +CFLAGS = -Wall -Werror -std=c89 -Isrc -wolfsocks: wolfsocks.c - $(CC) $(CFLAGS) $< $(LDFLAGS) -o $@ +OBJS = src/cursor.o + +wolfsocks: src/wolfsocks.c $(OBJS) + $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ + +tags: fake + ctags src/*.c src/*.h + +.PHONY: fake diff --git a/corpus/like.json b/corpus/like.json @@ -0,0 +1,12 @@ +{ + "@context": ["https://www.w3.org/ns/activitystreams", + {"@language": "en"}], + "type": "Like", + "actor": "https://dustycloud.org/chris/", + "summary": "Chris liked 'Minimal ActivityPub update client'", + "object": "https://rhiaro.co.uk/2016/05/minimal-activitypub", + "to": ["https://rhiaro.co.uk/#amy", + "https://dustycloud.org/followers", + "https://rhiaro.co.uk/followers/"], + "cc": "https://e14n.com/evan" +} diff --git a/src/cursor.c b/src/cursor.c @@ -0,0 +1,137 @@ + +#include "cursor.h" + +#include <stdio.h> +#include <string.h> + +void copy_cursor(struct cursor *src, struct cursor *dest) +{ + dest->start = src->start; + dest->p = src->p; + dest->end = src->end; +} + +void make_cursor(unsigned char *start, unsigned char *end, struct cursor *cursor) +{ + cursor->start = start; + cursor->p = start; + cursor->end = end; +} + +int cursor_index(struct cursor *cursor, int elem_size) +{ + return (cursor->p - cursor->start) / elem_size; +} + + +int pull_byte(struct cursor *cursor, unsigned char *c) +{ + if (cursor->p + 1 > cursor->end) + return 0; + + *c = *cursor->p; + cursor->p++; + + return 1; +} + + +int push_byte(struct cursor *cursor, unsigned char c) +{ + if (cursor->p + 1 >= cursor->end) { + return 0; + } + + *cursor->p = c; + cursor->p++; + + return 1; +} + +int pull_data_into_cursor(struct cursor *cursor, + struct cursor *dest, + unsigned char **data, + int len) +{ + int ok; + + if (dest->p + len >= dest->end) { + printf("not enough room in dest buffer\n"); + return 0; + } + + ok = pull_data(cursor, dest->p, len); + if (!ok) return 0; + + *data = dest->p; + dest->p += len; + + return 1; +} + +int pull_data(struct cursor *cursor, unsigned char *data, int len) +{ + if (cursor->p + len >= cursor->end) { + return 0; + } + + memcpy(data, cursor->p, len); + cursor->p += len; + + return 1; +} + +int push_data(struct cursor *cursor, unsigned char *data, int len) +{ + if (cursor->p + len > cursor->end) { + printf("push_data oob\n"); + return 0; + } + + memcpy(cursor->p, data, len); + cursor->p += len; + + return 1; +} + +int push_int(struct cursor *cursor, int i) +{ + return push_data(cursor, (unsigned char*)&i, sizeof(i)); +} + +int pull_int(struct cursor *cursor, int *i) +{ + return pull_data(cursor, (unsigned char*)i, sizeof(*i)); +} + +int push_u16(struct cursor *cursor, unsigned short i) +{ + return push_data(cursor, (unsigned char*)&i, sizeof(i)); +} + +void *index_cursor(struct cursor *cursor, unsigned short index, int elem_size) +{ + unsigned char *p; + p = &cursor->start[elem_size * index]; + + if (p > cursor->end) + return NULL; + + return (void*)p; +} + + +int push_sized_str(struct cursor *cursor, const char *str, int len) +{ + return push_data(cursor, (unsigned char*)str, len); +} + +int push_str(struct cursor *cursor, const char *str) +{ + return push_data(cursor, (unsigned char*)str, strlen(str)); +} + +int cursor_remaining_capacity(struct cursor *cursor) +{ + return cursor->end - cursor->p; +} diff --git a/src/cursor.h b/src/cursor.h @@ -0,0 +1,34 @@ + +#ifndef WOLFSOCKS_CURSOR_H +#define WOLFSOCKS_CURSOR_H + +struct cursor { + unsigned char *start; + unsigned char *p; + unsigned char *end; +}; + + +void copy_cursor(struct cursor *src, struct cursor *dest); +int cursor_index(struct cursor *cursor, int elem_size); +void make_cursor(unsigned char *start, unsigned char *end, struct cursor *cursor); +int cursor_remaining_capacity(struct cursor *cursor); +void *index_cursor(struct cursor *cursor, unsigned short index, int elem_size); + +int push_u16(struct cursor *cursor, unsigned short i); +int push_int(struct cursor *cursor, int i); +int push_data(struct cursor *cursor, unsigned char *data, int len); +int push_byte(struct cursor *cursor, unsigned char c); + +int pull_data_into_cursor(struct cursor *cursor, struct cursor *dest, unsigned char **data, int len); +int pull_data(struct cursor *cursor, unsigned char *data, int len); +int pull_byte(struct cursor *cursor, unsigned char *c); +int pull_int(struct cursor *cursor, int *i); + +int push_prefixed_str(struct cursor *cursor, const char *str); +int push_str(struct cursor *cursor, const char *str); +int push_sized_str(struct cursor *cursor, const char *str, int len); + +int pull_prefixed_str(struct cursor *cursor, struct cursor *dest_buf, const char **str); + +#endif diff --git a/src/wolfsocks.c b/src/wolfsocks.c @@ -0,0 +1,156 @@ + +#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 "cursor.h" + +#define BUF_SIZE 4096 + +struct http_req { + char method[12]; + char path[256]; + char ver[8]; +}; + + +static void error(char *msg) +{ + perror(msg); + exit(1); +} + +static int parse_segment(struct cursor *cur, char *method, int method_len) +{ + int ok; + int i; + + for (i = 0; i < method_len-1; i++) { + if (!pull_byte(cur, (unsigned char*)&method[i])) + return 0; + + if (method[i] == ' ') { + method[i] = 0; + break; + } + } + + return 1; +} + +static int parse_http_request(struct http_req *req, unsigned char *buffer, int buflen) +{ + struct cursor c; + make_cursor(buffer, buffer + buflen, &c); + int ok; + + if (!parse_segment(&c, req->method, sizeof(req->method))) + return 0; + + if (!parse_segment(&c, req->path, sizeof(req->path))) + return 0; + + if (!parse_segment(&c, req->ver, sizeof(req->ver))) + return 0; + + return 1; +} + +static void print_http_request(struct http_req *req) +{ + printf("%s %s %s\r\n", req->method, req->path, req->ver); +} + +void run_http_server() +{ + static unsigned char buffer[BUF_SIZE]; + ssize_t len; + socklen_t client_len; + + int parent, client; + struct sockaddr_in server_addr, client_addr; + struct hostent *client_host; + char *client_addr_str; + int optval; + + struct http_req req; + + const int port = 5188; + + 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"); + } + + client_len = sizeof(client_addr); + while (1) { + client = accept(parent, (struct sockaddr *) &client_addr, + &client_len); + if (client < 0) { + error("accept"); + } + + client_host = gethostbyaddr( + (const char *)&client_addr.sin_addr.s_addr, + sizeof(client_addr.sin_addr.s_addr), AF_INET); + + if (!client_host) { + error("gethostbyaddr"); + } + + client_addr_str = inet_ntoa(client_addr.sin_addr); + + if (!client_addr_str) { + error("inet_htoa"); + } + + while(1) { + len = read(client, (void*)buffer, BUF_SIZE); + if (len == 0) { + break; + } + + if (parse_http_request(&req, buffer, BUF_SIZE)) { + print_http_request(&req); + } + + if (len != BUF_SIZE) { + break; + } + } + + close(client); + } +} + +int main(int argc, char *argv[]) +{ + run_http_server(); + + return 0; +} diff --git a/wolfsocks.c b/wolfsocks.c @@ -1,110 +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> - -#define BUF_SIZE 4096 - -void error(char *msg) -{ - perror(msg); - exit(1); -} - -void parse_http_request() -{ -} - -void run_http_server() -{ - static char buffer[BUF_SIZE]; - ssize_t len, wrote; - socklen_t client_len; - - int parent, client; - struct sockaddr_in server_addr, client_addr; - struct hostent *client_host; - char *client_addr_str; - int optval; - - const int port = 5188; - - 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"); - } - - client_len = sizeof(client_addr); - while (1) { - client = accept(parent, (struct sockaddr *) &client_addr, - &client_len); - if (client < 0) { - error("accept"); - } - - client_host = gethostbyaddr( - (const char *)&client_addr.sin_addr.s_addr, - sizeof(client_addr.sin_addr.s_addr), AF_INET); - - if (!client_host) { - error("gethostbyaddr"); - } - - client_addr_str = inet_ntoa(client_addr.sin_addr); - - if (!client_addr_str) { - error("inet_htoa"); - } - - while(1) { - len = read(client, (void*)buffer, BUF_SIZE); - if (len == 0) { - break; - } - - wrote = fwrite(buffer, 1, len, stdout); - if (wrote != len) { - printf("wrote %ld != bufsize %ld\n", wrote, len); - break; - } - - if (len != BUF_SIZE) { - break; - } - } - - close(client); - } -} - -int main(int argc, char *argv[]) -{ - run_http_server(); - - return 0; -}