@@ -34,8 +34,9 @@ struct C.epoll_event {
3434
3535struct Server {
3636pub :
37- port int = 3000
38- max_request_buffer_size int = 8192
37+ family net.AddrFamily = .ip6
38+ port int = 3000
39+ max_request_buffer_size int = 8192
3940 user_data voidptr
4041mut :
4142 listen_fds []int = []int {len: max_thread_pool_size, cap: max_thread_pool_size}
@@ -50,6 +51,7 @@ pub fn new_server(config ServerConfig) !&Server {
5051 return error ('max_request_buffer_size must be greater than 0' )
5152 }
5253 mut server := & Server{
54+ family: config.family
5355 port: config.port
5456 max_request_buffer_size: config.max_request_buffer_size
5557 user_data: config.user_data
@@ -92,9 +94,9 @@ fn close_socket(fd int) bool {
9294 return true
9395}
9496
95- fn create_server_socket (port int ) int {
97+ fn create_server_socket (server Server ) int {
9698 // Create a socket with non-blocking mode
97- server_fd := C.socket (net.AddrFamily.ip , net.SocketType.tcp, 0 )
99+ server_fd := C.socket (server.family , net.SocketType.tcp, 0 )
98100 if server_fd < 0 {
99101 eprintln (@LOCATION)
100102 C.perror (c 'Socket creation failed' )
@@ -118,7 +120,7 @@ fn create_server_socket(port int) int {
118120 return - 1
119121 }
120122
121- addr := net.new_ip (u16 (port), [u8 (0 ), 0 , 0 , 0 ]! )
123+ addr := net.new_ip (u16 (server. port), [u8 (0 ), 0 , 0 , 0 ]! )
122124 alen := addr.len ()
123125 if C.bind (server_fd, voidptr (& addr), alen) < 0 {
124126 eprintln (@LOCATION)
@@ -225,20 +227,55 @@ fn process_events(mut server Server, epoll_fd int, listen_fd int) {
225227 continue
226228 }
227229 if events[i].events & u32 (C.EPOLLIN) != 0 {
228- bytes_read := C.recv (client_fd, unsafe { & request_buffer[0 ] }, server.max_request_buffer_size - 1 ,
229- 0 )
230- if bytes_read > 0 {
230+ // Read all available data from the socket
231+ mut total_bytes_read := 0
232+ mut readed_request_buffer := []u8 {len: server.max_request_buffer_size, cap: server.max_request_buffer_size}
233+
234+ for {
235+ bytes_read := C.recv (client_fd, unsafe { & request_buffer[0 ] }, server.max_request_buffer_size - 1 ,
236+ 0 )
237+ if bytes_read < 0 {
238+ if C.errno == C.EAGAIN || C.errno == C.EWOULDBLOCK {
239+ // No more data available right now
240+ break
241+ }
242+ // Error occurred
243+ eprintln ('ERROR: recv() failed with errno=${C .errno }' )
244+ break
245+ } else if bytes_read == 0 {
246+ // Connection closed by client
247+ break
248+ }
249+
250+ // Append the received data to the buffer
251+ if total_bytes_read + bytes_read > server.max_request_buffer_size {
252+ // Buffer size exceeded
253+ break
254+ }
255+ unsafe {
256+ readed_request_buffer.push_many (& request_buffer[0 ], bytes_read)
257+ }
258+ total_bytes_read + = bytes_read
259+
260+ // Check if we've received the complete HTTP request (look for \r\n\r\n)
261+ if total_bytes_read > = 4 {
262+ if readed_request_buffer[total_bytes_read - 4 ] == `\r `
263+ && readed_request_buffer[total_bytes_read - 3 ] == `\n `
264+ && readed_request_buffer[total_bytes_read - 2 ] == `\r `
265+ && readed_request_buffer[total_bytes_read - 1 ] == `\n ` {
266+ break
267+ }
268+ }
269+ }
270+
271+ if total_bytes_read > 0 {
231272 // Check if request exceeds buffer size
232- if bytes_read > = server.max_request_buffer_size - 1 {
273+ if total_bytes_read > = server.max_request_buffer_size - 1 {
233274 C.send (client_fd, status_413_ response.data, status_413_ response.len,
234275 C.MSG_NOSIGNAL)
235276 handle_client_closure (epoll_fd, client_fd)
236277 continue
237278 }
238- mut readed_request_buffer := []u8 {cap: bytes_read}
239- unsafe {
240- readed_request_buffer.push_many (& request_buffer[0 ], bytes_read)
241- }
242279 mut decoded_http_request := decode_http_request (readed_request_buffer) or {
243280 eprintln ('Error decoding request ${err }' )
244281 C.send (client_fd, tiny_bad_request_response.data, tiny_bad_request_response.len,
@@ -340,10 +377,10 @@ fn process_events(mut server Server, epoll_fd int, listen_fd int) {
340377 C.close (fd)
341378 }
342379 // Leave the connection open; closure is driven by client FIN or errors
343- } else if bytes_read == 0 {
380+ } else if total_bytes_read == 0 {
344381 // Normal client closure (FIN received)
345382 handle_client_closure (epoll_fd, client_fd)
346- } else if bytes_read < 0 && C.errno != C.EAGAIN && C.errno != C.EWOULDBLOCK {
383+ } else if total_bytes_read < 0 && C.errno != C.EAGAIN && C.errno != C.EWOULDBLOCK {
347384 // Unexpected recv error - send 444 No Response
348385 C.send (client_fd, status_444_ response.data, status_444_ response.len,
349386 C.MSG_NOSIGNAL)
@@ -361,7 +398,7 @@ pub fn (mut server Server) run() ! {
361398 return
362399 }
363400 for i := 0 ; i < max_thread_pool_size; i++ {
364- server.listen_fds[i] = create_server_socket (server.port )
401+ server.listen_fds[i] = create_server_socket (server)
365402 if server.listen_fds[i] < 0 {
366403 return
367404 }
@@ -383,7 +420,7 @@ pub fn (mut server Server) run() ! {
383420 server.threads[i] = spawn process_events (mut server, server.epoll_fds[i], server.listen_fds[i])
384421 }
385422
386- println ('listening on http://localhost :${server .port }/' )
423+ println ('listening on http://0.0.0.0 :${server .port }/' )
387424 // Main thread waits for workers; accepts are handled in worker epoll loops
388425 for i in 0 .. max_thread_pool_size {
389426 server.threads[i].wait ()
0 commit comments