changeset 5:3e12bf044589

Fixed Dowa hashmap to recursively add files into memory.
author June Park <parkjune1995@gmail.com>
date Sat, 27 Sep 2025 16:23:04 -0700
parents 0b3b4f5887bb
children 1e61008b9980
files dowa/BUILD dowa/d_memory.c dowa/dowa.h dowa/dowa_test.c dowa/test_folder/bar/bar.txt dowa/test_folder/foo.txt seobeo/main.c seobeo/seobeo.h
diffstat 8 files changed, 227 insertions(+), 127 deletions(-) [+]
line wrap: on
line diff
--- a/dowa/BUILD	Fri Sep 26 15:14:46 2025 -0700
+++ b/dowa/BUILD	Sat Sep 27 16:23:04 2025 -0700
@@ -20,4 +20,7 @@
   srcs = ["dowa_test.c"],
   deps = [":dowa"],
   args = [],
+  data = glob([
+      "test_folder/**",
+  ]),
 )
--- a/dowa/d_memory.c	Fri Sep 26 15:14:46 2025 -0700
+++ b/dowa/d_memory.c	Sat Sep 27 16:23:04 2025 -0700
@@ -1,15 +1,15 @@
 #include "dowa.h"
 
 // --- Arena --- //
-Dowa_PArena Dowa_Arena_Initialize(size_t capacity)
+Dowa_PArena Dowa_Arena_Create(size_t capacity)
 {
-  Dowa_PArena p_arena;
-  p_arena = malloc(capacity);
+  Dowa_PArena p_arena = malloc(sizeof(Dowa_Arena));
   if (p_arena == NULL)
   {
     perror("malloc");
     return NULL;
   }
+  p_arena->buffer = malloc(capacity);
   p_arena->offset = 0;
   p_arena->capacity = capacity;
   return p_arena;
@@ -28,8 +28,10 @@
 
 void Dowa_Arena_Free(Dowa_PArena p_arena)
 {
-  if (p_arena) {
-    free(p_arena->buffer);
+  if (p_arena)
+  {
+    if (p_arena->buffer)
+      free(p_arena->buffer);
     free(p_arena);
   }
 }
@@ -43,7 +45,7 @@
   {
     return NULL;
   }
-  p_hash_map->entries = calloc(capacity, sizeof *p_hash_map->entries);
+  p_hash_map->entries = calloc(capacity, sizeof(*p_hash_map->entries));
   if (p_hash_map->entries == NULL)
   {
     free(p_hash_map);
@@ -54,6 +56,29 @@
   return p_hash_map;
 }
 
+void Dowa_HashMap_Free(Dowa_PHashMap p_hash_map)
+{
+  if (p_hash_map)
+  {
+    Dowa_PHashEntry entry;
+    if (p_hash_map->entries)
+    {
+      for (int idx=0; idx<p_hash_map->capacity; idx++)
+      {
+        entry = p_hash_map->entries[idx];
+        if (entry)
+        {
+          free(entry->key);
+          free(entry->buffer);
+          free(entry);
+        }
+      }
+      free(p_hash_map->entries);
+    }
+  }
+  free(p_hash_map);
+}
+
 int32 Dowa_HashMap_GetPosition(Dowa_PHashMap p_hash_map, char *key)
 {
   int32 hash_val = HASH_KEY_NUMBER;
@@ -65,41 +90,64 @@
   return hash_val % p_hash_map->capacity;
 }
 
-void Dowa_HashMap_PushValueWithType(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size, Dowa_ValueType type)
+void *Dowa_HashMap_Get(Dowa_PHashMap p_hash_map, char *key)
+{
+  int idx_foo = Dowa_HashMap_GetPosition(p_hash_map, key);
+  void *value = p_hash_map->entries[idx_foo];
+  if (strcmp(((Dowa_PHashEntry) value)->key, key) != 0)
+  {
+    return NULL;
+  }
+  return ((Dowa_PHashEntry) value)->buffer;
+}
+
+int32 Dowa_HashMap_PushValueWithTypeNoCopy(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size, Dowa_HashMap_ValueType type)
 {
   int idx = Dowa_HashMap_GetPosition(p_hash_map, key);
   Dowa_PHashEntry entry = p_hash_map->entries[idx];
   if (entry)
-  {
-    free(entry->key);
     free(entry->buffer);
-  }
   else 
   {
     entry = malloc(sizeof(Dowa_HashEntry));
-    if (entry == NULL)
-    {
-      perror("malloc");
-      return;
-    }
+    if (entry == NULL) { perror("malloc"); return -1; }
+
     p_hash_map->entries[idx] = entry;
+    p_hash_map->current_capacity++;
+    entry->key = strdup(key);
   }
-  entry->key = strdup(key);
-  entry->buffer = malloc(value_size);
-  if (entry->buffer == NULL)
+  entry->buffer = value;
+  entry->capacity = value_size;
+  entry->type = type;
+  return 0;
+}
+
+int32 Dowa_HashMap_PushValueWithType(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size, Dowa_HashMap_ValueType type)
+{
+  int idx = Dowa_HashMap_GetPosition(p_hash_map, key);
+  Dowa_PHashEntry entry = p_hash_map->entries[idx];
+  if (entry)
+    free(entry->buffer);
+  else 
   {
-    perror("malloc");
-    return;
+    entry = malloc(sizeof(Dowa_HashEntry));
+    if (entry == NULL) { perror("malloc"); return -1; }
+
+    p_hash_map->entries[idx] = entry;
+    p_hash_map->current_capacity++;
+    entry->key = strdup(key);
   }
+  entry->buffer = malloc(value_size);
+  if (entry->buffer == NULL) { perror("malloc"); return -1; }
   entry->capacity = value_size;
   entry->type = type;
   memcpy(entry->buffer, value, value_size);
-  p_hash_map->current_capacity++;
+  return 0;
 }
 
 void Dowa_HashMap_PushValue(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size)
 {
-  Dowa_HashMap_PushValueWithType(p_hash_map, key, value, value_size, DOWA_TYPE_BUFFER);
+  Dowa_HashMap_PushValueWithType(p_hash_map, key, value, value_size, DOWA_HASH_MAP_TYPE_BUFFER);
 }
 
 void Dowa_HashMap_PopKey(Dowa_PHashMap p_hash_map, char *key)
@@ -119,10 +167,9 @@
   }
 }
 
