changeset 36:84672efec192

[Zenbu] WIP fixing issues regarding to using edge only. I think there is a problem where socket closes before sending back the info.
author MrJuneJune <me@mrjunejune.com>
date Sun, 09 Nov 2025 06:25:16 -0800
parents 33b1caf051cd
children fb9bcd3145cb
files debugger.sh dowa/d_memory.c dowa/dowa.h mrjunejune/main.c seobeo/os/s_linux_edge.c seobeo/s_linux_network.c seobeo/s_web.c seobeo/seobeo.h seobeo/seobeo_internal.h
diffstat 9 files changed, 241 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/debugger.sh	Sun Nov 09 06:25:16 2025 -0800
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+bazel build //mrjunejune:mrjunejune_server -c dbg && gdb bazel-bin/mrjunejune/mrjunejune_server
--- a/dowa/d_memory.c	Thu Oct 30 09:53:22 2025 -0700
+++ b/dowa/d_memory.c	Sun Nov 09 06:25:16 2025 -0800
@@ -31,8 +31,8 @@
   if (!p_arena) return;
 
   if (p_arena->buffer)
-    free(p_arena->buffer);
-  free(p_arena);
+    Dowa_Free(p_arena->buffer);
+  Dowa_Free(p_arena);
 }
 
 void *Dowa_Arena_Copy(Dowa_PArena p_arena, const void *src, size_t size)
@@ -60,7 +60,7 @@
   p_hash_map->entries = calloc(capacity, sizeof(*p_hash_map->entries));
   if (p_hash_map->entries == NULL)
   {
-    free(p_hash_map);
+    Dowa_Free(p_hash_map);
     return NULL;
   }
   p_hash_map->capacity = capacity;
@@ -87,7 +87,7 @@
   memset(p_hash_map->entries, 0, capacity * sizeof *p_hash_map->entries);
   if (p_hash_map->entries == NULL)
   {
-    free(p_hash_map);
+    Dowa_Free(p_hash_map);
     return NULL;
   }
   p_hash_map->capacity = capacity;
@@ -116,15 +116,15 @@
         entry = p_hash_map->entries[idx];
         if (entry)
         {
-          free(entry->key);
-          free(entry->buffer);
-          free(entry);
+          Dowa_Free(entry->key);
+          Dowa_Free(entry->buffer);
+          Dowa_Free(entry);
         }
       }
     }
-    free(p_hash_map->entries);
+    Dowa_Free(p_hash_map->entries);
   }
-  free(p_hash_map);
+  Dowa_Free(p_hash_map);
 }
 
 int32 Dowa_HashMap_Get_Position(Dowa_PHashMap p_hash_map, const char *key)
@@ -169,17 +169,29 @@
   {
     if (strcmp(entry->key, key) == 0)
     {
-      if (!p_hash_map->p_arena && entry->buffer)
-        free(entry->buffer);
-      entry->buffer = value;
-      entry->capacity = value_size;
-      entry->type = type;
-      return 0; 
+      // Fails if it the key exists...
+      return -1; 
     }
-    prev = entry;
-    entry = entry->next;
   }
 
+  // Overriding doesn't really make sense? when copying over
+  // as we need to free it.
+  //
+  //while (entry)
+  //{
+  //  if (strcmp(entry->key, key) == 0)
+  //  {
+  //    if (!p_hash_map->p_arena && entry->buffer)
+  //      Dowa_Free(entry->buffer);
+  //    entry->buffer = value;
+  //    entry->capacity = value_size;
+  //    entry->type = type;
+  //    return 0; 
+  //  }
+  //  prev = entry;
+  //  entry = entry->next;
+  //}
+
   // New Key 
   entry = p_hash_map->p_arena ? 
     Dowa_Arena_Allocate(p_hash_map->p_arena, sizeof(Dowa_HashEntry)) :
