diff seobeo/s_linux_network.c @ 4:0b3b4f5887bb

[Seobeo] Updated so that it create socket for both server and clients.
author June Park <parkjune1995@gmail.com>
date Fri, 26 Sep 2025 15:14:46 -0700
parents 2758f5527d2b
children 1e61008b9980
line wrap: on
line diff
--- a/seobeo/s_linux_network.c	Wed Sep 24 18:49:09 2025 -0700
+++ b/seobeo/s_linux_network.c	Fri Sep 26 15:14:46 2025 -0700
@@ -1,29 +1,16 @@
 #include "seobeo/seobeo.h"
 
-int Seobeo_CreateSocket(int32 stream, char* port, int32 backlog)
+int Seobeo_CreateSocket(int32 stream, const char *host,  const char* port, int32 backlog)
 {
-  int32 sock_fd;
-  struct addrinfo hints, *server_infos, *free_server_info;
-  int32 yes = 1; // Need this for setsockopt 
+  struct addrinfo hints = {0}, *server_infos, *free_server_info;
+  int32 sock_fd, yes = 1;  // Need this for setsockopt 
 
-  memset(&hints, 0, sizeof(hints));
-  if (stream)
-  {
-    hints.ai_family = AF_INET;
-    hints.ai_socktype = SOCK_STREAM;
-    hints.ai_protocol = IPPROTO_TCP; 
-    hints.ai_flags = AI_PASSIVE;
-  }
-  else
-  {
-    hints.ai_family = AF_INET;
-    hints.ai_socktype = SOCK_DGRAM;
-    hints.ai_protocol = IPPROTO_UDP; 
-    hints.ai_flags = AI_PASSIVE;
-  }
+  hints.ai_family   = AF_INET;
+  hints.ai_socktype = stream ? SOCK_STREAM   : SOCK_DGRAM;
+  hints.ai_protocol = stream ? IPPROTO_TCP   : IPPROTO_UDP;
+  hints.ai_flags    = stream ? AI_PASSIVE    : 0;
 
-
-  if (getaddrinfo(NULL, port, &hints, &server_infos) != 0)
+  if (getaddrinfo(host, port, &hints, &server_infos) != 0)
   {
     perror("getaddrinfo");
     return -1;
@@ -62,14 +49,14 @@
      }
 
      // UDP should be non blocking
-	   if(!stream)
+     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;
-	     }
+         perror("v_network: Couldn't make socket non-blocking\n");
+         return -1;
+       }
      }
 
      // binded to a open server infos;
@@ -86,11 +73,12 @@
   }
 
   // TCP listen
-	if(stream)
+  if(stream)
   {
     if (listen(sock_fd, backlog) != 0)
     {
       perror("listen");
+      close(sock_fd);
       return -1;
     }
   }
@@ -98,43 +86,133 @@
   return sock_fd;
 }
 
-
-void Seobeo_ListenClient(int sock_fd, void (*handle_client)(int))
+Seobeo_PHandle Seobeo_Stream_Handle_Create(const char *host,  const char* port)
 {
-  int32 client_fd;
-  struct sockaddr_storage client_addr; 
-  socklen_t sin_size;
+  Seobeo_PHandle p_handle;
+  p_handle = malloc(sizeof(*p_handle));
+
+  p_handle->socket = Seobeo_CreateSocket(1, host,  port, 10); // socke fd
+  p_handle->host = host != NULL ? strdup(host) : "localhost";
+  p_handle->port = strdup(port);
+
+  p_handle->read_buffer = malloc(sizeof(*p_handle->read_buffer) * INITIAL_BUFFER_CAPACITY);
+  p_handle->read_buffer_capacity = INITIAL_BUFFER_CAPACITY;
+  p_handle->read_buffer_len = 0;
+
+  p_handle->write_buffer = malloc(sizeof(*p_handle->read_buffer) * INITIAL_BUFFER_CAPACITY);
+  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;
 
+  return p_handle;
+}
+
+Seobeo_PHandle Seobeo_Stream_Handle_Accept(Seobeo_PHandle server_h)
+{
+  struct sockaddr_storage addr;
+  socklen_t addrlen = sizeof addr;
   char client_inet_addr[INET6_ADDRSTRLEN];
+  int client_fd = accept(server_h->socket,
+                         (struct sockaddr*)&addr,
+                         &addrlen);
+  inet_ntop(
+      addr.ss_family,
+      Seobeo_GetIP4OrIP6((struct sockaddr *)&addr),
+      client_inet_addr, sizeof client_inet_addr);
+
+  if (client_fd == -1)
+  {
+    return NULL;
+  }
+
+  Seobeo_PHandle h = malloc(sizeof *h);
 
-  while (1) 
-  {
-    sin_size = sizeof(client_addr);
-    client_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
+  h->socket               = client_fd;
+  h->host                 = strdup(client_inet_addr);
+  h->port                 = NULL;
+
+  h->read_buffer_capacity = server_h->read_buffer_capacity;
+  h->read_buffer_len      = 0;
+  h->read_buffer          = malloc(h->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);
+
+  return h;
+}
 
-    if (client_fd == -1)
-    {
-      perror("accept");
-      break;
+void Seobeo_Handle_Destroy(Seobeo_PHandle h)
+{
+  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);
+}
+
+int Seobeo_Handle_Flush(Seobeo_PHandle h)
+{
+  uint32 total = h->write_buffer_len;
+  uint32 sent  = 0;
+
+  while (sent < total) {
+    ssize_t n = write(
+      h->socket,
+      h->write_buffer + sent,
+      total - sent
+    );
+    if (n < 0) {
+      if (errno == EINTR)  continue;
+      if (errno == EAGAIN) return 1;
+      return -1;
     }
+    sent += (uint32)n;
+  }
 
-    inet_ntop(
-        client_addr.ss_family,
-        Seobeo_GetIP4OrIP6((struct sockaddr *)&client_addr),
-        client_inet_addr, sizeof client_inet_addr);
+  h->write_buffer_len = 0;
+  return 0;
+}
+
 
-    printf("server: got connection from %s\n", client_inet_addr);
+int Seobeo_Handle_QueueData(Seobeo_PHandle h, 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 (rc < 0) return -1;
+    if (rc > 0) return 1;
+  }
 
-    // Create a child process
-    if (!fork())
+  if (data_size > h->write_buffer_capacity)
+  {
+    uint32_t offset = 0;
+    while (offset < data_size)
     {
-      close(sock_fd);
-      handle_client(client_fd);
-      exit(0);
+      ssize_t n = write(h->socket,
+                data + offset,
+                data_size - offset);
+      if (n < 0) {
+        if (errno == EINTR)  continue;
+        if (errno == EAGAIN) return 1;
+        return -1;
+      }
+      offset += (uint32_t)n;
     }
+    return 0;
+  }
 
-    close(client_fd);
-  }
+  memcpy(h->write_buffer + h->write_buffer_len,
+         data,
+         data_size);
+  h->write_buffer_len += data_size;
+  return 0;
 }
 
 void *Seobeo_GetIP4OrIP6(struct sockaddr *sa)