-#include <stdio.h>
-
 void Dowa_HashMap_Print(Dowa_PHashMap map)
 {
+  printf("\n-----------\n\n");
   for (size_t i = 0; i < map->capacity; ++i)
   {
     Dowa_PHashEntry e = map->entries[i];
@@ -130,23 +177,29 @@
     printf("%s: ", e->key);
     switch (e->type)
     {
-      case DOWA_TYPE_BUFFER:
+      case DOWA_HASH_MAP_TYPE_BUFFER:
       {
         unsigned char *p = e->buffer;
-        for (size_t j = 0; j < e->capacity; ++j) {
+        for (size_t j = 0; j < e->capacity; ++j)
+        {
           printf("%02x", p[j]);
         }
         printf("\n");
       }
       break;
-      case DOWA_TYPE_STRING:
+      case DOWA_HASH_MAP_TYPE_STRING:
       {
         printf("%s\n", (char*)e->buffer);
       }
       break;
-      case DOWA_TYPE_INT:
+      case DOWA_HASH_MAP_TYPE_HASHMAP:
       {
-        printf("%d\n", *(int32_t*)e->buffer);
+        printf("This is a hashmap with size of %zu, and pointer %p\n", (Dowa_PHashMap)e->capacity, (void *)e);
+      }
+      break;
+      case DOWA_HASH_MAP_TYPE_INT:
+      {
+        printf("%d\n", *(int32*)e->buffer);
       }
       break;
       default:
@@ -155,20 +208,17 @@
       }
     }
   }
+  printf("-----------\n");
 }
 