@@ -217,7 +229,7 @@
     if (strcmp(entry->key, key) == 0)
     {
       if (!p_hash_map->p_arena && entry->buffer)
-        free(entry->buffer);
+        Dowa_Free(entry->buffer);
 
       entry->buffer = p_hash_map->p_arena ?
         Dowa_Arena_Allocate(p_hash_map->p_arena, value_size) :
@@ -274,9 +286,9 @@
   Dowa_PHashEntry entry = p_hash_map->entries[idx];
   if (entry && !(p_hash_map->p_arena))
   {
-    free(entry->key);
-    free(entry->buffer);
-    free(entry);
+    Dowa_Free(entry->key);
+    Dowa_Free(entry->buffer);
+    Dowa_Free(entry);
   }
   p_hash_map->entries[idx] = NULL;
   if (p_hash_map->current_capacity > 0)
@@ -368,14 +380,14 @@
       if (fread(buf, 1, size, f) != size)
       {
         perror("fread");
-        if (!p_hash_map->p_arena) free(buf);
+        if (!p_hash_map->p_arena) Dowa_Free(buf);
         fclose(f);
         continue;
       }
       fclose(f);
 
       Dowa_HashMap_Push_Value_With_Type(p_hash_map, entry->d_name, buf, size, DOWA_HASH_MAP_TYPE_STRING);
-      free(buf);  // Dowa_HashMap_PushValue made its own copy
+      Dowa_Free(buf);  // Dowa_HashMap_PushValue made its own copy
     }
     else if (S_ISDIR(st.st_mode))
     {
--- a/dowa/dowa.h	Thu Oct 30 09:53:22 2025 -0700
+++ b/dowa/dowa.h	Sun Nov 09 06:25:16 2025 -0800
@@ -17,6 +17,13 @@
 #define TRUE  1
 #define FALSE 0
 
+#define Dowa_Free(p) do { \
+  if (p) {                \
+    free(p);              \
+    (p) = NULL;           \
+  }                       \
+} while (0)
+
 // Fixed-width integer types
 typedef unsigned int   uint32;   // 32-bit unsigned integer
 typedef int            int32;    // 32-bit signed integer
--- a/mrjunejune/main.c	Thu Oct 30 09:53:22 2025 -0700
+++ b/mrjunejune/main.c	Sun Nov 09 06:25:16 2025 -0800
@@ -11,6 +11,12 @@
 
 #include "seobeo/seobeo.h"
 
