diff --git a/.gitignore b/.gitignore index ddc0755..49361ea 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ work/*.o build/swebs example/logs example/swebs.pid +example/library.so diff --git a/Makefile b/Makefile index 99f0ab9..467bc90 100644 --- a/Makefile +++ b/Makefile @@ -1,21 +1,25 @@ SRC = $(wildcard src/*.c) OBJ = $(subst .c,.o,$(subst src,work,$(SRC))) LIBS = -pthread -pie -lrt $(shell pkg-config --libs gnutls) -CFLAGS := -O2 -pipe -Wall -Wpedantic -Werror -ansi -D_POSIX_C_SOURCE=200809L -CFLAGS += -Isrc/include -fpie $(shell pkg-config --cflags gnutls) +CFLAGS := -O2 -pipe -Wall -Wpedantic -ansi +CFLAGS += -Isrc/ -fpie -D_POSIX_C_SOURCE=200809L $(shell pkg-config --cflags gnutls) INSTALLDIR := /usr/sbin +HEADERDIR := /usr/include/ +INCLUDE_DIRECTORY := swebs OUT = swebs build/$(OUT): $(OBJ) $(CC) $(OBJ) -o build/$(OUT) $(LIBS) -work/%.o: src/%.c $(wildcard src/include/*.h) +work/%.o: src/%.c $(wildcard src/swebs/*.h) $(CC) $(CFLAGS) $< -c -o $@ install: build/$(OUT) cp build/$(OUT) $(INSTALLDIR)/$(OUT) + cp -r src/$(INCLUDE_DIRECTORY) $(HEADERDIR)/$(INCLUDE_DIRECTORY) if ! id swebs >> /dev/null 2>&1; then useradd -M swebs; fi uninstall: $(INSTALLDIR)/$(OUT) rm $(INSTALLDIR)/$(OUT) + rm -r $(HEADERDIR)/$(INCLUDE_DIRECTORY) if id swebs >> /dev/null 2>&1; then userdel swebs; fi diff --git a/documentation/dynamicpages.md b/documentation/dynamicpages.md new file mode 100644 index 0000000..6403106 --- /dev/null +++ b/documentation/dynamicpages.md @@ -0,0 +1,62 @@ +# Part 1: The problem + +A static webpage is easy. Just tell swebs to read a few files given a few http paths and you're done. Dyanmic pages are harder. There are a few solutions, you could execute a program and return stdout (too slow), encourage each website to create their own forks of swebs and make it really easy to directly modify the source code to add a dynamic page (inelegant), write a php interpreter (bloated), execute a program the user creates and keep it running while the web server communicates with it (what's the point of writing a web server if the user does all the work of setting up a server and responding to requests?) + +# Part 2: The solution + +The solution I thought of was to dynamically load a C library the user optionally writes that creates pages. The user is responsible for writing C code that generates pages, and swebs is responsible for parsing requests and asking for said pages. The library the user creates must be a shared object file, and define this function: + +```int getResponse(Request *request, Response *response)``` + +```getResponse``` returns the HTTP response code of that request. + +```Request``` and ```Response``` are defined in ``````. ```getResponse()```. `````` is guarunteed to be included by ``````, where ```getResponse()``` is defined. + +The specific library to use is set with the ```library``` global variable in a sitefile. + +The various data types important to you in this scenario are: + +``` +typedef struct { + char *field; + char *value; +} Field; +/*HTTP field*/ + +typedef struct { + long fieldCount; + Field *fields; +} Request; +/*HTTP request, pretty self explanatory*/ + +typedef enum { + FILE_KNOWN_LENGTH, + /* A file where the total length is known (i.e. a file on disk) */ + FILE_UNKNOWN_LENGTH, + /* A file where the total length is unknown (i.e. a pipe) */ + BUFFER, + /* A buffer stored in memory. free() will be called on said buffer. */ + DEFAULT + /* The default response for the response code */ +} ResponseType; + +typedef struct { + int fd; + size_t len; + /* This field is sometimes optional */ +} File; + +typedef struct { + void *data; + /* This data will be freed. */ + size_t len; +} Buffer; + +typedef struct { + ResponseType type; + union { + File file; + Buffer buffer; + } response; +} Response; +``` diff --git a/documentation/sitefiles.md b/documentation/sitefiles.md index 89a899e..bf58f60 100644 --- a/documentation/sitefiles.md +++ b/documentation/sitefiles.md @@ -28,9 +28,11 @@ sitefiles also allow comments with # # Part 4: Global variables +* ```port``` - the port to use. Note that this is a global variable, and so one instance of swebs cannot use multiple ports. * ```transport``` - the type of connection to use. One of: * TCP (default) * TLS * ```key``` - The filepath of the private key to use if transport == TLS * ```cert``` - The filepath of the certificate to use if transport == TLS * ```timeout``` - The amount of time to wait for data before closing the connection in ms +* ```library``` - the path of a library that is linked in during runtime if ```DYNAMIC_LINKED_PAGES```is set. diff --git a/example/Makefile b/example/Makefile new file mode 100644 index 0000000..da0b281 --- /dev/null +++ b/example/Makefile @@ -0,0 +1,2 @@ +library.so: library.c + $(CC) $< -o $@ -shared -I../src/ diff --git a/example/library.c b/example/library.c new file mode 100644 index 0000000..050da51 --- /dev/null +++ b/example/library.c @@ -0,0 +1,14 @@ +#include +#include +#include + +#include + +int getResponse(Request *request, Response *response) { + char *str = "

Hello world!

"; + response->type = BUFFER; + response->response.buffer.data = malloc(30); + strcpy(response->response.buffer.data, str); + response->response.buffer.len = strlen(str); + return 200; +} diff --git a/example/run.sh b/example/run.sh index 84a4ab1..93d405d 100755 --- a/example/run.sh +++ b/example/run.sh @@ -1,3 +1,3 @@ #!/bin/sh -../build/swebs -P swebs.pid -s sitefile -o logs -p 8000 -b 100 -j2 +../build/swebs -p swebs.pid -s sitefile -o logs -b 100 -j2 diff --git a/example/sitefile b/example/sitefile index c707a5f..3a63b61 100644 --- a/example/sitefile +++ b/example/sitefile @@ -1,7 +1,10 @@ +define port 8000 + #define transport TLS define key domain.key define cert domain.crt define timeout 2000 +define library ./library.so set host localhost:8000 read / site/index.html @@ -10,7 +13,7 @@ throw /blog/forbidden 403 exec /blog/2022-1-31 site/blog/blog/2022-1-31.sh read /blog/.* site/blog/ #/blog/2021-1-25.html turns into site/blog//blog/2021-1-25.html -exec /dynamic site/build-page.sh +linked /library set host 127.0.0.1:8000 read / site/easteregg.html read /egg.png site/egg.png diff --git a/src/connections.c b/src/connections.c index 04a1b83..999ce6f 100644 --- a/src/connections.c +++ b/src/connections.c @@ -19,11 +19,11 @@ #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include int newConnection(Stream *stream, Connection *ret) { struct timespec currentTime; diff --git a/src/dynamic.c b/src/dynamic.c new file mode 100644 index 0000000..1db9128 --- /dev/null +++ b/src/dynamic.c @@ -0,0 +1,42 @@ +/* + swebs - a simple web server + Copyright (C) 2022 Nate Choe + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#include +#if DYNAMIC_LINKED_PAGES +#include +#include + +int (*loadGetResponse(char *library))(Request *, Response *) { + void *handle = dlopen(library, RTLD_LAZY); + int (*ret)(Request *, Response *); + + *(void **) &ret = dlsym(handle, "getResponse"); + /* Dirty hack to make this code ANSI C compliant*/ + return ret; +} +#else +#include + +#include + +int (*loadGetResponse(char *library))(Request *, Response *) { + /* The code should NEVER reach this state */ + exit(EXIT_FAILURE); +} +#endif diff --git a/src/main.c b/src/main.c index 17f0562..2341802 100644 --- a/src/main.c +++ b/src/main.c @@ -24,10 +24,10 @@ #include #include -#include -#include -#include -#include +#include +#include +#include +#include static void daemonize(char *pidfile) { pid_t pid; @@ -66,7 +66,6 @@ int main(int argc, char **argv) { char *logout = "/var/log/swebs.log"; char *sitefile = NULL; int processes = sysconf(_SC_NPROCESSORS_ONLN) + 1; - uint16_t port = 443; int backlog = 100; char shouldDaemonize = 0; char *pidfile = "/run/swebs.pid"; @@ -79,7 +78,7 @@ int main(int argc, char **argv) { int i; for (;;) { - int c = getopt(argc, argv, "o:j:s:p:b:c:BP:hl"); + int c = getopt(argc, argv, "o:j:s:b:c:Bp:hl"); if (c == -1) break; switch (c) { @@ -92,16 +91,13 @@ int main(int argc, char **argv) { case 's': sitefile = optarg; break; - case 'p': - port = atoi(optarg); - break; case 'b': backlog = atoi(optarg); break; case 'B': shouldDaemonize = 1; break; - case 'P': + case 'p': pidfile = optarg; break; case 'l': @@ -126,10 +122,9 @@ NULL " -o [out] Set the log file (default: /var/log/swebs.log)", " -j [cores] Use that many cores (default: $(nproc)+1)", " -s [site file] Use that site file (required)", -" -p [port] Set the port (default: 443)", " -b [backlog] Set the socket backlog (default: 100)", " -B Run swebs in the background and daemonize", -" -P [pidfile] Specify PID file if daemonizing", +" -p [pidfile] Specify PID file if daemonizing", " (defualt: /run/swebs.pid)", " -l Show some legal details", " -h Show this help message", @@ -155,11 +150,11 @@ NULL switch (site->type) { case TCP: default: - listener = createListener(TCP, port, backlog); + listener = createListener(TCP, site->port, backlog); break; case TLS: initTLS(); - listener = createListener(TLS, port, backlog, + listener = createListener(TLS, site->port, backlog, site->key, site->cert); break; } diff --git a/src/responses.c b/src/responses.c index 5ab42ac..5951f7e 100644 --- a/src/responses.c +++ b/src/responses.c @@ -26,8 +26,8 @@ #include #include -#include -#include +#include +#include static int readResponse(Connection *conn, char *path) { int fd = -1; @@ -151,6 +151,38 @@ error: return 1; } +static int linkedResponse(Connection *conn, + int (*getResponse)(Request *request, Response *response)) { + Request request; + Response response; + int code; + int ret; + + request.fieldCount = conn->fieldCount; + request.fields = conn->fields; + + code = getResponse(&request, &response); + + switch (response.type) { + case FILE_KNOWN_LENGTH: + return sendKnownPipe(conn->stream, getCode(code), + response.response.file.fd, + response.response.file.len); + case FILE_UNKNOWN_LENGTH: + return sendPipe(conn->stream, getCode(code), + response.response.file.fd); + case BUFFER: + ret = sendBinaryResponse(conn->stream, getCode(code), + response.response.buffer.data, + response.response.buffer.len); + free(response.response.buffer.data); + return ret; + case DEFAULT: + return sendErrorResponse(conn->stream, getCode(code)); + } + return 1; +} + static int fullmatch(regex_t *regex, char *str) { regmatch_t match; if (regexec(regex, str, 1, &match, 0)) @@ -190,6 +222,20 @@ int sendResponse(Connection *conn, Sitefile *site) { sendErrorResponse(conn->stream, site->content[i].arg); break; + case LINKED: +#if DYNAMIC_LINKED_PAGES + if (!site->getResponse) + sendErrorResponse(conn->stream, + ERROR_500); + else + linkedResponse(conn, + site->getResponse); +#else + /* Unreachable state */ + sendErrorResponse(conn->stream, + ERROR_500); +#endif + break; default: sendErrorResponse(conn->stream, ERROR_500); diff --git a/src/responseutil.c b/src/responseutil.c index c7682ef..9282c60 100644 --- a/src/responseutil.c +++ b/src/responseutil.c @@ -22,7 +22,7 @@ #include -#include +#include #define CONST_FIELDS "Server: swebs/0.1\r\n" @@ -55,7 +55,7 @@ static int sendStreamValist(Stream *stream, char *format, ...) { va_start(ap, format); vsprintf(data, format, ap); - if (resilientSend(stream, data, len) < len) { + if (resilientSend(stream, data, len)) { free(data); return 1; } @@ -124,20 +124,9 @@ int sendHeader(Stream *stream, const char *status, size_t len) { int sendSeekableFile(Stream *stream, const char *status, int fd) { off_t len; - size_t totalSent = 0; len = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); - sendHeader(stream, status, len); - for (;;) { - char buffer[1024]; - ssize_t inBuffer = read(fd, buffer, sizeof(buffer)); - if (inBuffer < 0) - return 1; - if (inBuffer == 0) - return totalSent != len; - if (resilientSend(stream, buffer, inBuffer)) - return 1;; - } + return sendKnownPipe(stream, status, fd, len); } int sendPipe(Stream *stream, const char *status, int fd) { @@ -177,3 +166,18 @@ error: sendErrorResponse(stream, ERROR_500); return 1; } + +int sendKnownPipe(Stream *stream, const char *status, int fd, size_t len) { + size_t totalSent = 0; + sendHeader(stream, status, len); + for (;;) { + char buffer[1024]; + ssize_t inBuffer = read(fd, buffer, sizeof(buffer)); + if (inBuffer < 0) + return 1; + if (inBuffer == 0) + return totalSent != len; + if (resilientSend(stream, buffer, inBuffer)) + return 1; + } +} diff --git a/src/runner.c b/src/runner.c index 52213cf..e7da0fb 100644 --- a/src/runner.c +++ b/src/runner.c @@ -22,9 +22,9 @@ #include #include -#include -#include -#include +#include +#include +#include void *runServer(RunnerArgs *args) { Sitefile *site = args->site; diff --git a/src/sitefile.c b/src/sitefile.c index 2f81d33..12a90a6 100644 --- a/src/sitefile.c +++ b/src/sitefile.c @@ -20,9 +20,18 @@ #include #include -#include -#include -#include +#include + +#include +#include +#include +#if DYNAMIC_LINKED_PAGES +#include +#endif +/* + * This if isn't technically necessary, but it generates warnings, which is + * good. + * */ typedef enum { SUCCESS, @@ -173,6 +182,7 @@ Sitefile *parseSitefile(char *path) { int argc; char **argv; int allocatedLength = 50; + char gotPort = 0; Sitefile *ret; if (file == NULL) @@ -186,6 +196,9 @@ Sitefile *parseSitefile(char *path) { ret->timeout = 0; ret->size = 0; ret->content = malloc(allocatedLength * sizeof(SiteCommand)); +#if DYNAMIC_LINKED_PAGES + ret->getResponse = NULL; +#endif if (ret->content == NULL) { free(ret); return NULL; @@ -194,6 +207,8 @@ Sitefile *parseSitefile(char *path) { ReturnCode status = getCommand(file, &argc, &argv); switch (status) { case FILE_END: + if (!gotPort) + goto nterror; fclose(file); return ret; case ERROR: case LINE_END: @@ -226,12 +241,26 @@ Sitefile *parseSitefile(char *path) { else goto error; } + else if (strcmp(argv[1], "port") == 0) { + ret->port = atoi(argv[2]); + gotPort = 1; + } else if (strcmp(argv[1], "key") == 0) ret->key = strdup(argv[2]); else if (strcmp(argv[1], "cert") == 0) ret->cert = strdup(argv[2]); else if (strcmp(argv[1], "timeout") == 0) ret->timeout = atoi(argv[2]); + else if (strcmp(argv[1], "library") == 0) { +#if DYNAMIC_LINKED_PAGES + ret->getResponse = loadGetResponse(argv[2]); +#else + fprintf(stderr, +"This version of swebs has no dynamic page support\n" + ); + exit(EXIT_FAILURE); +#endif + } else goto error; continue; @@ -245,31 +274,37 @@ Sitefile *parseSitefile(char *path) { goto error; ret->content = newcontent; } - if (argc < 3) - goto error; if (regcomp(&ret->content[ret->size].path, argv[1], cflags)) goto error; if (strcmp(argv[0], "read") == 0) { + if (argc < 3) + goto error; ret->content[ret->size].arg = strdup(argv[2]); if (ret->content[ret->size].arg == NULL) goto error; ret->content[ret->size].command = READ; } else if (strcmp(argv[0], "exec") == 0) { + if (argc < 3) + goto error; ret->content[ret->size].arg = strdup(argv[2]); if (ret->content[ret->size].arg == NULL) goto error; ret->content[ret->size].command = EXEC; } else if (strcmp(argv[0], "throw") == 0) { + if (argc < 3) + goto error; ret->content[ret->size].arg = getCode(atoi(argv[2])); if (ret->content[ret->size].arg == NULL) goto error; ret->content[ret->size].command = THROW; } + else if (strcmp(argv[0], "linked") == 0) + ret->content[ret->size].command = LINKED; else goto error; freeTokens(argc, argv); diff --git a/src/sockets.c b/src/sockets.c index a29a0cd..bc2d11f 100644 --- a/src/sockets.c +++ b/src/sockets.c @@ -26,7 +26,7 @@ #include #include -#include +#include int initTLS() { assert(gnutls_global_init() >= 0); diff --git a/src/swebs/config.h b/src/swebs/config.h new file mode 100644 index 0000000..f06f695 --- /dev/null +++ b/src/swebs/config.h @@ -0,0 +1,14 @@ +/* + * This file specifies which features to enable/disable during compile time. + * 0 - disable a feature + * non-zero - enable a feature + * */ + +#ifndef HAVE_CONFIG +#define HAVE_CONFIG +/* HEADER GUARD, DO NOT REMOVE*/ + +#define DYNAMIC_LINKED_PAGES 1 + +#endif +/* HEADER GUARD, DO NOT REMOVE*/ diff --git a/src/include/connections.h b/src/swebs/connections.h similarity index 94% rename from src/include/connections.h rename to src/swebs/connections.h index a552fe1..f097f7f 100644 --- a/src/include/connections.h +++ b/src/swebs/connections.h @@ -18,9 +18,9 @@ #ifndef HAVE_CONNECTIONS #define HAVE_CONNECTIONS -#include -#include -#include +#include +#include +#include typedef enum { RECEIVE_REQUEST, @@ -28,11 +28,6 @@ typedef enum { RECEIVE_BODY } ConnectionSteps; -typedef struct { - char *field; - char *value; -} Field; - typedef struct Connection { Stream *stream; ConnectionSteps progress; diff --git a/src/swebs/dynamic.h b/src/swebs/dynamic.h new file mode 100644 index 0000000..3aab32c --- /dev/null +++ b/src/swebs/dynamic.h @@ -0,0 +1,25 @@ +/* + swebs - a simple web server + Copyright (C) 2022 Nate Choe + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#ifndef HAVE_DYNAMIC +#define HAVE_DYNAMIC + +#include + +int (*loadGetResponse(char *))(Request *, Response *); +/* It takes the name of the library and returns getResponse() */ +#endif diff --git a/src/include/responses.h b/src/swebs/responses.h similarity index 93% rename from src/include/responses.h rename to src/swebs/responses.h index b6ce69f..1b6d010 100644 --- a/src/include/responses.h +++ b/src/swebs/responses.h @@ -17,8 +17,8 @@ */ #ifndef HAVE_RESPONSES #define HAVE_RESPONSES -#include -#include +#include +#include int sendResponse(Connection *conn, Sitefile *site); /* returns 1 on error, sets conn->progress to SEND_RESPONSE */ diff --git a/src/include/responseutil.h b/src/swebs/responseutil.h similarity index 93% rename from src/include/responseutil.h rename to src/swebs/responseutil.h index 3edfab4..c7c3a49 100644 --- a/src/include/responseutil.h +++ b/src/swebs/responseutil.h @@ -17,7 +17,7 @@ */ #ifndef HAVE_RESPONSE_UTIL #define HAVE_RESPONSE_UTIL -#include +#include #define CODE_200 "200 OK" #define ERROR_400 "400 Bad Request" @@ -34,4 +34,5 @@ int sendErrorResponse(Stream *stream, const char *error); int sendHeader(Stream *stream, const char *status, size_t len); int sendSeekableFile(Stream *stream, const char *status, int fd); int sendPipe(Stream *stream, const char *status, int fd); +int sendKnownPipe(Stream *stream, const char *status, int fd, size_t len); #endif diff --git a/src/include/runner.h b/src/swebs/runner.h similarity index 95% rename from src/include/runner.h rename to src/swebs/runner.h index bd57a50..f5ac963 100644 --- a/src/include/runner.h +++ b/src/swebs/runner.h @@ -19,8 +19,8 @@ #define HAVE_RUNNER #include -#include -#include +#include +#include typedef struct { Sitefile *site; diff --git a/src/include/sitefile.h b/src/swebs/sitefile.h similarity index 86% rename from src/include/sitefile.h rename to src/swebs/sitefile.h index 814afac..b64f5e9 100644 --- a/src/include/sitefile.h +++ b/src/swebs/sitefile.h @@ -18,13 +18,16 @@ #ifndef HAVE_SITEFILE #define HAVE_SITEFILE #include +#include -#include +#include +#include typedef enum { READ, EXEC, - THROW + THROW, + LINKED } Command; typedef struct { @@ -42,6 +45,10 @@ typedef struct { char *key; char *cert; int timeout; + uint16_t port; +#if DYNAMIC_LINKED_PAGES + int (*getResponse)(Request *, Response *); +#endif } Sitefile; Sitefile *parseSitefile(char *path); diff --git a/src/include/sockets.h b/src/swebs/sockets.h similarity index 98% rename from src/include/sockets.h rename to src/swebs/sockets.h index 15b1337..4c0468a 100644 --- a/src/include/sockets.h +++ b/src/swebs/sockets.h @@ -22,7 +22,7 @@ #include #include -#include +#include typedef struct { SocketType type; diff --git a/src/swebs/swebs.h b/src/swebs/swebs.h new file mode 100644 index 0000000..fca2ecd --- /dev/null +++ b/src/swebs/swebs.h @@ -0,0 +1,35 @@ +/* + swebs - a simple web server + Copyright (C) 2022 Nate Choe + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + * This file is called swebs.h because it's the main thing that the end users + * are going to be interfacing with. + * */ +#ifndef HAVE_SWEBS +#define HAVE_SWEBS +#include +#if DYNAMIC_LINKED_PAGES +#include + +int getResponse(Request *request, Response *response); +/* Returns the HTTP response code, the user is responsible for writing this */ + +#else +#error "This version of swebs has no dynamic linked page support" +#endif +#endif diff --git a/src/swebs/types.h b/src/swebs/types.h new file mode 100644 index 0000000..c090a6c --- /dev/null +++ b/src/swebs/types.h @@ -0,0 +1,80 @@ +/* + swebs - a simple web server + Copyright (C) 2022 Nate Choe + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#ifndef HAVE_TYPES +#define HAVE_TYPES + +#include +#include + +typedef enum { + TCP, + TLS +} SocketType; + +typedef enum { + GET, + POST, + PUT, + HEAD, + DELETE, + PATCH, + OPTIONS, + INVALID + /* + * this indicates an invalid type of request, there is no request called + * INVALID in HTTP/1.1. + * */ +} RequestType; + +typedef struct { + char *field; + char *value; +} Field; + +typedef struct { + long fieldCount; + Field *fields; +} Request; + +typedef enum { + FILE_KNOWN_LENGTH, + FILE_UNKNOWN_LENGTH, + BUFFER, + DEFAULT + /* Return the default value for this error code */ +} ResponseType; + +typedef struct { + int fd; + size_t len; + /* Sometimes optional */ +} File; + +typedef struct { + void *data; + size_t len; +} Buffer; + +typedef struct { + ResponseType type; + union { + File file; + Buffer buffer; + } response; +} Response; +#endif diff --git a/src/include/util.h b/src/swebs/util.h similarity index 79% rename from src/include/util.h rename to src/swebs/util.h index 342a78b..d706dcb 100644 --- a/src/include/util.h +++ b/src/swebs/util.h @@ -17,25 +17,8 @@ */ #ifndef HAVE_UTIL #define HAVE_UTIL -typedef enum { - TCP, - TLS -} SocketType; -typedef enum { - GET, - POST, - PUT, - HEAD, - DELETE, - PATCH, - OPTIONS, - INVALID - /* - * this indicates an invalid type of request, there is no request called - * INVALID in HTTP/1.1. - * */ -} RequestType; +#include int initLogging(char *path); int createLog(char *msg); diff --git a/src/util.c b/src/util.c index 03d94e8..49bc23a 100644 --- a/src/util.c +++ b/src/util.c @@ -21,7 +21,8 @@ #include #include -#include +#include +#include static FILE *logs;