-
-
-int Dowa_Cache_Folder(Dowa_PHashMap map, const char *folder_path)
+int Dowa_HashMap_Cache_Folder(Dowa_PHashMap map, const char *folder_path)
 {
   DIR *dir = opendir(folder_path);
-  if (!dir) {
-    perror("opendir");
-    return -1;
-  }
+  if (!dir) { perror("opendir"); return -1; }
 
   struct dirent *entry;
-  while ((entry = readdir(dir))) {
+  while ((entry = readdir(dir)))
+  {
     // skip "." and ".."
     if (entry->d_name[0] == '.' &&
        (entry->d_name[1] == '\0' ||
@@ -179,41 +229,53 @@
     snprintf(fullpath, sizeof fullpath, "%s/%s", folder_path, entry->d_name);
 
     struct stat st;
-    if (stat(fullpath, &st) < 0 || !S_ISREG(st.st_mode))
-      continue;  // skip non-files or errors
+    if (stat(fullpath, &st) < 0) { perror("stat"); continue; }
 
-    size_t size = (size_t)st.st_size;
-    FILE *f = fopen(fullpath, "rb");
-    if (!f)
+    if (S_ISREG(st.st_mode))
     {
-      perror("fopen");
-      continue;
-    }
+      size_t size = (size_t)st.st_size;
+      FILE *f = fopen(fullpath, "rb");
+      if (!f) { perror("fopen"); continue; }
+
+      void *buf = malloc(size);
+      if (!buf) { perror("malloc"); fclose(f); closedir(dir); return -1; }
 
-    void *buf = malloc(size);
-    if (!buf)
-    {
-      perror("malloc");
+      if (fread(buf, 1, size, f) != size)
+      {
+        perror("fread");
+        free(buf);
+        fclose(f);
+        continue;
+      }
       fclose(f);
-      closedir(dir);
-      return -1;
+
+      Dowa_HashMap_PushValueWithType(map, entry->d_name, buf, size, DOWA_HASH_MAP_TYPE_STRING);
+      free(buf);  // Dowa_HashMap_PushValue made its own copy
     }
-
-    if (fread(buf, 1, size, f) != size)
+    else if (S_ISDIR(st.st_mode))
     {
-      perror("fread");
-      free(buf);
-      fclose(f);
-      continue;
-    }
-    fclose(f);
+      Dowa_PHashMap p_child_map = Dowa_HashMap_Create(100); 
+      if (!p_child_map)
+      {
+        perror("Dowa_HashMap_Create");
+        return -1;
+      }
+      if (Dowa_HashMap_Cache_Folder(p_child_map, fullpath) == -1)
+      {
+        perror("Dowa_HashMap_Cache_Folder");
+        return -1;
+      }
+      void *value = Dowa_HashMap_Get(p_child_map, "bar.txt");
 
-    // key = filename (d_name), value = file contents
-    Dowa_HashMap_PushValueWithType(map, entry->d_name, buf, size, DOWA_TYPE_STRING);
-
-    free(buf);  // Dowa_HashMap_PushValue made its own copy
+      // Should not copy as we malloced alredy.
+      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);
+        return -1;
+      }
+    }
   }
-
   closedir(dir);
   return 0;
 }
--- a/dowa/dowa.h	Fri Sep 26 15:14:46 2025 -0700
+++ b/dowa/dowa.h	Sat Sep 27 16:23:04 2025 -0700
@@ -13,7 +13,7 @@
 #include "dowa_internal.h"
 
 #define HASH_KEY_NUMBER 5381 // DJD hash number
-
+#define ONE_MEGA_BYTE   1048576
 typedef unsigned int uint32;
 typedef int int32;
 typedef unsigned short uint16;
@@ -30,24 +30,25 @@
   char   *buffer;
   size_t offset;
   size_t capacity;