+volatile sig_atomic_t stop_server = 0;
+
+void handle_sigint(int sig) {
+  printf("Failed\n");
+  stop_server = 1;
+}
 
 int main(void)
 {
--- a/seobeo/os/s_linux_edge.c	Thu Oct 30 09:53:22 2025 -0700
+++ b/seobeo/os/s_linux_edge.c	Sun Nov 09 06:25:16 2025 -0800
@@ -2,72 +2,163 @@
 #include "seobeo/seobeo.h"
 
 
-void  *Seobeo_Web_Edge_Worker(void *vargs)
-{
+void *Seobeo_Web_Edge_Worker(void *vargs) {
   WorkerArgs *args = vargs;
-  uint32 max_events = 64;
+  const int max_events = 64;
   struct epoll_event events[max_events];
-  while (1)
-  {
+
+  while (1) {
     int n = epoll_wait(args->evfd, events, max_events, -1);
-    if (n < 0) continue;
+    if (n < 0) {
+      perror("epoll_wait");
+      continue;
+    }
+
+    for (int i = 0; i < n; i++) {
+      Seobeo_PHandle phandle = events[i].data.ptr;
 
-    for (int i = 0; i < n; i++)
-    {
-      Seobeo_PHandle socket_fd = events[i].data.ptr;
-      // when server....
-      if (socket_fd == args->srv)
-      {
-        Seobeo_PHandle cli =
-          Seobeo_Stream_Handle_Server_Accept(socket_fd);
-        if (!cli) continue;
-
+      if (phandle == args->srv) {
+        while (1) {
+          Seobeo_PHandle p_cli_handle = Seobeo_Stream_Handle_Server_Accept(args->srv);
+          if (!p_cli_handle) break;
 
-        struct epoll_event client_ev = {
-          .events = EPOLLIN | EPOLLET,  
-          .data.ptr = cli
-        };
-        epoll_ctl(args->evfd, EPOLL_CTL_ADD,
-                  cli->socket, &client_ev);
-      }
-      // when client....
-      else
-      {
-        Seobeo_Web_HandleClientRequest(socket_fd, args->cache); // This frees
+          struct epoll_event client_ev = {
+            .events = EPOLLIN | EPOLLET,
+            .data.ptr = p_cli_handle
+          };
+          if (epoll_ctl(args->evfd, EPOLL_CTL_ADD, p_cli_handle->socket, &client_ev) < 0)
+          {
+            perror("epoll_ctl ADD client");
+            Seobeo_Handle_Destroy(p_cli_handle);
+          }
+        }
+      } else {
+        Seobeo_Web_HandleClientRequest(phandle, args->cache);
+        epoll_ctl(args->evfd, EPOLL_CTL_DEL, phandle->socket, NULL);
+        Seobeo_Handle_Destroy(phandle);
       }
     }
   }
+
   return NULL;
 }
 
-void  Seobeo_Web_Edge(
+void Seobeo_Web_Edge(
     Seobeo_PHandle p_server_handle,
-    int            thread_count,
-    Dowa_PHashMap   p_html_cache)
-{
+    int thread_count,
+    Dowa_PHashMap p_html_cache) {
+
   int epfd = epoll_create1(0);
+  if (epfd < 0) {
+    perror("epoll_create1");
+    return;
+  }
+
   struct epoll_event ev = {
-    .events   = EPOLLIN,
+    .events = EPOLLIN | EPOLLET,
     .data.ptr = p_server_handle
   };
-  epoll_ctl(epfd, EPOLL_CTL_ADD,
-            p_server_handle->socket, &ev);
+  if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_server_handle->socket, &ev) < 0) {
+    perror("epoll_ctl ADD server");
+    close(epfd);
+    return;
+  }
 
   pthread_attr_t attr;
   pthread_attr_init(&attr);
   pthread_attr_setstacksize(&attr, 5 * 1024 * 1024); // 5 MB
 
-  pthread_t  threads[thread_count];
-  for (int i = 0; i < thread_count; i++)
-  {
+  for (int i = 0; i < thread_count; i++) {
     WorkerArgs *args = malloc(sizeof(WorkerArgs));
     *args = (WorkerArgs){ p_server_handle, p_html_cache, epfd };
 
-    pthread_create(&threads[i], NULL, Seobeo_Web_Edge_Worker, args);
+    pthread_t tid;
+    pthread_create(&tid, &attr, Seobeo_Web_Edge_Worker, args);
+    pthread_detach(tid);
   }
-  for (int i = 0; i < thread_count; i++)
+
+  while (1) pause();
+}
+
+
+void Seobeo_Web_Edge_2(Seobeo_PHandle p_handle_server, Dowa_PHashMap cache) {
+  const int MAX_EVENTS = 1024;
+  struct epoll_event events[MAX_EVENTS];
+  char keybuf[32];
+
+  int epfd = epoll_create1(0);
+  if (epfd < 0)
+  {
+    perror("epoll_create1");
+    return;
+  }
+
+  struct epoll_event ev = {
+    .events = EPOLLIN | EPOLLET,
+    .data.fd = p_handle_server->socket
+  };
+  if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_handle_server->socket, &ev) < 0)
   {
-    pthread_join(threads[i], NULL);
+    perror("epoll_ctl ADD server");
+    close(epfd);
+    return;
   }
-  return;
+
+  Dowa_PHashMap handles = Dowa_HashMap_Create(1024);
+  snprintf(keybuf, sizeof(keybuf), "%d", p_handle_server->socket);
+  Dowa_HashMap_Push_Value(handles, keybuf, p_handle_server, sizeof(p_handle_server));
+
+  while (1) {
+    int n = epoll_wait(epfd, events, MAX_EVENTS, -1);
+    if (n < 0)
+    {
+      if (errno == EINTR) continue;
+      perror("epoll_wait");
+      break;
+    }
+
+    for (int i = 0; i < n; i++)
+    {
+      int fd = events[i].data.fd;
+
+      if (fd == p_handle_server->socket)
+      {
+        while (1)
+        {
+          Seobeo_PHandle p_handle_client = Seobeo_Stream_Handle_Server_Accept(p_handle_server);
+          if (!p_handle_client) break;
+
+          struct epoll_event client_ev = {
+            .events = EPOLLIN | EPOLLET,
+            .data.fd = p_handle_client->socket
+          };
+          if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_handle_client->socket, &client_ev) < 0)
+          {
+            perror("epoll_ctl ADD client");
+            continue;
+          }
+
+          snprintf(keybuf, sizeof(keybuf), "%d", p_handle_client->socket);
+          if (p_handle_client)
+              Dowa_HashMap_Push_Value_With_Type_NoCopy(handles, keybuf, p_handle_client,
+                                                       sizeof(p_handle_client), DOWA_HASH_MAP_TYPE_HASHMAP);
+        }
+        continue;
+      }
+
+      snprintf(keybuf, sizeof(keybuf), "%d", fd);
+      Seobeo_PHandle p_handle_client = Dowa_HashMap_Get(handles, keybuf);
+      if (!p_handle_client)
+      {
+        // might happen if client closed between event and lookup
+        epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
+        continue;
+      }
+
+      Seobeo_Web_HandleClientRequest(p_handle_client, cache);
+    }
+  }
+
+  close(epfd);
 }
+
--- a/seobeo/s_linux_network.c	Thu Oct 30 09:53:22 2025 -0700
+++ b/seobeo/s_linux_network.c	Sun Nov 09 06:25:16 2025 -0800
@@ -37,9 +37,13 @@
   }
 
   if (listen(socket_fd, 16) != 0)
