changeset 17:d97ec3ded2ae

[Seobeo] Few changes... - Fixed seobeo edge for macos - Updated so that socket creation can be used for both client and server - Started on a cutelient library for making connection to the server.
author June Park <parkjune1995@gmail.com>
date Sat, 04 Oct 2025 07:53:12 -0700
parents fb2cff495a60
children fa2b8af609d9
files cutelient/BUILD cutelient/main.c playground/hello.ts playground/main.c playground/new.txt seobeo/BUILD seobeo/main.c seobeo/os/s_linux_edge.c seobeo/os/s_macos_edge.c seobeo/pages/hello/bar.txt seobeo/pages/hello/index.html seobeo/pages/hello/index.js seobeo/pages/index.html seobeo/pages/index.js seobeo/s_linux_network.c seobeo/s_web.c seobeo/seobeo.h
diffstat 17 files changed, 222 insertions(+), 96 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cutelient/BUILD	Sat Oct 04 07:53:12 2025 -0700
@@ -0,0 +1,7 @@
+load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
+
+cc_binary(
+  name = "cutelient",
+  srcs = ["main.c"],
+  deps = ["//seobeo:seobeo"],
+)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cutelient/main.c	Sat Oct 04 07:53:12 2025 -0700
@@ -0,0 +1,7 @@
+#include "seobeo/seobeo.h"
+
+
+int main()
+{
+  Seobeo_Web_ClientGet("127.0.0.1", "6969", "/react");
+}
--- a/playground/hello.ts	Fri Oct 03 09:55:51 2025 -0700
+++ b/playground/hello.ts	Sat Oct 04 07:53:12 2025 -0700
@@ -1,4 +1,4 @@
-const JUNE = "JUNE"
+const JUNE = "JUNE";
 
 export {
   JUNE,
--- a/playground/main.c	Fri Oct 03 09:55:51 2025 -0700
+++ b/playground/main.c	Sat Oct 04 07:53:12 2025 -0700
@@ -1,32 +1,83 @@
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#define NUM_THREADS     5
+// #include <pthread.h>
+// #include <stdio.h>
+// #include <stdlib.h>
+// #define NUM_THREADS     5
+// 
+// void *PrintHello(void *threadid)
+// {
+//    long tid;
+//    tid = (long)threadid;
+//    printf("Hello World! It's me, thread #%ld!\n", tid);
+//    pthread_exit(NULL);
+// }
+// 
+// int main (int argc, char *argv[])
+// {
+//    pthread_t threads[NUM_THREADS];
+//    int rc;
+//    long t;
+//    for(t = 0; t < NUM_THREADS; t++)
+//    {
+//       printf("In main: creating thread %ld\n", t);
+//       rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
+//       if (rc)
+//       {
+//          printf("ERROR; return code from pthread_create() is %d\n", rc);
+//          exit(-1);
+//       }
+//    }
+// 
+//    /* Last thing that main() should do */
+//    pthread_exit(NULL);
+// }
 
-void *PrintHello(void *threadid)
-{
-   long tid;
-   tid = (long)threadid;
-   printf("Hello World! It's me, thread #%ld!\n", tid);
-   pthread_exit(NULL);
-}
+#include	<sys/event.h>
+#include	<err.h>
+#include	<fcntl.h>
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<string.h>
 
-int main (int argc, char *argv[])
+int main(int	argc, char **argv)
 {
-   pthread_t threads[NUM_THREADS];
-   int rc;
-   long t;
-   for(t = 0; t < NUM_THREADS; t++)
-   {
-      printf("In main: creating thread %ld\n", t);
-      rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
-      if (rc)
-      {
-         printf("ERROR; return code from pthread_create() is %d\n", rc);
-         exit(-1);
-      }
-   }
+	   struct kevent event;	   /* Event we want to monitor */
+	   struct kevent tevent;   /* Event triggered */
+	   int kq, fd, ret;
+
+	   if (argc != 2)
+	       err(EXIT_FAILURE, "Usage: %s path\n", argv[0]);
+
+	   fd =	open(argv[1], O_RDONLY);
+	   if (fd == -1)
+	       err(EXIT_FAILURE, "Failed to open '%s'",	argv[1]);
+
+	   /* Create kqueue. */
+	   kq =	kqueue();
+	   if (kq == -1)
+	       err(EXIT_FAILURE, "kqueue() failed");
+
+	   /* Initialize kevent	structure. */
+     EV_SET(&event, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR,
+       NOTE_WRITE | NOTE_ATTRIB,
+       0, NULL);
 
-   /* Last thing that main() should do */
-   pthread_exit(NULL);
+	   /* Attach event to the kqueue. */
+	   ret = kevent(kq, &event, 1, NULL, 0,	NULL);
+	   if (ret == -1)
+	       err(EXIT_FAILURE, "kevent register");
+
+	   for (;;)
+     {
+	       /* Sleep	until something	happens. */
+	       ret = kevent(kq,	NULL, 0, &tevent, 1, NULL);
+	       if (ret == -1) {
+		   err(EXIT_FAILURE, "kevent wait");
+	       } else if (ret >	0) {
+		   if (tevent.flags & EV_ERROR)
+		       errx(EXIT_FAILURE, "Event error:	%s", strerror(event.data));
+		   else
+		       printf("Something was written in	'%s'\n", argv[1]);
+	       }
+	   }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/playground/new.txt	Sat Oct 04 07:53:12 2025 -0700
@@ -0,0 +1,1 @@
+hello good sir
--- a/seobeo/BUILD	Fri Oct 03 09:55:51 2025 -0700
+++ b/seobeo/BUILD	Sat Oct 04 07:53:12 2025 -0700
@@ -2,11 +2,6 @@
 load("@rules_cc//cc:cc_library.bzl", "cc_library")
 
 filegroup(
-  name = "pages_files",
-  srcs = glob(["pages/**"]),
-)
-
-filegroup(
   name = "seobeo_hdrs",
   srcs = [
     "seobeo.h",
@@ -15,15 +10,8 @@
   visibility = ["//visibility:public"],
 )
 
-cc_binary(
-  name = "seobeo_example",
-  srcs = ["main.c"],
-  deps = [":seobeo"],
-  data = [":pages_files"],
-)
-
 alias(
-  name   = "seobeo",
+  name = "seobeo",
   actual = select({
     "//config:macos":  ":seobeo_macos",
     "//config:linux":  ":seobeo_linux",
--- a/seobeo/main.c	Fri Oct 03 09:55:51 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-/*
-** server.c -- a stream socket server demo
-*/
-
-#include "seobeo/seobeo.h"
-
-
-int main(void)
-{
-  Seobeo_Web_StartBasicHTTPServer("seobeo/pages", "8080", SEOBEO_MODE_FORK, 2);
-}
--- a/seobeo/os/s_linux_edge.c	Fri Oct 03 09:55:51 2025 -0700
+++ b/seobeo/os/s_linux_edge.c	Sat Oct 04 07:53:12 2025 -0700
@@ -39,7 +39,7 @@
 {
   int epfd = epoll_create1(0);
   struct epoll_event ev = {
-    .events   = EPOLLIN,
+    .events   = EPOLLIN | EPOLLONESHOT,
     .data.ptr = p_server_handle
   };
   epoll_ctl(epfd, EPOLL_CTL_ADD,
@@ -50,9 +50,9 @@
   pthread_attr_setstacksize(&attr, 100 * 1024 * 1024); // 100 MB
 
   pthread_t  threads[thread_count];
-  WorkerArgs args = { p_server_handle, p_html_cache, epfd };
   for (int i = 0; i < thread_count; i++)
   {
+    WorkerArgs args = { p_server_handle, p_html_cache, epfd };
     pthread_create(&threads[i], NULL,
                    Seobeo_Web_Edge_Worker, &args);
   }
--- a/seobeo/os/s_macos_edge.c	Fri Oct 03 09:55:51 2025 -0700
+++ b/seobeo/os/s_macos_edge.c	Sat Oct 04 07:53:12 2025 -0700
@@ -60,10 +60,9 @@
   pthread_t  threads[thread_count];
   for (int i = 0; i < thread_count; i++)
   {
-    WorkerArgs *args = malloc(sizeof(WorkerArgs));
-    *args = (WorkerArgs){ p_server_handle, p_html_cache, kq };
+    WorkerArgs args = { p_server_handle, p_html_cache, kq };
     pthread_create(&threads[i], NULL,
-                   Seobeo_Web_Edge_Worker, args);
+                   Seobeo_Web_Edge_Worker, &args);
   }
   for (int i = 0; i < thread_count; i++)
   {
--- a/seobeo/pages/hello/bar.txt	Fri Oct 03 09:55:51 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-hello
--- a/seobeo/pages/hello/index.html	Fri Oct 03 09:55:51 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-<HTML>
-  <head>
-    <script src="index.js"></script>
-  </head>
-  <body>
-    <h1> Hello </h1>
-  </body>
-</HTML>
--- a/seobeo/pages/hello/index.js	Fri Oct 03 09:55:51 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-console.log("Hello 2");
--- a/seobeo/pages/index.html	Fri Oct 03 09:55:51 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-<HTML>
-  <head>
-  </head>
-  <body>
-    <h1> This is June park xd </h1>
-  </body>
-  <script src="index.js"></script>
-</HTML>
--- a/seobeo/pages/index.js	Fri Oct 03 09:55:51 2025 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-console.log("hello");
--- a/seobeo/s_linux_network.c	Fri Oct 03 09:55:51 2025 -0700
+++ b/seobeo/s_linux_network.c	Sat Oct 04 07:53:12 2025 -0700
@@ -1,6 +1,6 @@
 #include "seobeo/seobeo.h"
 
-int Seobeo_CreateSocket(int32 stream, const char *host,  const char* port, int32 backlog)
+int Seobeo_CreateSocket(int32 stream, const char *host,  const char* port)
 {
   struct addrinfo hints = {0}, *server_infos, *free_server_info;
   int32 sock_fd, yes = 1;  // Need this for setsockopt 
@@ -41,24 +41,34 @@
        continue;
      }
 
-     if (bind(sock_fd, free_server_info->ai_addr, free_server_info->ai_addrlen) == -1)
+     if (host != NULL)
      {
-       close(sock_fd);
-       perror("setsockopt");
-       continue;
-     }
+       if (connect(sock_fd, free_server_info->ai_addr, free_server_info->ai_addrlen) == -1)
+       {
+         perror("connect");
+         continue;
+       }
 
-     // UDP should be non blocking
-     if(!stream)
+     }
+     else
      {
-       if (fcntl(sock_fd, F_SETFL, O_NONBLOCK) != 0)
+       if (bind(sock_fd, free_server_info->ai_addr, free_server_info->ai_addrlen) == -1)
        {
-         close(sock_fd);
          perror("v_network: Couldn't make socket non-blocking\n");
-         return -1;
+         continue;
+       }
+
+       // UDP should be non blocking
+       if(!stream)
+       {
+         if (fcntl(sock_fd, F_SETFL, O_NONBLOCK) != 0)
+         {
+           close(sock_fd);
+           perror("v_network: Couldn't make socket non-blocking\n");
+           return -1;
+         }
        }
      }
-
      // binded to a open server infos;
      break;
   }
@@ -72,10 +82,9 @@
     return -1;
   }
 
-  // TCP listen
-  if(stream)
+  if (host == NULL)
   {
-    if (listen(sock_fd, backlog) != 0)
+    if (listen(sock_fd, 16) != 0)
     {
       perror("listen");
       close(sock_fd);
@@ -91,7 +100,11 @@
   Seobeo_PHandle p_handle;
   p_handle = malloc(sizeof(*p_handle));
 
-  p_handle->socket = Seobeo_CreateSocket(1, host,  port, 10); // socke fd
+  p_handle->socket = Seobeo_CreateSocket(1, host,  port); // socke fd
+  if (!p_handle->socket)
+  {
+    perror("Seobeo_CreateSocket");
+  }
   p_handle->host = host != NULL ? strdup(host) : "localhost";
   p_handle->port = strdup(port);
 
@@ -192,7 +205,7 @@
   return 0;
 }
 
-int Seobeo_Handle_Queue(Seobeo_PHandle p_handle, const uint8_t *data, uint32_t data_size)
+int Seobeo_Handle_Queue(Seobeo_PHandle p_handle, const uint8 *data, uint32 data_size)
 {
   if (p_handle->write_buffer_len + data_size > p_handle->write_buffer_capacity)
   {
@@ -203,7 +216,7 @@
 
   if (data_size > p_handle->write_buffer_capacity)
   {
-    uint32_t offset = 0;
+    uint32 offset = 0;
     while (offset < data_size)
     {
       ssize_t n = write(p_handle->socket,
@@ -215,7 +228,7 @@
         if (errno == EAGAIN) return 1;
         return -1;
       }
-      offset += (uint32_t)n;
+      offset += (uint32)n;
     }
     return 0;
   }
--- a/seobeo/s_web.c	Fri Oct 03 09:55:51 2025 -0700
+++ b/seobeo/s_web.c	Sat Oct 04 07:53:12 2025 -0700
@@ -1,5 +1,18 @@
 #include "seobeo/seobeo.h"
 
+int Seobeo_Web_GenerateRequestHeader(void *buffer, const char *host, 
+                                     const char *path) 
+{
+  return sprintf(
+    buffer,
+    "GET %s HTTP/1.1\r\n"
+    "Host: %s\r\n"
+    "Connection: close\r\n"
+    "\r\n",
+    path, host
+  );
+}
+
 void Seobeo_Web_GenerateResponseHeader(void *buffer, int status,
                                        const char *content_type, const int content_length) 
 {
@@ -58,6 +71,8 @@
     goto clean_up;
   }
 
+  Dowa_HashMap_Print(p_req_map);
+
   const char *path = (const char*)Dowa_HashMap_Get(p_req_map, "Path");
 
   char *file_path = Dowa_Arena_Allocate(p_response_arena, (size_t)512);
@@ -306,3 +321,76 @@
 
   return -1;
 }
+
+
+int Seobeo_Web_ClientGet(const char *host,
+                         const char *port,
+                         const char *path)
+{
+  Seobeo_PHandle h = Seobeo_Stream_Handle_Create(host, port);
+  if (!h || h->socket < 0)
+  {
+    if (h) Seobeo_Handle_Destroy(h);
+    return -1;
+  }
+
+  Dowa_PArena p_request_arena = Dowa_Arena_Create(1 * 1024 * 1024);
+  if (!p_request_arena)
+  {
+    perror("Dowa_Arena_Create");
+    return -1;
+  }
+  void *p_request_header = Dowa_Arena_Allocate(p_request_arena, 4096);
+  if (!p_request_header)
+  {
+    perror("Dowa_Arena_Allocate");
+    return -1;
+  }
+
+  int request_len = Seobeo_Web_GenerateRequestHeader(p_request_header, host, path);
+  printf("request: %s\n", (char *)p_request_header);
+  Seobeo_Handle_Queue(h, (uint8 *)p_request_header, (uint32)request_len);
+
+  if (Seobeo_Handle_Flush(h) < 0)
+  {
+    perror("Seobeo_Handle_Flush");
+    Seobeo_Handle_Destroy(h);
+    return -1;
+  }
+
+  size_t cap = 1024*8, used = 0;
+  char *p_request_body = Dowa_Arena_Allocate(p_request_arena, cap);
+  if (!p_request_body) { Seobeo_Handle_Destroy(h); return -1; }
+
+  while (1) {
+    int n = Seobeo_Handle_Read(h);
+    if (n > 0)
+    {
+      memcpy(p_request_body + used, h->read_buffer, h->read_buffer_len);
+      used += h->read_buffer_len;
+      Seobeo_Handle_Consume(h, (uint32)h->read_buffer_len);
+    }
+    else if (n == 0)
+    {
+      // non-blocking mode and no data right now → keep looping or break?
+      // For a simple blocking client, you could block instead:
+      continue;
+    }
+    else if (n == -2)
+    {
+      // peer closed; we’ve got everything
+      break;
+    }
+    else
+    {
+      Dowa_Arena_Free(p_request_arena);
+      Seobeo_Handle_Destroy(h);
+      return -1;
+    }
+  }
+
+  printf("%s\n\n", p_request_body);
+  Dowa_Arena_Free(p_request_arena);
+  Seobeo_Handle_Destroy(h);
+  return 0;
+}
--- a/seobeo/seobeo.h	Fri Oct 03 09:55:51 2025 -0700
+++ b/seobeo/seobeo.h	Sat Oct 04 07:53:12 2025 -0700
@@ -70,7 +70,7 @@
 } Seobeo_ServerMode;
 
 // --- Socket, IP related --- //
-extern int            Seobeo_CreateSocket(int32 stream, const char *host,  const char* port, int32 backlog);
+extern int            Seobeo_CreateSocket(int32 stream, const char *host,  const char* port);
 extern void           *Seobeo_GetIP4OrIP6(struct sockaddr *sa);
 
 // --- TCP --- //
@@ -85,6 +85,8 @@
 extern int            Seobeo_Web_StartBasicHTTPServer(const char *folder_path, const char *port, Seobeo_ServerMode mode, int thread_count);
 extern void           *Seobeo_Web_Edge_Worker(void *vargs); // Maybe not web only...
 extern void           Seobeo_Web_Edge(Seobeo_PHandle p_server_handle, int thread_count, Dowa_PHashMap p_html_cache);
+extern int            Seobeo_Web_ClientGet(const char *host, const char *port, const char *path);
+
 
 // --- Helper functions --- //
 extern void           Seobeo_Handle_Destroy(Seobeo_PHandle p_handle);