Mercurial
changeset 6:1e61008b9980
[Seobeo] Updated seobeo so that API is more opinionated. Added my webpage./build.sh
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Mon, 29 Sep 2025 16:00:44 -0700 |
| parents | 3e12bf044589 |
| children | 114cad94008f |
| files | dowa/d_memory.c seobeo/BUILD seobeo/main.c seobeo/pages/index.html seobeo/s_linux_network.c seobeo/seobeo.h |
| diffstat | 6 files changed, 133 insertions(+), 166 deletions(-) [+] |
line wrap: on
line diff
--- a/dowa/d_memory.c Sat Sep 27 16:23:04 2025 -0700 +++ b/dowa/d_memory.c Mon Sep 29 16:00:44 2025 -0700 @@ -265,13 +265,12 @@ perror("Dowa_HashMap_Cache_Folder"); return -1; } - void *value = Dowa_HashMap_Get(p_child_map, "bar.txt"); - // Should not copy as we malloced alredy. + // Should not copy as we malloced already. if (Dowa_HashMap_PushValueWithTypeNoCopy(map, entry->d_name, p_child_map, sizeof(p_child_map), DOWA_HASH_MAP_TYPE_HASHMAP) == -1) { - Dowa_HashMap_Free(map); + Dowa_HashMap_Free(p_child_map); return -1; } }
--- a/seobeo/BUILD Sat Sep 27 16:23:04 2025 -0700 +++ b/seobeo/BUILD Mon Sep 29 16:00:44 2025 -0700 @@ -5,25 +5,40 @@ name = "seobeo", actual = select({ "@platforms//os:osx": ":seobeo_example_mac", - }) + }), + visibility = ["//visibility:public"], +) + +filegroup( + name = "pages_files", + srcs = glob(["pages/**"]), +) + +filegroup( + name = "seobeo_headers", + srcs = [ + "seobeo.h", + "seobeo_internal.h" + ], + visibility = ["//visibility:public"], ) cc_binary( name = "seobeo_example_mac", srcs = ["main.c"], deps = [":seobeo_non_window"], - data = [ - "pages/index.html" - ], + data = glob(["pages/**"]), target_compatible_with = [ "@platforms//os:osx", ], + visibility = ["//visibility:public"], ) cc_library( name = "seobeo_non_window", srcs = [ "s_linux_network.c", + "s_web.c", ], deps = ["//dowa:dowa"], hdrs = [ @@ -33,4 +48,5 @@ target_compatible_with = [ "@platforms//os:osx", ], + visibility = ["//visibility:public"], )
--- a/seobeo/main.c Sat Sep 27 16:23:04 2025 -0700 +++ b/seobeo/main.c Mon Sep 29 16:00:44 2025 -0700 @@ -4,122 +4,8 @@ #include "seobeo/seobeo.h" -Dowa_PHashMap cache; - -void SigchildHandler(int s) -{ - (void)s; // quiet unused variable warning - - // waitpid() might overwrite errno, so we save and restore it: - int saved_errno = errno; - - while(waitpid(-1, NULL, WNOHANG) > 0); - - errno = saved_errno; -} - -void HandleClientRequest(Seobeo_PHandle cli) -{ - Dowa_PArena response_arena = Dowa_Arena_Create(8192); - if (!response_arena) - { - perror("Dowa_Arena_Initialize"); - goto clean_up; - } - - size_t idx = Dowa_HashMap_GetPosition(cache, "index.html"); - Dowa_PHashEntry entry = cache->entries[idx]; - if (!entry) - { - // 404 response if missing - const char *not_found = - "HTTP/2.0 404 Not Found\r\n" - "Content-Length: 0\r\n" - "Connection: close\r\n" - "\r\n"; - send(cli->socket, not_found, strlen(not_found), 0); - goto clean_up; - } - - // 3) Prepare header with the correct contentālength - size_t body_size = entry->capacity; - const char *template = - "HTTP/2.0 200 OK\r\n" - "Content-Type: text/html\r\n" - "Content-Length: %zu\r\n" - "Connection: close\r\n" - "\r\n"; - - // Compute how large the header is and allocate just enough space - int header_len = snprintf(NULL, 0, template, body_size); - void *header = Dowa_Arena_Allocate(response_arena, (size_t)(header_len+1)); - if (header == NULL) - { - perror("Dowa_Arena_Allocate"); - goto clean_up; - } - - snprintf((char *)header, header_len + 1, template, body_size); - Seobeo_Handle_QueueData(cli, - (const uint8*)header, - (uint32)(header_len + 1)); - Seobeo_Handle_QueueData(cli, - (const uint8*)entry->buffer, - (uint32)body_size); - Seobeo_Handle_Flush(cli); - goto clean_up; - -clean_up: - Seobeo_Handle_Destroy(cli); - Dowa_Arena_Free(response_arena); - return ; -} int main(void) { - struct sigaction sa; - - cache = Dowa_HashMap_Create(1024); - if (Dowa_Cache_Folder(cache, "seobeo/pages") != 0) - { - perror("Dowa_Cache_Folder"); - return -1; - } - - Seobeo_PHandle srv = Seobeo_Stream_Handle_Create(NULL, "8080"); - - if (srv->socket < 0) return 1; - printf("Listening on port 8080\n"); - - // TODO: Use epoll or something else. - // Code from Beej's book - // Handling child processes - sa.sa_handler = SigchildHandler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - if (sigaction(SIGCHLD, &sa, NULL) == -1) - { - perror("sigaction"); - exit(1); - } - - while (1) - { - Seobeo_PHandle cli = Seobeo_Stream_Handle_Accept(srv); - if (cli == NULL) - { - continue; - } - printf("client connected from %s\n", cli->host); - - if (!fork()) - { - HandleClientRequest(cli); - exit(0); - } - Seobeo_Handle_Destroy(cli); - } - - Seobeo_Handle_Destroy(srv); - return 0; + Seobeo_Web_StartBasicHTTPServer("seobeo/pages", "8080"); }
--- a/seobeo/pages/index.html Sat Sep 27 16:23:04 2025 -0700 +++ b/seobeo/pages/index.html Mon Sep 29 16:00:44 2025 -0700 @@ -2,6 +2,7 @@ <head> </head> <body> - <h1> June </h1> + <h1> This is June park xd </h1> </body> + <script src="index.js"></script> </HTML>
--- a/seobeo/s_linux_network.c Sat Sep 27 16:23:04 2025 -0700 +++ b/seobeo/s_linux_network.c Mon Sep 29 16:00:44 2025 -0700 @@ -110,12 +110,12 @@ return p_handle; } -Seobeo_PHandle Seobeo_Stream_Handle_Accept(Seobeo_PHandle server_h) +Seobeo_PHandle Seobeo_Stream_Handle_Accept(Seobeo_PHandle p_server_handle) { struct sockaddr_storage addr; socklen_t addrlen = sizeof addr; char client_inet_addr[INET6_ADDRSTRLEN]; - int client_fd = accept(server_h->socket, + int client_fd = accept(p_server_handle->socket, (struct sockaddr*)&addr, &addrlen); inet_ntop( @@ -128,45 +128,46 @@ return NULL; } - Seobeo_PHandle h = malloc(sizeof *h); + Seobeo_PHandle p_client_handle = malloc(sizeof *p_client_handle); - h->socket = client_fd; - h->host = strdup(client_inet_addr); - h->port = NULL; + p_client_handle->socket = client_fd; + p_client_handle->host = strdup(client_inet_addr); + p_client_handle->port = NULL; - h->read_buffer_capacity = server_h->read_buffer_capacity; - h->read_buffer_len = 0; - h->read_buffer = malloc(h->read_buffer_capacity); + p_client_handle->read_buffer_capacity = p_server_handle->read_buffer_capacity; + p_client_handle->read_buffer_len = 0; + p_client_handle->read_buffer = malloc(p_client_handle->read_buffer_capacity); - h->write_buffer_capacity = server_h->write_buffer_capacity; - h->write_buffer_len = 0; - h->write_buffer = malloc(h->write_buffer_capacity); + p_client_handle->write_buffer_capacity = p_server_handle->write_buffer_capacity; + p_client_handle->write_buffer_len = 0; + p_client_handle->write_buffer = malloc(p_client_handle->write_buffer_capacity); - return h; + return p_client_handle; } -void Seobeo_Handle_Destroy(Seobeo_PHandle h) +void Seobeo_Handle_Destroy(Seobeo_PHandle p_handle) { - close(h->socket); - free(h->host); - free(h->port); - free(h->read_buffer); - free(h->write_buffer); - free(h->file); - free(h->text_copy); - free(h->file_name); - free(h); + close(p_handle->socket); + free(p_handle->host); + free(p_handle->port); + free(p_handle->read_buffer); + free(p_handle->write_buffer); + free(p_handle->file); + free(p_handle->text_copy); + free(p_handle->file_name); + free(p_handle); } -int Seobeo_Handle_Flush(Seobeo_PHandle h) +int Seobeo_Handle_Flush(Seobeo_PHandle p_handle) { - uint32 total = h->write_buffer_len; + uint32 total = p_handle->write_buffer_len; uint32 sent = 0; - while (sent < total) { + while (sent < total) + { ssize_t n = write( - h->socket, - h->write_buffer + sent, + p_handle->socket, + p_handle->write_buffer + sent, total - sent ); if (n < 0) { @@ -177,28 +178,29 @@ sent += (uint32)n; } - h->write_buffer_len = 0; + p_handle->write_buffer_len = 0; return 0; } - -int Seobeo_Handle_QueueData(Seobeo_PHandle h, const uint8_t *data, uint32_t data_size) +int Seobeo_Handle_Queue(Seobeo_PHandle p_handle, const uint8_t *data, uint32_t data_size) { - if (h->write_buffer_len + data_size > h->write_buffer_capacity) { - int rc = Seobeo_Handle_Flush(h); + if (p_handle->write_buffer_len + data_size > p_handle->write_buffer_capacity) + { + int rc = Seobeo_Handle_Flush(p_handle); if (rc < 0) return -1; if (rc > 0) return 1; } - if (data_size > h->write_buffer_capacity) + if (data_size > p_handle->write_buffer_capacity) { uint32_t offset = 0; while (offset < data_size) { - ssize_t n = write(h->socket, + ssize_t n = write(p_handle->socket, data + offset, data_size - offset); - if (n < 0) { + if (n < 0) + { if (errno == EINTR) continue; if (errno == EAGAIN) return 1; return -1; @@ -208,13 +210,55 @@ return 0; } - memcpy(h->write_buffer + h->write_buffer_len, + memcpy(p_handle->write_buffer + p_handle->write_buffer_len, data, data_size); - h->write_buffer_len += data_size; + p_handle->write_buffer_len += data_size; return 0; } +int Seobeo_Handle_Read(Seobeo_PHandle p_handle) +{ + // How many bytes we can still read into the buffer + uint32 free_space = p_handle->read_buffer_capacity - p_handle->read_buffer_len; + if (free_space == 0) + return -1; + + ssize_t n = read( + p_handle->socket, + p_handle->read_buffer + p_handle->read_buffer_len, + free_space + ); + if (n < 0) { + if (errno == EINTR) return Seobeo_Handle_Read(p_handle); + if (errno == EAGAIN) return 0; // no data available right now + return -1; // fatal error + } + if (n == 0) { + return -2; // peer closed the connection + } + + p_handle->read_buffer_len += (uint32)n; + return (int)n; // number of bytes read +} + +void Seobeo_Handle_Consume(Seobeo_PHandle p_handle, uint32 consumed) +{ + if (consumed >= p_handle->read_buffer_len) + { + p_handle->read_buffer_len = 0; + return; + } + + // Slide remaining bytes to the front + memmove( + p_handle->read_buffer, + p_handle->read_buffer + consumed, + p_handle->read_buffer_len - consumed + ); + p_handle->read_buffer_len -= consumed; +} + void *Seobeo_GetIP4OrIP6(struct sockaddr *sa) { if (sa->sa_family == AF_INET)
--- a/seobeo/seobeo.h Sat Sep 27 16:23:04 2025 -0700 +++ b/seobeo/seobeo.h Mon Sep 29 16:00:44 2025 -0700 @@ -23,6 +23,17 @@ #define INITIAL_BUFFER_CAPACITY 4096 +// HTTP STATUS CODE +#define HTTP_OK 200 +#define HTTP_CREATED 201 +#define HTTP_MOVED_PERMANENTLY 301 +#define HTTP_FOUND 302 +#define HTTP_BAD_REQUEST 400 +#define HTTP_UNAUTHORIZED 401 +#define HTTP_FORBIDDEN 403 +#define HTTP_NOT_FOUND 404 +#define HTTP_INTERNAL_ERROR 500 + typedef struct { int socket; char *host; @@ -31,7 +42,7 @@ uint8 *read_buffer; uint32 read_buffer_capacity; uint32 read_buffer_len; // current size - uint32 read_buffer_pos; // TODO: Implement this for client + uint32 read_buffer_used; // TODO: Implement this for client uint8 *write_buffer; uint32 write_buffer_capacity; @@ -49,11 +60,21 @@ // --- TCP --- // extern Seobeo_PHandle Seobeo_Stream_Handle_Create(const char *host, const char* port); -extern Seobeo_PHandle Seobeo_Stream_Handle_Accept(Seobeo_PHandle server_h); +extern Seobeo_PHandle Seobeo_Stream_Handle_Accept(Seobeo_PHandle p_server_handle); +extern int Seobeo_Stream_Handle_Read(Seobeo_PHandle p_handle); + +// --- Web --- // +extern void Seobeo_Web_GenerateResponseHeader(void *buffer, int status, const char *content_type, const int content_length); +extern void Seobeo_Web_HandleClientRequest(Seobeo_PHandle cli, Dowa_PHashMap p_html_cache); +extern int Seobeo_Web_ParseClientHeader(Seobeo_PHandle p_handle, Dowa_PHashMap map); +extern int Seobeo_Web_StartBasicHTTPServer(const char *folder_path, const char *port); // --- Helper functions --- // -extern void Seobeo_Handle_Destroy(Seobeo_PHandle h); -extern int Seobeo_Handle_Flush(Seobeo_PHandle h); -extern int Seobeo_Handle_QueueData(Seobeo_PHandle h, const uint8_t *data, uint32_t data_size); +extern void Seobeo_Handle_Destroy(Seobeo_PHandle p_handle); +extern int Seobeo_Handle_Flush(Seobeo_PHandle p_handle); +extern int Seobeo_Handle_Queue(Seobeo_PHandle p_handle, const uint8_t *data, uint32_t data_size); +extern int Seobeo_Handle_Read(Seobeo_PHandle p_handle); +extern void Seobeo_Handle_Consume(Seobeo_PHandle p_handle, uint32 consumed); + #endif