-  { perror("listen"); close(socket_fd); return NULL; }
+  { 
+    printf("Closing: %d", socket_fd);
+    perror("listen"); close(socket_fd); return NULL; 
+  }
 
-	if(fcntl(socket_fd, F_SETFL, O_NONBLOCK) != 0) { perror("fcntl"); return NULL; }
+  int flags = fcntl(socket_fd, F_GETFL, 0);
+	if(fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK) != 0) { perror("fcntl"); return NULL; }
   freeaddrinfo(server_infos);
 
   p_handle = malloc(sizeof(*p_handle));
@@ -62,9 +66,6 @@
   p_handle->write_buffer_capacity = INITIAL_BUFFER_CAPACITY;
   p_handle->write_buffer_len = 0;
 
-  p_handle->file = NULL;
-  p_handle->text_copy = NULL;
-  p_handle->file_name = NULL;
   p_handle->destroyed = false;
 
   return p_handle;
@@ -135,9 +136,6 @@
   p_handle->write_buffer_capacity = INITIAL_BUFFER_CAPACITY;
   p_handle->write_buffer_len = 0;
 
-  p_handle->file = NULL;
-  p_handle->text_copy = NULL;
-  p_handle->file_name = NULL;
   p_handle->destroyed = false;
 
   return p_handle;
@@ -194,14 +192,14 @@
   if (!p_handle) return;
 
   bool expected = false;
+  // Need to check
   if (!atomic_compare_exchange_strong(&p_handle->destroyed, &expected, true))
   {
-    // Already destroyed by another thread
     return;
   }
 
