@@ -201,7 +201,7 @@ fn handle_accept_loop(epoll_fd int, listen_fd int, mut client_fds map[int]bool)
201201 }
202202}
203203
204- fn handle_client_closure (epoll_fd int , client_fd int , mut client_fds map [int ]bool ) {
204+ fn handle_client_closure (epoll_fd int , client_fd int , mut client_fds map [int ]bool , mut client_buffers map [ int ][] u8 ) {
205205 // Never close the listening socket here
206206 if client_fd == 0 {
207207 return
@@ -211,17 +211,18 @@ fn handle_client_closure(epoll_fd int, client_fd int, mut client_fds map[int]boo
211211 return
212212 }
213213 client_fds.delete (client_fd)
214+ client_buffers.delete (client_fd)
214215 remove_fd_from_epoll (epoll_fd, client_fd)
215216 close_socket (client_fd)
216217}
217218
218- fn close_worker_clients (epoll_fd int , mut client_fds map [int ]bool ) {
219+ fn close_worker_clients (epoll_fd int , mut client_fds map [int ]bool , mut client_buffers map [ int ][] u8 ) {
219220 for client_fd in client_fds.keys () {
220- handle_client_closure (epoll_fd, client_fd, mut client_fds)
221+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers )
221222 }
222223}
223224
224- fn process_request (server & Server, epoll_fd int , client_fd int , request_buffer []u8 , mut client_fds map [int ]bool ) {
225+ fn process_request (server & Server, epoll_fd int , client_fd int , request_buffer []u8 , mut client_fds map [int ]bool , mut client_buffers map [ int ][] u8 ) {
225226 server.begin_request ()
226227 defer {
227228 server.end_request ()
@@ -230,7 +231,7 @@ fn process_request(server &Server, epoll_fd int, client_fd int, request_buffer [
230231 eprintln ('Error decoding request ${err} ' )
231232 C.send (client_fd, tiny_bad_request_response.data, tiny_bad_request_response.len,
232233 C.MSG_NOSIGNAL)
233- handle_client_closure (epoll_fd, client_fd, mut client_fds)
234+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers )
234235 return
235236 }
236237 decoded_http_request.client_conn_fd = client_fd
@@ -239,14 +240,15 @@ fn process_request(server &Server, epoll_fd int, client_fd int, request_buffer [
239240 eprintln ('Error handling request ${err} ' )
240241 C.send (client_fd, tiny_bad_request_response.data, tiny_bad_request_response.len,
241242 C.MSG_NOSIGNAL)
242- handle_client_closure (epoll_fd, client_fd, mut client_fds)
243+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers )
243244 return
244245 }
245246
246247 if response.takeover {
247248 // The handler has taken ownership of the connection.
248249 // Remove from epoll and tracking, but do NOT close the fd.
249250 client_fds.delete (client_fd)
251+ client_buffers.delete (client_fd)
250252 remove_fd_from_epoll (epoll_fd, client_fd)
251253 return
252254 }
@@ -265,7 +267,7 @@ fn process_request(server &Server, epoll_fd int, client_fd int, request_buffer [
265267 pos + = sent
266268 }
267269 if send_error {
268- handle_client_closure (epoll_fd, client_fd, mut client_fds)
270+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers )
269271 return
270272 }
271273 }
@@ -274,7 +276,7 @@ fn process_request(server &Server, epoll_fd int, client_fd int, request_buffer [
274276 mut fd := C.open (response.file_path.str, C.O_RDONLY, 0 )
275277 if fd == - 1 {
276278 eprintln ('ERROR: open file failed' )
277- handle_client_closure (epoll_fd, client_fd, mut client_fds)
279+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers )
278280 return
279281 }
280282 defer {
@@ -285,7 +287,7 @@ fn process_request(server &Server, epoll_fd int, client_fd int, request_buffer [
285287 mut st := C.stat{}
286288 if C.fstat (fd, & st) != 0 {
287289 eprintln ('ERROR: fstat failed' )
288- handle_client_closure (epoll_fd, client_fd, mut client_fds)
290+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers )
289291 return
290292 }
291293 mut offset := i64 (0 )
@@ -333,26 +335,28 @@ fn process_request(server &Server, epoll_fd int, client_fd int, request_buffer [
333335 }
334336 }
335337
336- handle_client_closure (epoll_fd, client_fd, mut client_fds)
338+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers )
337339 return
338340 }
339341 }
340342
343+ client_buffers.delete (client_fd)
341344 if server.is_shutting_down () || response.should_close {
342- handle_client_closure (epoll_fd, client_fd, mut client_fds)
345+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers )
343346 }
344347}
345348
346349fn process_events (server & Server, epoll_fd int , listen_fd int ) {
347350 mut events := [max_connection_size]C.epoll_event{}
348351 mut request_buffer := []u8 {len: server.max_request_buffer_size, cap: server.max_request_buffer_size}
349352 mut client_fds := map [int ]bool {}
353+ mut client_buffers := map [int ][]u8 {}
350354 unsafe {
351355 request_buffer.flags.set (.noslices | .nogrow | .noshrink)
352356 }
353357 for {
354358 if server.is_shutting_down () && server.active_request_count () == 0 {
355- close_worker_clients (epoll_fd, mut client_fds)
359+ close_worker_clients (epoll_fd, mut client_fds, mut client_buffers )
356360 return
357361 }
358362 num_events := C.epoll_wait (epoll_fd, & events[0 ], max_connection_size, epoll_wait_timeout_ms)
@@ -386,23 +390,28 @@ fn process_events(server &Server, epoll_fd int, listen_fd int) {
386390 // Try to send 444 No Response before closing abnormal connection
387391 C.send (client_fd, status_444_ response.data, status_444_ response.len,
388392 C.MSG_NOSIGNAL)
389- handle_client_closure (epoll_fd, client_fd, mut client_fds)
393+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers )
390394 } else {
391395 eprintln ('ERROR: Invalid FD from epoll: ${client_fd} ' )
392396 }
393397 continue
394398 }
395399 if events[i].events & u32 (C.EPOLLIN) != 0 {
396400 if server.is_shutting_down () {
397- handle_client_closure (epoll_fd, client_fd, mut client_fds)
401+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers )
398402 continue
399403 }
400404 // Read all available data from the socket
401405 mut total_bytes_read := 0
402- mut readed_request_buffer := []u8 {cap: server.max_request_buffer_size}
406+ mut readed_request_buffer := client_buffers[client_fd] or {
407+ []u8 {cap: server.max_request_buffer_size}
408+ }
403409 mut headers_complete := false
404410 mut header_too_large := false
405411 mut header_end_pos := - 1
412+ mut request_complete := false
413+ mut peer_closed := false
414+ mut recv_error := false
406415
407416 for {
408417 bytes_read := C.recv (client_fd, unsafe { & request_buffer[0 ] },
@@ -414,9 +423,11 @@ fn process_events(server &Server, epoll_fd int, listen_fd int) {
414423 }
415424 // Error occurred
416425 eprintln ('ERROR: recv() failed with errno=${C.errno} ' )
426+ recv_error = true
417427 break
418428 } else if bytes_read == 0 {
419429 // Connection closed by client
430+ peer_closed = true
420431 break
421432 }
422433
@@ -426,11 +437,12 @@ fn process_events(server &Server, epoll_fd int, listen_fd int) {
426437 total_bytes_read + = bytes_read
427438
428439 // Enforce the configured limit on request headers, not on the whole body.
429- if ! headers_complete && total_bytes_read > = 4 {
440+ buffer_len := readed_request_buffer.len
441+ if ! headers_complete && buffer_len > = 4 {
430442 header_end_pos = find_header_end_in_buf (readed_request_buffer.data,
431- total_bytes_read )
443+ buffer_len )
432444 if header_end_pos == - 1 {
433- if total_bytes_read > = server.max_request_buffer_size {
445+ if buffer_len > = server.max_request_buffer_size {
434446 header_too_large = true
435447 break
436448 }
@@ -443,29 +455,31 @@ fn process_events(server &Server, epoll_fd int, listen_fd int) {
443455 }
444456 }
445457
446- if headers_complete
447- && has_complete_body (readed_request_buffer.data, total_bytes_read) {
458+ if headers_complete && has_complete_body (readed_request_buffer.data, buffer_len) {
459+ request_complete = true
448460 break
449461 }
450462 }
451463
452464 if header_too_large {
453465 C.send (client_fd, status_413_ response.data, status_413_ response.len,
454466 C.MSG_NOSIGNAL)
455- handle_client_closure (epoll_fd, client_fd, mut client_fds)
467+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers )
456468 continue
457469 }
458- if total_bytes_read > 0 {
470+ if request_complete {
459471 process_request (server, epoll_fd, client_fd, readed_request_buffer, mut
460- client_fds)
461- } else if total_bytes_read == 0 {
462- // Normal client closure (FIN received)
463- handle_client_closure (epoll_fd, client_fd, mut client_fds)
464- } else if total_bytes_read < 0 && C.errno != C.EAGAIN && C.errno != C.EWOULDBLOCK {
472+ client_fds, mut client_buffers)
473+ } else if recv_error {
465474 // Unexpected recv error - send 444 No Response
466475 C.send (client_fd, status_444_ response.data, status_444_ response.len,
467476 C.MSG_NOSIGNAL)
468- handle_client_closure (epoll_fd, client_fd, mut client_fds)
477+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers)
478+ } else if peer_closed || (total_bytes_read == 0 && readed_request_buffer.len == 0 ) {
479+ // Normal client closure (FIN received)
480+ handle_client_closure (epoll_fd, client_fd, mut client_fds, mut client_buffers)
481+ } else if readed_request_buffer.len > 0 {
482+ client_buffers[client_fd] = readed_request_buffer
469483 }
470484 }
471485 }
0 commit comments