comparison 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
comparison
equal deleted inserted replaced
256:30c2196d03d4 257:609d3c6aff4e
72 72
73 // Let kernel handle keep-alive timeout 73 // Let kernel handle keep-alive timeout
74 configure_keep_alive(p_cli_handle->socket); 74 configure_keep_alive(p_cli_handle->socket);
75 75
76 struct epoll_event client_ev = { 76 struct epoll_event client_ev = {
77 .events = EPOLLIN | EPOLLET, 77 .events = EPOLLIN | EPOLLET | EPOLLRDHUP,
78 .data.ptr = p_cli_handle 78 .data.ptr = p_cli_handle
79 }; 79 };
80 80
81 if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_cli_handle->socket, &client_ev) < 0) 81 if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_cli_handle->socket, &client_ev) < 0)
82 { 82 {
88 // Client socket - handle request 88 // Client socket - handle request
89 else 89 else
90 { 90 {
91 Seobeo_Handle *p_client_handle = p_handle; 91 Seobeo_Handle *p_client_handle = p_handle;
92 92
93 // Connection error or hangup - clean up 93 boolean peer_closed =
94 if (events[i].events & (EPOLLERR | EPOLLHUP)) 94 (events[i].events & (EPOLLHUP | EPOLLRDHUP)) != 0;
95 // Preserve readable bytes on a half-close so the final request can
96 // still receive its response.
97 if ((events[i].events & EPOLLERR) ||
98 (peer_closed && !(events[i].events & EPOLLIN)))
95 { 99 {
96 epoll_ctl(epfd, EPOLL_CTL_DEL, p_client_handle->socket, NULL); 100 epoll_ctl(epfd, EPOLL_CTL_DEL, p_client_handle->socket, NULL);
97 Seobeo_Handle_Destroy(p_client_handle); 101 Seobeo_Handle_Destroy(p_client_handle);
102 continue;
103 }
104
105 if (p_client_handle->is_sse)
106 {
107 int32 read_result = Seobeo_Handle_Read(p_client_handle);
108 if (read_result < 0)
109 {
110 epoll_ctl(epfd, EPOLL_CTL_DEL, p_client_handle->socket, NULL);
111 Seobeo_Handle_Destroy(p_client_handle);
112 }
113 else if (p_client_handle->read_buffer_len)
114 {
115 Seobeo_Handle_Consume(
116 p_client_handle,
117 p_client_handle->read_buffer_len);
118 }
98 continue; 119 continue;
99 } 120 }
100 121
101 // Handle requests (loop for pipelined requests) 122 // Handle requests (loop for pipelined requests)
102 boolean keep_alive = TRUE; 123 boolean keep_alive = TRUE;
103 while (keep_alive) 124 while (keep_alive)
104 { 125 {
105 keep_alive = Seobeo_Web_ClientHandle_Request(p_client_handle, args->cache, TRUE); 126 keep_alive = Seobeo_Web_ClientHandle_Request(p_client_handle, args->cache, TRUE);
127
128 if (p_client_handle->is_sse)
129 break;
130 if (peer_closed)
131 keep_alive = FALSE;
106 132
107 // No more data in buffer, wait for next epoll event 133 // No more data in buffer, wait for next epoll event
108 if (keep_alive && p_client_handle->read_buffer_len == 0) 134 if (keep_alive && p_client_handle->read_buffer_len == 0)
109 break; 135 break;
110 } 136 }