-  if (p_handle->host) free(p_handle->host);
-  if (p_handle->port) free(p_handle->port);
+  if (p_handle->host) Dowa_Free(p_handle->host);
+  if (p_handle->port) Dowa_Free(p_handle->port);
 
   if (p_handle->ssl)
   {
@@ -216,15 +214,15 @@
     p_handle->ssl_ctx = NULL;
   }
 
-  if (p_handle->socket) close(p_handle->socket);
-
-  if (p_handle->read_buffer) free(p_handle->read_buffer);
-  if (p_handle->write_buffer) free(p_handle->write_buffer);
+  if (p_handle->socket) {
+    printf("Closing: %d", p_handle->socket);
+    close(p_handle->socket);
+  }
 
-  if (p_handle->text_copy) free(p_handle->text_copy);
-  if (p_handle->file_name) free(p_handle->file_name);
+  if (p_handle->read_buffer) Dowa_Free(p_handle->read_buffer);
+  if (p_handle->write_buffer) Dowa_Free(p_handle->write_buffer);
 
-  free(p_handle);
+  Dowa_Free(p_handle);
 }
 
 
@@ -254,6 +252,7 @@
       sent += (uint32)n;
     }else
     {
+      printf("socket: %d\n", p_handle->socket);
       ssize_t n = write(
         p_handle->socket,
         p_handle->write_buffer + sent,
@@ -315,12 +314,28 @@
     return 0;
   }
 
+  if (!p_handle) {
+    printf("[ERROR] p_handle is NULL before memcpy\n");
+    return;
+  }
+  
+  if (!p_handle->write_buffer) {
+    printf("[ERROR] p_handle->write_buffer is NULL (len=%zu, size=%zu)\n",
+            p_handle->write_buffer_len, data_size);
+    return;
+  }
+  
+  printf("[DEBUG] memcpy -> dest=%p (write_buffer=%p + offset=%zu), src=%p, size=%zu\n",
+          p_handle->write_buffer + p_handle->write_buffer_len,
+          p_handle->write_buffer,
+          p_handle->write_buffer_len,
+          data,
+          data_size); 
+
   memcpy(p_handle->write_buffer + p_handle->write_buffer_len,
          data,
          data_size);
   p_handle->write_buffer_len += data_size;
-  // DEBUG
-  printf("\nheader data_size: %d\n\n", data_size);
   return 0;
 }
 
--- a/seobeo/s_web.c	Thu Oct 30 09:53:22 2025 -0700
+++ b/seobeo/s_web.c	Sun Nov 09 06:25:16 2025 -0800
@@ -58,6 +58,7 @@
 void Seobeo_Web_HandleClientRequest(Seobeo_PHandle p_cli_handle,
                                     Dowa_PHashMap p_html_cache)
 {
+  printf("p_cli_handle: %p", p_cli_handle);
   Dowa_PHashEntry entry = NULL;
   Dowa_PHashMap p_current = p_html_cache;
   char *slash;
@@ -80,9 +81,10 @@
                         (uint32)strlen(p_response_header));
     Seobeo_Handle_Flush(p_cli_handle);
     goto clean_up;
+    return;
   }
 
-  Dowa_HashMap_Print(p_req_map);
+  // Dowa_HashMap_Print(p_req_map);
 
   // Extract method (GET, POST, etc.)
   const char *method = (const char*)Dowa_HashMap_Get(p_req_map, "HTTP_Method");
@@ -249,10 +251,12 @@
   goto clean_up;
 
 clean_up:
-  if (p_cli_handle)
-    Seobeo_Handle_Destroy(p_cli_handle);
-  if (p_response_arena)
-    Dowa_Arena_Destroy(p_response_arena);
+  printf("clean up\n\n");
+  return;
+//  if (p_cli_handle)
+//    Seobeo_Handle_Destroy(p_cli_handle);
+//  if (p_response_arena)
+//    Dowa_Arena_Destroy(p_response_arena);
 }
 
 