-} Dowa_Areana, *Dowa_PArena;
+} Dowa_Arena, *Dowa_PArena;
 
-extern Dowa_PArena Dowa_Arena_Initialize(size_t capacity);
+extern Dowa_PArena Dowa_Arena_Create(size_t capacity);
 extern void        *Dowa_Arena_Allocate(Dowa_PArena p_arena, size_t size);
 extern void        Dowa_Arena_Free(Dowa_PArena p_arena);
 
-// --- Map --- //
+// --- HashMap --- //
 typedef enum {
-  DOWA_TYPE_BUFFER,
-  DOWA_TYPE_STRING,
-  DOWA_TYPE_INT,
-} Dowa_ValueType;
+  DOWA_HASH_MAP_TYPE_BUFFER,
+  DOWA_HASH_MAP_TYPE_STRING,
+  DOWA_HASH_MAP_TYPE_HASHMAP,
+  DOWA_HASH_MAP_TYPE_INT,
+} Dowa_HashMap_ValueType;
 
 typedef struct {
   char           *key;
   void           *buffer; 
   size_t         capacity;
-  Dowa_ValueType type;
+  Dowa_HashMap_ValueType type;
 } Dowa_HashEntry, *Dowa_PHashEntry;
 
 typedef struct {
@@ -56,16 +57,19 @@
   uint32          current_capacity;
 } Dowa_HashMap, *Dowa_PHashMap;
 
-extern Dowa_PHashMap Dowa_HashMap_Create(size_t capacity);
-extern int32         Dowa_HashMap_GetPosition(Dowa_PHashMap p_hash_map, char *key);
-extern void          Dowa_HashMap_PushValue(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size);
-extern void          Dowa_HashMap_PushValueWithType(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size, Dowa_ValueType type);
-extern void          Dowa_HashMap_PopKey(Dowa_PHashMap p_hash_map, char *key);
+extern Dowa_PHashMap   Dowa_HashMap_Create(size_t capacity);
+extern void            Dowa_HashMap_Free(Dowa_PHashMap p_hash_map);
+extern int32           Dowa_HashMap_GetPosition(Dowa_PHashMap p_hash_map, char *key);
+extern void            *Dowa_HashMap_Get(Dowa_PHashMap p_hash_map, char *key);
+extern void            Dowa_HashMap_PushValue(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size);
+extern int32           Dowa_HashMap_PushValueWithTypeNoCopy(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size, Dowa_HashMap_ValueType type);
+extern int32           Dowa_HashMap_PushValueWithType(Dowa_PHashMap p_hash_map, char *key, void *value, size_t value_size, Dowa_HashMap_ValueType type);
+extern void            Dowa_HashMap_PopKey(Dowa_PHashMap p_hash_map, char *key);
 
 // --- Maybe Useful --- //
 extern void Dowa_HashMap_Print(Dowa_PHashMap map);
-// 0 for success, -1 for failure.
-extern int  Dowa_Cache_Folder(Dowa_PHashMap map, const char *folder_path);
+// 0 for success, -1 for failure. Get all files in the folder into key and vlaues.
+extern int  Dowa_HashMap_Cache_Folder(Dowa_PHashMap map, const char *folder_path);
 
 
 #endif
--- a/dowa/dowa_test.c	Fri Sep 26 15:14:46 2025 -0700
+++ b/dowa/dowa_test.c	Sat Sep 27 16:23:04 2025 -0700
@@ -1,16 +1,19 @@
 #include "dowa.h"
 
