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 | ++ |
M | Makefile | | | 13 | ++++++++++--- |
A | corpus/like.json | | | 12 | ++++++++++++ |
A | src/cursor.c | | | 137 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | src/cursor.h | | | 34 | ++++++++++++++++++++++++++++++++++ |
A | src/wolfsocks.c | | | 156 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
D | wolfsocks.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;
-}