@@ -400,12 +404,12 @@
 
       Dowa_HashMap_Push_Value_With_Type(map, key, val, value_len + 1, DOWA_HASH_MAP_TYPE_STRING);
 
-      printf("Capacity: %d, Length: %d ", (int)map->p_arena->capacity, (int)map->p_arena->offset);
-      printf("value_len: %d, key: %s value %s position: %d\n\n", (int)value_len + 1, key, val, Dowa_HashMap_Get_Position(map, key));
-      printf("Method: %s Position: %d Pointer %p\n\n", Dowa_HashMap_Get(map, "HTTP_Method"), Dowa_HashMap_Get_Position(map, "HTTP_Method"), map);
+      // printf("Capacity: %d, Length: %d ", (int)map->p_arena->capacity, (int)map->p_arena->offset);
+      // printf("value_len: %d, key: %s value %s position: %d\n\n", (int)value_len + 1, key, val, Dowa_HashMap_Get_Position(map, key));
+      // printf("Method: %s Position: %d Pointer %p\n\n", Dowa_HashMap_Get(map, "HTTP_Method"), Dowa_HashMap_Get_Position(map, "HTTP_Method"), map);
 
-      free(key);
-      free(val);
+      Dowa_Free(key);
+      Dowa_Free(val);
     }
 
     line = next + 2;
@@ -430,7 +434,7 @@
     body[body_len] = '\0';
 
     Dowa_HashMap_Push_Value(map, "Body", body, body_len + 1);
-    free(body);
+    Dowa_Free(body);
 
     Seobeo_Handle_Consume(p_handle, (uint32)body_len);
   }
@@ -483,13 +487,13 @@
 
     while (1)
     {
-      Seobeo_PHandle cli =
+      Seobeo_PHandle p_cli_handle =
         Seobeo_Stream_Handle_Server_Accept(p_server_handle);
-      if (!cli) continue;
+      if (!p_cli_handle) continue;
 
       if (fork() == 0)
       {
-        Seobeo_Web_HandleClientRequest(cli,
+        Seobeo_Web_HandleClientRequest(p_cli_handle,
                                        p_html_cache);
         _exit(0);
       }
@@ -499,7 +503,8 @@
   if (mode == SEOBEO_MODE_EDGE)
   {
     printf("EDGE MODE\n");
-    Seobeo_Web_Edge(p_server_handle, thread_count, p_html_cache);
+    Seobeo_Web_Edge_2(p_server_handle, p_html_cache);
+    // Seobeo_Web_Edge(p_server_handle, thread_count, p_html_cache);
   }
 
   return -1;
--- a/seobeo/seobeo.h	Thu Oct 30 09:53:22 2025 -0700
+++ b/seobeo/seobeo.h	Sun Nov 09 06:25:16 2025 -0800
@@ -40,6 +40,8 @@
 #define HTTP_NOT_FOUND 404
 #define HTTP_INTERNAL_ERROR 500
 
+extern volatile sig_atomic_t stop_server;
+
 // --- TCP --- //
 // --- Generate a Server Handle. ---//
 extern Seobeo_PHandle Seobeo_Stream_Handle_Server_Create(const char *host,  const char* port);
--- a/seobeo/seobeo_internal.h	Thu Oct 30 09:53:22 2025 -0700
+++ b/seobeo/seobeo_internal.h	Sun Nov 09 06:25:16 2025 -0800
@@ -66,6 +66,7 @@
 // --- Serving using Edge --- //
 extern void          *Seobeo_Web_Edge_Worker(void *vargs); 
 extern void           Seobeo_Web_Edge(Seobeo_PHandle p_server_handle, int thread_count, Dowa_PHashMap p_html_cache);
+extern void           Seobeo_Web_Edge_2(Seobeo_PHandle p_server_handle, Dowa_PHashMap p_html_cache);
 
 #endif