diff seobeo/os/s_linux_edge.c @ 257:609d3c6aff4e

[seobeo] Add persistent SSE streams Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Tue, 04 Aug 2026 16:49:11 -0700
parents b8aa08503378
children 1f9877b637e9
line wrap: on
line diff
--- a/seobeo/os/s_linux_edge.c	Tue Aug 04 16:49:01 2026 -0700
+++ b/seobeo/os/s_linux_edge.c	Tue Aug 04 16:49:11 2026 -0700
@@ -74,7 +74,7 @@
           configure_keep_alive(p_cli_handle->socket);
 
           struct epoll_event client_ev = {
-            .events = EPOLLIN | EPOLLET,
+            .events = EPOLLIN | EPOLLET | EPOLLRDHUP,
             .data.ptr = p_cli_handle
           };
 
@@ -90,20 +90,46 @@
       {
         Seobeo_Handle *p_client_handle = p_handle;
 
-        // Connection error or hangup - clean up
-        if (events[i].events & (EPOLLERR | EPOLLHUP))
+        boolean peer_closed =
+            (events[i].events & (EPOLLHUP | EPOLLRDHUP)) != 0;
+        // Preserve readable bytes on a half-close so the final request can
+        // still receive its response.
+        if ((events[i].events & EPOLLERR) ||
+            (peer_closed && !(events[i].events & EPOLLIN)))
         {
           epoll_ctl(epfd, EPOLL_CTL_DEL, p_client_handle->socket, NULL);
           Seobeo_Handle_Destroy(p_client_handle);
           continue;
         }
 
+        if (p_client_handle->is_sse)
+        {
+          int32 read_result = Seobeo_Handle_Read(p_client_handle);
+          if (read_result < 0)
+          {
+            epoll_ctl(epfd, EPOLL_CTL_DEL, p_client_handle->socket, NULL);
+            Seobeo_Handle_Destroy(p_client_handle);
+          }
+          else if (p_client_handle->read_buffer_len)
+          {
+            Seobeo_Handle_Consume(
+                p_client_handle,
+                p_client_handle->read_buffer_len);
+          }
+          continue;
+        }
+
         // Handle requests (loop for pipelined requests)
         boolean keep_alive = TRUE;
         while (keep_alive)
         {
           keep_alive = Seobeo_Web_ClientHandle_Request(p_client_handle, args->cache, TRUE);
 
+          if (p_client_handle->is_sse)
+            break;
+          if (peer_closed)
+            keep_alive = FALSE;
+
           // No more data in buffer, wait for next epoll event
           if (keep_alive && p_client_handle->read_buffer_len == 0)
             break;