-static void TestArena() {
+static void TestArena()
+{
   const size_t capacity = 64;
-  Dowa_PArena arena = Dowa_Arena_Initialize(capacity);
+  Dowa_PArena arena = Dowa_Arena_Create(capacity);
   assert(arena != NULL);
   assert(arena->offset == 0);
   assert(arena->capacity == capacity);
 
   // Allocate within capacity
   void *p1 = Dowa_Arena_Allocate(arena, 16);
-  // assert(p1 != NULL);
+  assert(p1 != NULL);
   assert(arena->offset == 16);
+  sprintf((char *)p1, "%i", 10);
+  assert(strcmp(p1, "10") == 0);
 
   // Allocate more
   void *p2 = Dowa_Arena_Allocate(arena, 32);
@@ -25,7 +28,8 @@
   Dowa_Arena_Free(arena);
 }
 
-static void TestHashMap() {
+static void TestHashMap()
+{
   const size_t capacity = 10;
   Dowa_PHashMap map = Dowa_HashMap_Create(capacity);
   assert(map != NULL);
@@ -43,21 +47,20 @@
   assert(strcmp(e_foo->key, "foo") == 0);
   assert(*(int*)e_foo->buffer == 42);
 
-  // Overwrite "foo" -> 100
+  // Overwrite "foo" -> 100 (capacity should not change)
   int val2 = 100;
   Dowa_HashMap_PushValue(map, "foo", &val2, sizeof(val2));
-  // current_capacity increments again according to your implementation
-  assert(map->current_capacity == 2);
+  assert(map->current_capacity == 1);
 
-  Dowa_PHashEntry e_foo2 = map->entries[idx_foo];
-  assert(e_foo2 != NULL);
-  assert(strcmp(e_foo2->key, "foo") == 0);
-  assert(*(int*)e_foo2->buffer == 100);
+  e_foo = map->entries[idx_foo];
+  assert(e_foo != NULL);
+  assert(strcmp(e_foo->key, "foo") == 0);
+  assert(*(int*)e_foo->buffer == 100);
 
   // Insert "bar" -> -7
   int val3 = -7;
   Dowa_HashMap_PushValue(map, "bar", &val3, sizeof(val3));
-  assert(map->current_capacity == 3);
+  assert(map->current_capacity == 2);
 
   int idx_bar = Dowa_HashMap_GetPosition(map, "bar");
   Dowa_PHashEntry e_bar = map->entries[idx_bar];
@@ -68,24 +71,35 @@
   // Pop "foo"
   Dowa_HashMap_PopKey(map, "foo");
   assert(map->entries[idx_foo] == NULL);
-  assert(map->current_capacity == 2);
+  assert(map->current_capacity == 1);
 
   // Pop "bar"
   Dowa_HashMap_PopKey(map, "bar");
   assert(map->entries[idx_bar] == NULL);
-  assert(map->current_capacity == 1);
+  assert(map->current_capacity == 0);
+
+  // Clean up map
+  Dowa_HashMap_Free(map);
+}
+
+void Test_Dowa_HashMap_Cache_Folder()
+{
+  Dowa_PHashMap map = Dowa_HashMap_Create(100);
 
-  // Clean up remaining entries and the map itself
-  for (size_t i = 0; i < map->capacity; ++i) {
-    Dowa_PHashEntry ent = map->entries[i];
-    if (ent) {
-      free(ent->key);
-      free(ent->buffer);
-      free(ent);
-    }
-  }
-  free(map->entries);
-  free(map);
+  int res = Dowa_HashMap_Cache_Folder(map, "dowa/test_folder");
+  assert(res == 0 && "Folder caching should succeed");
+
+  const char *foo_val = (const char *)Dowa_HashMap_Get(map, "foo.txt");
+  assert(foo_val != NULL);
+  assert(strcmp("this is foo\n", foo_val)==0);
+
+  Dowa_HashMap_Print(map);
+
+  Dowa_PHashMap p_bar_map = (Dowa_PHashMap)Dowa_HashMap_Get(map, "bar");
+  assert(p_bar_map != NULL); 
+  assert(strcmp("this is bar\n", (const char *)Dowa_HashMap_Get(p_bar_map, "bar.txt"))==0);
+
+  Dowa_HashMap_Free(map);
 }
 
 int main(void) {
@@ -95,6 +109,8 @@
   TestHashMap();
   printf("HashMap tests passed.\n");
 
+  Test_Dowa_HashMap_Cache_Folder();
+  printf("Test_Dowa_HashMap_Cache_Folder passed\n");
   return 0;
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dowa/test_folder/bar/bar.txt	Sat Sep 27 16:23:04 2025 -0700
@@ -0,0 +1,1 @@
+this is bar
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dowa/test_folder/foo.txt	Sat Sep 27 16:23:04 2025 -0700
@@ -0,0 +1,1 @@
+this is foo
--- a/seobeo/main.c	Fri Sep 26 15:14:46 2025 -0700
+++ b/seobeo/main.c	Sat Sep 27 16:23:04 2025 -0700
@@ -20,25 +20,31 @@
 
 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) {
+  if (!entry)
+  {
     // 404 response if missing
     const char *not_found =
-      "HTTP/1.1 404 Not Found\r\n"
+      "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);
-    Seobeo_Handle_Destroy(cli);
-    return;
+    goto clean_up;
   }
 
   // 3) Prepare header with the correct content‐length
   size_t body_size = entry->capacity;
   const char *template =
-    "HTTP/1.1 200 OK\r\n"
+    "HTTP/2.0 200 OK\r\n"
     "Content-Type: text/html\r\n"
     "Content-Length: %zu\r\n"
     "Connection: close\r\n"
@@ -46,26 +52,27 @@
 
   // Compute how large the header is and allocate just enough space
   int header_len = snprintf(NULL, 0, template, body_size);
-  char *header = malloc(header_len + 1);
-  if (!header) {
-    perror("malloc");
-    return;
+  void *header = Dowa_Arena_Allocate(response_arena, (size_t)(header_len+1));
+  if (header == NULL)
+  {
+    perror("Dowa_Arena_Allocate");
+    goto clean_up;
   }
-  snprintf(header, header_len + 1, template, body_size);
 
+  snprintf((char *)header, header_len + 1, template, body_size);
   Seobeo_Handle_QueueData(cli,
               (const uint8*)header,
               (uint32)(header_len + 1));
-  free(header);
-
   Seobeo_Handle_QueueData(cli,
               (const uint8*)entry->buffer,
               (uint32)body_size);
-
+  Seobeo_Handle_Flush(cli);
+  goto clean_up;
 
-  Seobeo_Handle_Flush(cli);
-
+clean_up:
   Seobeo_Handle_Destroy(cli);
+  Dowa_Arena_Free(response_arena);
+  return ;
 }
 
 int main(void)
@@ -84,21 +91,26 @@
   if (srv->socket < 0) return 1;
   printf("Listening on port 8080\n");
 
-  sa.sa_handler = SigchildHandler; // reap all dead processes
+  // 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) {
+  if (sigaction(SIGCHLD, &sa, NULL) == -1)
+  {
     perror("sigaction");
     exit(1);
   }
 
-  while (1) {
+  while (1)
+  {
     Seobeo_PHandle cli = Seobeo_Stream_Handle_Accept(srv);
     if (cli == NULL)
     {
       continue; 
     }
-    printf("connected to %s\n", cli->host);
+    printf("client connected from %s\n", cli->host);
 
     if (!fork())
     {
--- a/seobeo/seobeo.h	Fri Sep 26 15:14:46 2025 -0700
+++ b/seobeo/seobeo.h	Sat Sep 27 16:23:04 2025 -0700
@@ -43,16 +43,17 @@
 } Sebeo_Handle, *Seobeo_PHandle;
 
 
-// --- Internal? --- //
+// --- Socket, IP related --- //
 extern int            Seobeo_CreateSocket(int32 stream, const char *host,  const char* port, int32 backlog);
 extern void           *Seobeo_GetIP4OrIP6(struct sockaddr *sa);
 
 // --- 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);
+
+// --- 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);
 
-
 #endif