1#[cfg(all(test, not(target_arch = "wasm32")))]
12pub mod tests;
13#[cfg(all(test, not(target_arch = "wasm32")))]
14mod example;
15#[cfg(feature = "http2")]
16pub(crate) mod http1_async;
17#[cfg(feature = "http2")]
18pub(crate) mod body_stream;
19#[cfg(feature = "http2")]
20pub(crate) mod body_pump;
21#[cfg(feature = "http2")]
22pub(crate) mod sendfile;
23#[cfg(feature = "http2")]
24pub mod per_core;
25pub(crate) mod framing;
26pub mod proxy_protocol;
27
28#[cfg(not(target_arch = "wasm32"))]
34use std::io::prelude::*;
35#[cfg(not(target_arch = "wasm32"))]
36use std::borrow::Borrow;
37#[cfg(not(target_arch = "wasm32"))]
38use std::net::{IpAddr, SocketAddr, TcpListener};
39#[cfg(not(target_arch = "wasm32"))]
40use std::str::FromStr;
41#[cfg(not(target_arch = "wasm32"))]
42use std::time::Duration;
43
44#[cfg(not(target_arch = "wasm32"))]
45use crate::request::{METHOD, Request};
46#[cfg(not(target_arch = "wasm32"))]
47use crate::response::{Response, STATUS_CODE_REASON_PHRASE};
48#[cfg(not(target_arch = "wasm32"))]
49use crate::app::App;
50#[cfg(not(target_arch = "wasm32"))]
51use crate::application::Application;
52#[cfg(not(target_arch = "wasm32"))]
53use crate::entry_point::{bootstrap, get_ip_port_thread_count, get_request_allocation_size, set_default_values};
54#[cfg(not(target_arch = "wasm32"))]
55use crate::header::Header;
56#[cfg(not(target_arch = "wasm32"))]
57use crate::log::Log;
58#[cfg(not(target_arch = "wasm32"))]
59use crate::mime_type::MimeType;
60#[cfg(not(target_arch = "wasm32"))]
61use crate::range::{ContentRange, Range};
62#[cfg(not(target_arch = "wasm32"))]
63use crate::symbol::SYMBOL;
64#[cfg(not(target_arch = "wasm32"))]
65use crate::thread_pool::ThreadPool;
66
67#[cfg(not(target_arch = "wasm32"))]
68pub const REQUEST_HEAD_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
73
74pub struct Server {}
75#[cfg(not(target_arch = "wasm32"))]
76impl Server {
77 pub fn process_request(mut stream: impl Read + Write + Unpin, peer_addr: SocketAddr) -> Vec<u8> {
78 let request_allocation_size = get_request_allocation_size();
79 let mut buffer = vec![0; request_allocation_size as usize];
80 let boxed_read = stream.read(&mut buffer);
81 if boxed_read.is_err() {
82 let message = boxed_read.err().unwrap().to_string();
83 eprintln!("unable to read TCP stream {}", &message);
84
85 let raw_response = Server::bad_request_response(message);
86 let boxed_stream = stream.write(raw_response.borrow());
87 if boxed_stream.is_ok() {
88 stream.flush().unwrap();
89 };
90 return raw_response;
91 }
92
93 boxed_read.unwrap();
94 let request : &[u8] = &buffer;
95
96 let boxed_request = Request::parse_request(request);
101 if boxed_request.is_err() {
102 let message = boxed_request.err().unwrap();
103 eprintln!("unable to parse request: {}", &message);
104
105 let raw_response = Server::bad_request_response(message);
106 let boxed_stream = stream.write(raw_response.borrow());
107 if boxed_stream.is_ok() {
108 stream.flush().unwrap();
109 };
110 return raw_response;
111 }
112
113
114 let request: Request = boxed_request.unwrap();
115 let (response, request) = App::handle_request(request);
116
117
118 let log_request_response = Log::combined(&request, &response, &peer_addr);
119 println!("{}", log_request_response);
120 let raw_response = Response::generate_response(response, request);
121
122 let boxed_stream = stream.write(raw_response.borrow());
123 if boxed_stream.is_ok() {
124 stream.flush().unwrap();
125 };
126
127 raw_response
128 }
129
130 pub fn bad_request_response(message: String) -> Vec<u8> {
131 let error_request = Request {
132 method: METHOD.get.to_string(),
133 request_uri: "".to_string(),
134 http_version: "".to_string(),
135 headers: vec![],
136 body: Default::default(),
137 };
138
139 let size = message.chars().count() as u64;
140 let content_range = ContentRange {
141 unit: Range::BYTES.to_string(),
142 range: Range { start: 0, end: size },
143 size: size.to_string(),
144 body: Vec::from(message.as_bytes()),
145 content_type: MimeType::TEXT_PLAIN.to_string(),
146 };
147
148 let header_list = Header::get_header_list(&error_request);
149 let error_response: Response = Response::get_response(
150 STATUS_CODE_REASON_PHRASE.n400_bad_request,
151 Some(header_list),
152 Some(vec![content_range])
153 );
154
155 let response = Response::generate_response(error_response, error_request);
156 return response;
157 }
158
159 pub fn payload_too_large_response(message: String) -> Vec<u8> {
165 let error_request = Request {
166 method: METHOD.get.to_string(),
167 request_uri: "".to_string(),
168 http_version: "".to_string(),
169 headers: vec![],
170 body: Default::default(),
171 };
172
173 let size = message.chars().count() as u64;
174 let content_range = ContentRange {
175 unit: Range::BYTES.to_string(),
176 range: Range { start: 0, end: size },
177 size: size.to_string(),
178 body: Vec::from(message.as_bytes()),
179 content_type: MimeType::TEXT_PLAIN.to_string(),
180 };
181
182 let mut header_list = Header::get_header_list(&error_request);
183 header_list.push(Header { name: Header::_CONNECTION.into(), value: "close".into() });
184 let error_response: Response = Response::get_response(
185 STATUS_CODE_REASON_PHRASE.n413_payload_too_large,
186 Some(header_list),
187 Some(vec![content_range])
188 );
189
190 Response::generate_response(error_response, error_request)
191 }
192
193 pub fn header_fields_too_large_response() -> Vec<u8> {
197 Server::closing_error_response(
198 STATUS_CODE_REASON_PHRASE.n431_request_header_fields_too_large,
199 format!("431 Request Header Fields Too Large: the request head exceeds {} bytes", framing::MAX_HEAD_SIZE),
200 )
201 }
202
203 pub fn request_timeout_response() -> Vec<u8> {
207 Server::closing_error_response(
208 STATUS_CODE_REASON_PHRASE.n408_request_timeout,
209 format!("408 Request Timeout: the request head took longer than {} s", REQUEST_HEAD_TIMEOUT.as_secs()),
210 )
211 }
212
213 fn closing_error_response(status: &'static crate::response::StatusCodeReasonPhrase, message: String) -> Vec<u8> {
215 let error_request = Request {
216 method: METHOD.get.to_string(),
217 request_uri: "".to_string(),
218 http_version: "".to_string(),
219 headers: vec![],
220 body: Default::default(),
221 };
222
223 let size = message.chars().count() as u64;
224 let content_range = ContentRange {
225 unit: Range::BYTES.to_string(),
226 range: Range { start: 0, end: size },
227 size: size.to_string(),
228 body: Vec::from(message.as_bytes()),
229 content_type: MimeType::TEXT_PLAIN.to_string(),
230 };
231
232 let mut header_list = Header::get_header_list(&error_request);
233 header_list.push(Header { name: Header::_CONNECTION.into(), value: "close".into() });
234 let error_response: Response = Response::get_response(status, Some(header_list), Some(vec![content_range]));
235
236 Response::generate_response(error_response, error_request)
237 }
238
239 pub fn continue_response() -> Vec<u8> {
245 let dummy_request = Request {
246 method: METHOD.get.to_string(),
247 request_uri: "".to_string(),
248 http_version: "".to_string(),
249 headers: vec![],
250 body: Default::default(),
251 };
252 let response = Response::get_response(STATUS_CODE_REASON_PHRASE.n100_continue, None, None);
253 Response::generate_response(response, dummy_request)
254 }
255
256 pub fn expectation_failed_response(message: String) -> Vec<u8> {
261 let error_request = Request {
262 method: METHOD.get.to_string(),
263 request_uri: "".to_string(),
264 http_version: "".to_string(),
265 headers: vec![],
266 body: Default::default(),
267 };
268
269 let size = message.chars().count() as u64;
270 let content_range = ContentRange {
271 unit: Range::BYTES.to_string(),
272 range: Range { start: 0, end: size },
273 size: size.to_string(),
274 body: Vec::from(message.as_bytes()),
275 content_type: MimeType::TEXT_PLAIN.to_string(),
276 };
277
278 let mut header_list = Header::get_header_list(&error_request);
279 header_list.push(Header { name: Header::_CONNECTION.into(), value: "close".into() });
280 let error_response: Response = Response::get_response(
281 STATUS_CODE_REASON_PHRASE.n417_expectation_failed,
282 Some(header_list),
283 Some(vec![content_range])
284 );
285
286 Response::generate_response(error_response, error_request)
287 }
288
289 pub fn process(mut stream: impl Read + Write + Unpin,
290 connection: ConnectionInfo,
291 app: impl Application) -> Result<(), String> {
292
293 let request_allocation_size = connection.request_size;
294 let client = connection.client.clone();
295 let client_addr = SocketAddr::new(IpAddr::from_str(client.ip.as_str()).unwrap(), client.port as u16);
296
297 let max_body_size = crate::entry_point::get_max_body_size();
298
299 let mut pending: Vec<u8> = Vec::new();
302 let mut read_buffer = vec![0u8; request_allocation_size as usize];
303
304 'session: loop {
305 let mut head_started: Option<std::time::Instant> = None;
310 let head_len = loop {
311 framing::skip_leading_empty_lines(&mut pending);
312 match framing::scan_head(&pending) {
313 framing::HeadScan::Complete(n) => break Some(n),
314 framing::HeadScan::TooLarge => {
315 let _ = stream.write_all(&Server::header_fields_too_large_response());
316 let _ = stream.flush();
317 return Err("request head too large".to_string());
318 }
319 framing::HeadScan::Incomplete => {}
320 }
321 if !pending.is_empty() && head_started.is_none() {
322 head_started = Some(std::time::Instant::now());
323 }
324 match stream.read(&mut read_buffer) {
325 Ok(0) | Err(_) => break None,
327 Ok(n) => pending.extend_from_slice(&read_buffer[..n]),
328 }
329 let started = *head_started.get_or_insert_with(std::time::Instant::now);
330 if started.elapsed() > REQUEST_HEAD_TIMEOUT && framing::scan_head(&pending) == framing::HeadScan::Incomplete {
331 let _ = stream.write_all(&Server::request_timeout_response());
332 let _ = stream.flush();
333 return Err("request head timed out".to_string());
334 }
335 };
336 let Some(head_len) = head_len else { break };
337
338 let parsed = Request::parse(&pending[..head_len])
339 .and_then(|request| framing::validate_head(&pending[..head_len], &request).map(|_| request))
340 .and_then(|request| framing::body_framing(&request).map(|f| (request, f)));
341 pending.drain(..head_len);
342 let (mut request, body_framing) = match parsed {
343 Ok(parsed) => parsed,
344 Err(message) => {
345 let _ = stream.write_all(&Server::bad_request_response(message.clone()));
346 let _ = stream.flush();
347 return Err(message);
348 }
349 };
350
351 let expects_continue = match request.header(Header::_EXPECT) {
355 Some(h) if h.value.trim().eq_ignore_ascii_case("100-continue") => true,
356 Some(h) => {
357 let raw_response = Server::expectation_failed_response(format!(
358 "417 Expectation Failed: unsupported Expect value '{}'", h.value.trim()
359 ));
360 let _ = stream.write_all(&raw_response);
361 let _ = stream.flush();
362 break;
363 }
364 None => false,
365 };
366
367 match body_framing {
368 framing::BodyFraming::None => {}
369 framing::BodyFraming::Length(declared_len) => {
370 if max_body_size > 0 && declared_len > max_body_size {
371 let raw_response = Server::payload_too_large_response(format!(
372 "413 Payload Too Large: declared Content-Length {} exceeds the {} byte limit",
373 declared_len, max_body_size
374 ));
375 let _ = stream.write_all(&raw_response);
376 let _ = stream.flush();
377 break;
378 }
379
380 if expects_continue && (pending.len() as u64) < declared_len {
383 if stream.write_all(&Server::continue_response()).and_then(|_| stream.flush()).is_err() {
384 break;
385 }
386 }
387
388 while (pending.len() as u64) < declared_len {
389 match stream.read(&mut read_buffer) {
390 Ok(0) | Err(_) => break 'session, Ok(k) => pending.extend_from_slice(&read_buffer[..k]),
392 }
393 }
394 request.body = pending.drain(..declared_len as usize).collect::<Vec<u8>>().into();
395 }
396 framing::BodyFraming::Chunked => {
397 if expects_continue && pending.is_empty() {
398 if stream.write_all(&Server::continue_response()).and_then(|_| stream.flush()).is_err() {
399 break;
400 }
401 }
402
403 let mut decoder = framing::ChunkedBody::new(max_body_size);
404 loop {
405 match decoder.feed(&pending) {
406 Ok((consumed, done)) => {
407 pending.drain(..consumed);
408 if done { break; }
409 }
410 Err(framing::ChunkError::TooLarge) => {
411 let raw_response = Server::payload_too_large_response(format!(
412 "413 Payload Too Large: chunked body exceeds the {} byte limit", max_body_size
413 ));
414 let _ = stream.write_all(&raw_response);
415 let _ = stream.flush();
416 break 'session;
417 }
418 Err(framing::ChunkError::Malformed(message)) => {
419 let _ = stream.write_all(&Server::bad_request_response(message.clone()));
420 let _ = stream.flush();
421 return Err(message);
422 }
423 }
424 match stream.read(&mut read_buffer) {
425 Ok(0) | Err(_) => break 'session,
426 Ok(k) => pending.extend_from_slice(&read_buffer[..k]),
427 }
428 }
429 request.body = decoder.body.into();
430 }
431 }
432
433 let keep_alive = framing::keep_alive(&request);
434
435 let mut response = match app.execute(&request, &connection) {
436 Ok(r) => r,
437 Err(message) => {
438 let raw_response = Server::bad_request_response(message.clone());
439 let boxed_stream = stream.write(raw_response.borrow());
440 if boxed_stream.is_ok() { stream.flush().unwrap(); }
441 return Err(message);
442 }
443 };
444
445 crate::metrics::record_request();
446 crate::compression::apply_compression(&request, &mut response);
447 response.drop_content_for_status();
448
449 response.headers.push(Header {
450 name: Header::_CONNECTION.into(),
451 value: if keep_alive { "keep-alive".into() } else { "close".into() },
452 });
453
454 Log::log_access(&request, &response, &client_addr);
455
456 if let Some(reader) = response.stream_pipe.take() {
457 if let Err(e) = Server::pipe_stream(&mut stream, response, request, reader) {
458 return Err(e);
459 }
460 } else if let Some(ref filepath) = response.stream_file.clone() {
461 if let Err(e) = Server::write_chunked_file(&mut stream, response, request, filepath) {
462 return Err(e);
463 }
464 } else {
465 let raw_response = Response::generate_response(response, request);
466 if let Err(e) = stream.write_all(raw_response.borrow()) {
468 return Err(e.to_string());
469 }
470 stream.flush().unwrap();
471 }
472
473 if !keep_alive { break; }
474 }
475
476 Ok(())
477 }
478
479 pub(crate) fn write_chunked_file(
482 stream: &mut impl Write,
483 response: Response,
484 request: Request,
485 filepath: &str,
486 ) -> Result<(), String> {
487 use std::fs::File;
488 use std::io::Read as _;
489
490 let (head, chunked) = Server::stream_file_head(response);
491 stream.write_all(&head).map_err(|e| e.to_string())?;
492
493 if request.method != METHOD.head {
494 let mut file = File::open(filepath).map_err(|e| e.to_string())?;
495 let mut buf = vec![0u8; 65536];
496 loop {
497 let n = file.read(&mut buf).map_err(|e| e.to_string())?;
498 if n == 0 { break; }
499 if chunked {
500 stream.write_all(format!("{:x}\r\n", n).as_bytes()).map_err(|e| e.to_string())?;
502 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
503 stream.write_all(b"\r\n").map_err(|e| e.to_string())?;
504 } else {
505 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
506 }
507 }
508 if chunked {
509 stream.write_all(b"0\r\n\r\n").map_err(|e| e.to_string())?;
511 }
512 }
513
514 stream.flush().map_err(|e| e.to_string())
515 }
516
517 pub(crate) fn stream_file_head(mut response: Response) -> (Vec<u8>, bool) {
524 let chunked = !response.headers.iter().any(|h| h.name.eq_ignore_ascii_case(Header::_CONTENT_LENGTH));
525 if chunked {
526 response.headers.push(Header {
527 name: Header::_TRANSFER_ENCODING.into(),
528 value: "chunked".into(),
529 });
530 }
531
532 let status = [
534 response.http_version.clone(),
535 response.status_code.to_string(),
536 Header::single_line(&response.reason_phrase).into_owned(),
537 ].join(SYMBOL.whitespace);
538
539 let mut headers_str = SYMBOL.new_line_carriage_return.to_string();
540 for header in &response.headers {
541 headers_str.push_str(&Header::single_line(&header.name));
542 headers_str.push_str(Header::NAME_VALUE_SEPARATOR);
543 headers_str.push_str(&Header::single_line(&header.value));
544 headers_str.push_str(SYMBOL.new_line_carriage_return);
545 }
546 let head = format!("{}{}{}", status, headers_str, SYMBOL.new_line_carriage_return);
547 (head.into_bytes(), chunked)
548 }
549
550 pub(crate) fn pipe_stream(
558 stream: &mut impl Write,
559 mut response: Response,
560 request: Request,
561 mut reader: Box<dyn std::io::Read + Send>,
562 ) -> Result<(), String> {
563 let backend_is_chunked = response.headers.iter().any(|h| {
567 h.name.eq_ignore_ascii_case("transfer-encoding")
568 && h.value.to_lowercase().contains("chunked")
569 });
570
571 response.headers.retain(|h| !h.name.eq_ignore_ascii_case("content-length"));
572 if !backend_is_chunked {
573 response.headers.push(Header {
574 name: Header::_TRANSFER_ENCODING.into(),
575 value: "chunked".into(),
576 });
577 }
578
579 let status = [
580 response.http_version.clone(),
581 response.status_code.to_string(),
582 Header::single_line(&response.reason_phrase).into_owned(),
583 ].join(SYMBOL.whitespace);
584
585 let mut head = format!("{}\r\n", status);
586 for header in &response.headers {
587 head.push_str(&Header::single_line(&header.name));
588 head.push_str(Header::NAME_VALUE_SEPARATOR);
589 head.push_str(&Header::single_line(&header.value));
590 head.push_str(SYMBOL.new_line_carriage_return);
591 }
592 head.push_str(SYMBOL.new_line_carriage_return);
593 stream.write_all(head.as_bytes()).map_err(|e| e.to_string())?;
594
595 if request.method != METHOD.head {
596 let mut buf = [0u8; 8192];
597 if backend_is_chunked {
598 loop {
601 match reader.read(&mut buf) {
602 Ok(0) | Err(_) => break,
603 Ok(n) => {
604 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
605 stream.flush().map_err(|e| e.to_string())?;
606 }
607 }
608 }
609 } else {
610 loop {
614 match reader.read(&mut buf) {
615 Ok(0) | Err(_) => break,
616 Ok(n) => {
617 stream
618 .write_all(format!("{:x}\r\n", n).as_bytes())
619 .map_err(|e| e.to_string())?;
620 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
621 stream.write_all(b"\r\n").map_err(|e| e.to_string())?;
622 stream.flush().map_err(|e| e.to_string())?;
623 }
624 }
625 }
626 stream.write_all(b"0\r\n\r\n").map_err(|e| e.to_string())?;
627 }
628 }
629
630 stream.flush().map_err(|e| e.to_string())
631 }
632
633 pub fn setup() -> Result<(TcpListener, ThreadPool), String> {
636 let info = Log::info("Rust Web Server");
637 println!("{}", info);
638
639 let usage_info = Log::usage_information();
640 println!("{}", usage_info);
641
642
643 println!("RWS Configuration Start: \n");
644
645 set_default_values();
646 bootstrap();
647
648 #[cfg(feature = "secrets")]
649 crate::secrets::resolve_env_vars().map_err(|e| e.to_string())?;
650
651 println!("\nRWS Configuration End\n\n");
652
653
654 let (ip, port, thread_count) = get_ip_port_thread_count();
655
656
657 let mut ip_readable = ip.to_string();
658
659 if ip.contains(":") {
660 ip_readable = [SYMBOL.opening_square_bracket, &ip, SYMBOL.closing_square_bracket].join("");
661 }
662
663 let bind_addr = [ip_readable, SYMBOL.colon.to_string(), port.to_string()].join(SYMBOL.empty_string);
664
665 #[cfg(feature = "http2")]
666 let protocol = {
667 let cert = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE).unwrap_or_default();
668 if cert.is_empty() { "http" } else { "https" }
669 };
670 #[cfg(not(feature = "http2"))]
671 let protocol = "http";
672
673 println!("Setting up {}://{}...", protocol, &bind_addr);
674
675 let boxed_listener = TcpListener::bind(&bind_addr);
676 if boxed_listener.is_err() {
677 let message = format!("unable to set up TCP listener: {}", boxed_listener.err().unwrap());
678 return Err(message);
679 }
680
681 let listener = boxed_listener.unwrap();
682 let pool = ThreadPool::new(thread_count as usize);
683
684
685 let server_url_thread_count = Log::server_url_thread_count(protocol, &bind_addr, thread_count);
686 println!("{}", server_url_thread_count);
687
688 Ok((listener, pool))
689 }
690
691 pub fn run(listener: TcpListener,
699 pool: ThreadPool,
700 app: impl Application + Send + 'static + Clone) {
701 #[cfg(feature = "http1")]
702 {
703 use std::sync::Arc;
704 use std::sync::atomic::{AtomicBool, Ordering};
705
706 let shutdown = Arc::new(AtomicBool::new(false));
707 let s = shutdown.clone();
708 if let Err(e) = ctrlc::set_handler(move || {
709 s.store(true, Ordering::SeqCst);
710 }) {
711 eprintln!("unable to install signal handler: {}", e);
712 }
713 crate::config_reload::install_sighup_handler();
714 if let Err(e) = listener.set_nonblocking(true) {
715 eprintln!("unable to set non-blocking listener: {}", e);
716 }
717
718 loop {
719 if shutdown.load(Ordering::SeqCst) {
720 break;
721 }
722 if crate::config_reload::RELOAD_REQUESTED
723 .compare_exchange(true, false, Ordering::SeqCst, Ordering::Relaxed)
724 .is_ok()
725 {
726 crate::config_reload::reload();
727 }
728 match listener.accept() {
729 Ok((stream, peer_addr)) => {
730 Server::dispatch_connection(stream, peer_addr, &pool, app.clone());
731 }
732 Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
733 std::thread::sleep(Duration::from_millis(10));
734 }
735 Err(e) => {
736 eprintln!("accept error: {}", e);
737 break;
738 }
739 }
740 }
741
742 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
743 println!("Shutting down — waiting for in-flight connections to finish");
744 pool.join();
745 println!("Server stopped");
746 }
747
748 #[cfg(not(feature = "http1"))]
749 {
750 for boxed_stream in listener.incoming() {
751 match boxed_stream {
752 Err(e) => {
753 eprintln!("unable to get TCP stream: {}", e);
754 return;
755 }
756 Ok(stream) => {
757 let peer_addr = match stream.peer_addr() {
758 Ok(a) => a,
759 Err(e) => {
760 eprintln!("unable to read peer addr: {}", e);
761 return;
762 }
763 };
764 Server::dispatch_connection(stream, peer_addr, &pool, app.clone());
765 }
766 }
767 }
768 }
769 }
770
771 fn dispatch_connection(
772 stream: std::net::TcpStream,
773 peer_addr: std::net::SocketAddr,
774 pool: &ThreadPool,
775 app: impl Application + Send + 'static + Clone,
776 ) {
777 print!("Connection established, ");
778 if let Ok(local) = stream.local_addr() {
779 print!("local addr: {}", local);
780 }
781 println!(", peer addr: {}", peer_addr);
782
783 let (server_ip, server_port, _thread_count) = get_ip_port_thread_count();
784 let connection = ConnectionInfo {
785 client: Address {
786 ip: peer_addr.ip().to_string(),
787 port: peer_addr.port() as i32,
788 },
789 server: Address {
790 ip: server_ip,
791 port: server_port,
792 },
793 request_size: get_request_allocation_size(),
794 sni_hostname: None,
795 };
796
797 if let Err(e) = stream.set_read_timeout(Some(Duration::from_secs(30))) {
798 eprintln!("failed to set read timeout: {}", e);
799 }
800
801 pool.execute(move || {
802 let mut stream = stream;
803 let mut connection = connection;
804 if proxy_protocol::enabled() {
805 match proxy_protocol::read_blocking(&mut stream) {
807 Ok(Some(source)) => {
808 connection.client = Address { ip: source.ip().to_string(), port: source.port() as i32 };
809 }
810 Ok(None) => {}
811 Err(e) => {
812 eprintln!("PROXY protocol header from {}: {}", peer_addr, e);
813 return;
814 }
815 }
816 }
817 crate::metrics::connection_open();
818 let result = Server::process(stream, connection, app);
819 crate::metrics::connection_close();
820 if let Err(msg) = result {
821 crate::metrics::record_error();
822 eprintln!("{}", msg);
823 }
824 });
825 }
826
827}
828
829#[derive(Clone)]
831pub struct ConnectionInfo {
832 pub client: Address,
834 pub server: Address,
836 pub request_size: i64,
838 pub sni_hostname: Option<String>,
841}
842
843#[derive(Clone)]
845pub struct Address {
846 pub ip: String,
847 pub port: i32
848}
849
850impl ConnectionInfo {
851 pub fn peer_addr(&self) -> Option<std::net::SocketAddr> {
854 self.client.to_socket_addr()
855 }
856}
857
858impl Address {
859 pub fn to_socket_addr(&self) -> Option<std::net::SocketAddr> {
862 let ip: std::net::IpAddr = self.ip.parse().ok()?;
863 let port = u16::try_from(self.port).ok()?;
864 Some(std::net::SocketAddr::new(ip, port))
865 }
866}
867
868#[cfg(feature = "http2")]
871async fn serve_tls_connection(
872 mut tcp_stream: tokio::net::TcpStream,
873 peer_addr: std::net::SocketAddr,
874 acceptor: tokio_rustls::TlsAcceptor,
875 app: impl Application + Send + 'static + Clone,
876) {
877 let _ = tcp_stream.set_nodelay(true);
878 let Some(peer_addr) = client_address(&mut tcp_stream, peer_addr).await else { return };
879 let timed_out = || std::io::Error::from(std::io::ErrorKind::TimedOut);
880 let handshake = async {
881 #[cfg(feature = "acme")]
882 if crate::acme::on_demand::enabled() {
883 let lazy = tokio_rustls::LazyConfigAcceptor::new(rustls::server::Acceptor::default(), tcp_stream);
887 let start = tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, lazy).await.map_err(|_| timed_out())??;
888 let hello = start.client_hello();
889 let name = hello.server_name().filter(|_| !crate::acme::tls_alpn::is_challenge(&hello)).map(str::to_string);
890 if let Some(name) = name {
891 crate::acme::on_demand::ensure(&name).await;
892 }
893 let finish = start.into_stream(acceptor.config().clone());
894 return tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, finish).await.map_err(|_| timed_out())?;
895 }
896 tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, acceptor.accept(tcp_stream)).await.map_err(|_| timed_out())?
897 };
898 match handshake.await {
899 Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {} Err(e) => eprintln!("TLS handshake failed: {}", e),
901 Ok(tls_stream) => {
902 let server_conn = tls_stream.get_ref().1;
903 let sni = server_conn.server_name().map(|s| s.to_string());
904 let protocol = server_conn.alpn_protocol().map(|p| p.to_vec());
905
906 match protocol.as_deref() {
907 #[cfg(feature = "acme")]
909 Some(crate::acme::tls_alpn::ALPN) => {}
910 Some(b"h2") => {
911 if let Err(e) = crate::h2_server::handle_connection(tls_stream, peer_addr, sni, app).await {
912 eprintln!("H2 connection error: {}", e);
913 }
914 }
915 _ => {
916 crate::metrics::connection_open();
917 let result = http1_async::serve(tls_stream, peer_addr, sni, true, app).await;
918 crate::metrics::connection_close();
919 if let Err(e) = result {
920 crate::metrics::record_error();
921 eprintln!("H1 TLS error: {}", e);
922 }
923 }
924 }
925 }
926 }
927}
928
929#[cfg(feature = "http2")]
931async fn serve_plain_connection(
932 tcp_stream: tokio::net::TcpStream,
933 peer_addr: std::net::SocketAddr,
934 app: impl Application + Send + 'static + Clone,
935) {
936 let mut tcp_stream = tcp_stream;
939 let _ = tcp_stream.set_nodelay(true);
940 let Some(peer_addr) = client_address(&mut tcp_stream, peer_addr).await else { return };
941 if starts_with_h2_preface(&tcp_stream).await {
942 if let Err(e) = crate::h2_server::handle_connection(tcp_stream, peer_addr, None, app).await {
943 eprintln!("H2C connection error: {}", e);
944 }
945 return;
946 }
947 crate::metrics::connection_open();
948 let result = http1_async::serve(tcp_stream, peer_addr, None, false, app).await;
949 crate::metrics::connection_close();
950 if let Err(e) = result {
951 crate::metrics::record_error();
952 eprintln!("{}", e);
953 }
954}
955
956#[cfg(feature = "http2")]
960async fn client_address(tcp_stream: &mut tokio::net::TcpStream, peer_addr: std::net::SocketAddr) -> Option<std::net::SocketAddr> {
961 if !proxy_protocol::enabled() {
962 return Some(peer_addr);
963 }
964 match tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, proxy_protocol::read_async(tcp_stream)).await {
965 Ok(Ok(source)) => Some(source.unwrap_or(peer_addr)),
966 Ok(Err(e)) => {
967 eprintln!("PROXY protocol header from {}: {}", peer_addr, e);
968 None
969 }
970 Err(_) => None,
971 }
972}
973
974#[cfg(feature = "http2")]
979async fn starts_with_h2_preface(tcp_stream: &tokio::net::TcpStream) -> bool {
980 const PREFACE: &[u8; 24] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
981 let mut seen = [0u8; 24];
982 let deadline = tokio::time::Instant::now() + http1_async::READ_TIMEOUT;
983 loop {
984 let n = match tokio::time::timeout_at(deadline, tcp_stream.peek(&mut seen)).await {
985 Ok(Ok(n)) => n,
986 _ => return false,
987 };
988 if n == 0 || seen[..n] != PREFACE[..n] {
989 return false;
990 }
991 if n == PREFACE.len() {
992 return true;
993 }
994 tokio::time::sleep(std::time::Duration::from_millis(5)).await;
996 }
997}
998
999#[cfg(feature = "http2")]
1002async fn accept_backoff(e: std::io::Error) {
1003 eprintln!("TCP accept error: {}", e);
1004 tokio::time::sleep(std::time::Duration::from_millis(50)).await;
1005}
1006
1007#[cfg(feature = "http2")]
1009fn shutdown_requests() -> &'static tokio::sync::watch::Sender<bool> {
1010 static REQUESTS: std::sync::OnceLock<tokio::sync::watch::Sender<bool>> = std::sync::OnceLock::new();
1011 REQUESTS.get_or_init(|| tokio::sync::watch::channel(false).0)
1012}
1013
1014#[cfg(feature = "http2")]
1018pub fn request_shutdown() {
1019 shutdown_requests().send_replace(true);
1020}
1021
1022#[cfg(feature = "http2")]
1025async fn sigterm() {
1026 let requested = async {
1027 let mut requests = shutdown_requests().subscribe();
1028 let _ = requests.wait_for(|stop| *stop).await;
1029 };
1030 #[cfg(unix)]
1031 {
1032 if let Ok(mut s) = tokio::signal::unix::signal(
1033 tokio::signal::unix::SignalKind::terminate()
1034 ) {
1035 tokio::select! {
1036 _ = s.recv() => {}
1037 _ = requested => {}
1038 }
1039 } else {
1040 requested.await
1041 }
1042 }
1043 #[cfg(not(unix))]
1044 requested.await
1045}
1046
1047#[cfg(feature = "http2")]
1049async fn sighup() {
1050 #[cfg(unix)]
1051 {
1052 if let Ok(mut s) = tokio::signal::unix::signal(
1053 tokio::signal::unix::SignalKind::hangup()
1054 ) {
1055 s.recv().await;
1056 } else {
1057 std::future::pending::<()>().await
1058 }
1059 }
1060 #[cfg(not(unix))]
1061 std::future::pending::<()>().await
1062}
1063
1064#[cfg(feature = "http2")]
1071pub(crate) async fn bind_all_families(ip: &str, port: u16) -> Result<Vec<tokio::net::TcpListener>, String> {
1072 use tokio::net::TcpListener;
1073 if ip != "0.0.0.0" {
1074 let addr = if ip.contains(':') { format!("[{ip}]:{port}") } else { format!("{ip}:{port}") };
1075 return TcpListener::bind(&addr).await.map(|l| vec![l]).map_err(|e| format!("{addr}: {e}"));
1076 }
1077 let mut listeners = Vec::new();
1078 let mut errors = Vec::new();
1079 for addr in [format!("[::]:{port}"), format!("0.0.0.0:{port}")] {
1080 match TcpListener::bind(&addr).await {
1081 Ok(l) => listeners.push(l),
1082 Err(e) => errors.push(format!("{addr}: {e}")),
1083 }
1084 }
1085 if listeners.is_empty() {
1086 return Err(errors.join("; "));
1087 }
1088 Ok(listeners)
1089}
1090
1091#[cfg(feature = "http2")]
1092impl Server {
1093 pub async fn run_tls(
1094 listener: TcpListener,
1095 pool: ThreadPool,
1096 app: impl Application + Send + 'static + Clone,
1097 ) {
1098 use crate::tls::create_tls_acceptor_from_vhosts;
1099
1100 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1101 .unwrap_or_default();
1102 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
1103 .unwrap_or_default();
1104
1105 if cert_path.is_empty() || key_path.is_empty() {
1106 println!("No TLS certificate configured — serving plain HTTP/1.1.");
1107 drop(pool);
1108 Server::run_plain(listener, app).await;
1109 return;
1110 }
1111
1112 let vhosts = crate::entry_point::get_virtual_hosts();
1113 let mut tls_acceptor = match create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1114 Ok(a) => a,
1115 Err(e) => {
1116 eprintln!("TLS setup failed: {}", e);
1117 return;
1118 }
1119 };
1120 #[cfg(feature = "acme")]
1122 crate::acme::tls_alpn::note_tls_listener();
1123
1124 #[cfg(unix)]
1125 if per_core::enabled() {
1126 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2), per-core runtimes...");
1127 let (acceptor_tx, acceptor_rx) = tokio::sync::watch::channel(tls_acceptor);
1128 let accept_loop = move |listener: tokio::net::TcpListener, mut stop: tokio::sync::watch::Receiver<bool>| {
1129 let app = app.clone();
1130 let acceptor_rx = acceptor_rx.clone();
1131 async move {
1132 loop {
1133 tokio::select! {
1134 result = listener.accept() => match result {
1135 Ok((tcp_stream, peer_addr)) => {
1136 let acceptor = acceptor_rx.borrow().clone();
1137 tokio::spawn(serve_tls_connection(tcp_stream, peer_addr, acceptor, app.clone()));
1138 }
1139 Err(e) => accept_backoff(e).await,
1140 },
1141 _ = per_core::stopped(&mut stop) => break,
1142 }
1143 }
1144 }
1145 };
1146 Server::run_per_core(listener, accept_loop, move || {
1147 let vhosts = crate::entry_point::get_virtual_hosts();
1148 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1149 let _ = acceptor_tx.send(new_acceptor);
1150 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
1151 }
1152 })
1153 .await;
1154 return;
1155 }
1156
1157 listener
1158 .set_nonblocking(true)
1159 .expect("failed to set TCP listener to non-blocking");
1160 let tokio_listener = tokio::net::TcpListener::from_std(listener)
1161 .expect("failed to convert TCP listener to tokio");
1162
1163 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2)...");
1164
1165 loop {
1166 tokio::select! {
1167 result = tokio_listener.accept() => {
1168 match result {
1169 Ok((tcp_stream, peer_addr)) => {
1170 tokio::spawn(serve_tls_connection(tcp_stream, peer_addr, tls_acceptor.clone(), app.clone()));
1171 }
1172 Err(e) => eprintln!("TCP accept error: {}", e),
1173 }
1174 }
1175 _ = tokio::signal::ctrl_c() => {
1176 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1177 println!("\nShutting down gracefully (SIGINT).");
1178 break;
1179 }
1180 _ = sigterm() => {
1181 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1182 println!("\nShutting down gracefully (SIGTERM).");
1183 break;
1184 }
1185 _ = sighup() => {
1186 crate::config_reload::reload();
1187 let vhosts = crate::entry_point::get_virtual_hosts();
1188 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1189 tls_acceptor = new_acceptor;
1190 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
1191 }
1192 }
1193 }
1194 }
1195 }
1196
1197 pub async fn run_plain(listener: TcpListener, app: impl Application + Send + 'static + Clone) {
1203 #[cfg(unix)]
1204 if per_core::enabled() {
1205 let accept_loop = move |listener: tokio::net::TcpListener, mut stop: tokio::sync::watch::Receiver<bool>| {
1206 let app = app.clone();
1207 async move {
1208 loop {
1209 tokio::select! {
1210 result = listener.accept() => match result {
1211 Ok((tcp_stream, peer_addr)) => {
1212 tokio::spawn(serve_plain_connection(tcp_stream, peer_addr, app.clone()));
1213 }
1214 Err(e) => accept_backoff(e).await,
1215 },
1216 _ = per_core::stopped(&mut stop) => break,
1217 }
1218 }
1219 }
1220 };
1221 Server::run_per_core(listener, accept_loop, || {}).await;
1222 return;
1223 }
1224
1225 listener
1226 .set_nonblocking(true)
1227 .expect("failed to set TCP listener to non-blocking");
1228 let tokio_listener = tokio::net::TcpListener::from_std(listener)
1229 .expect("failed to convert TCP listener to tokio");
1230
1231 loop {
1232 tokio::select! {
1233 result = tokio_listener.accept() => {
1234 match result {
1235 Ok((tcp_stream, peer_addr)) => {
1236 tokio::spawn(serve_plain_connection(tcp_stream, peer_addr, app.clone()));
1237 }
1238 Err(e) => accept_backoff(e).await,
1239 }
1240 }
1241 _ = tokio::signal::ctrl_c() => {
1242 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1243 println!("\nShutting down gracefully (SIGINT).");
1244 break;
1245 }
1246 _ = sigterm() => {
1247 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1248 println!("\nShutting down gracefully (SIGTERM).");
1249 break;
1250 }
1251 _ = sighup() => {
1252 crate::config_reload::reload();
1253 }
1254 }
1255 }
1256 }
1257
1258 #[cfg(unix)]
1263 async fn run_per_core<F, Fut>(listener: TcpListener, accept_loop: F, on_reload: impl Fn())
1264 where
1265 F: Fn(tokio::net::TcpListener, tokio::sync::watch::Receiver<bool>) -> Fut + Send + Clone + 'static,
1266 Fut: std::future::Future<Output = ()>,
1267 {
1268 let addr = match listener.local_addr() {
1269 Ok(a) => a,
1270 Err(e) => return eprintln!("per-core runtimes: {}", e),
1271 };
1272 drop(listener);
1274 let count = per_core::runtime_count();
1275 let (stop_tx, stop_rx) = tokio::sync::watch::channel(false);
1276 let handles = per_core::spawn(addr, count, stop_rx, accept_loop);
1277 println!("Started {} per-core runtimes on {}.", handles.len(), addr);
1278
1279 loop {
1280 tokio::select! {
1281 _ = tokio::signal::ctrl_c() => {
1282 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1283 println!("\nShutting down gracefully (SIGINT).");
1284 break;
1285 }
1286 _ = sigterm() => {
1287 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1288 println!("\nShutting down gracefully (SIGTERM).");
1289 break;
1290 }
1291 _ = sighup() => {
1292 crate::config_reload::reload();
1293 on_reload();
1294 }
1295 }
1296 }
1297 let _ = stop_tx.send(true);
1298 let _ = tokio::task::spawn_blocking(move || {
1299 for h in handles {
1300 let _ = h.join();
1301 }
1302 })
1303 .await;
1304 }
1305
1306 pub async fn run_redirect() {
1310 use std::env;
1311
1312 let cert_path = env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1313 .unwrap_or_default();
1314 if cert_path.is_empty() {
1315 return;
1316 }
1317
1318 let redirect_port_str = env::var(crate::entry_point::Config::RWS_CONFIG_HTTP_REDIRECT_PORT)
1319 .unwrap_or_default();
1320 if redirect_port_str.is_empty() {
1321 return;
1322 }
1323
1324 let redirect_port: u16 = match redirect_port_str.parse() {
1325 Ok(p) => p,
1326 Err(_) => {
1327 eprintln!("Invalid RWS_CONFIG_HTTP_REDIRECT_PORT: {}", redirect_port_str);
1328 return;
1329 }
1330 };
1331
1332 let (server_ip, server_port, _) = get_ip_port_thread_count();
1333 let listeners = match bind_all_families(&server_ip, redirect_port).await {
1334 Ok(l) => l,
1335 Err(e) => {
1336 eprintln!("HTTP redirect listener error on port {}: {}", redirect_port, e);
1337 return;
1338 }
1339 };
1340
1341 println!("HTTP→HTTPS redirect listening on http://{}:{}", server_ip, redirect_port);
1342 #[cfg(feature = "acme")]
1343 crate::acme::note_redirect_listener(redirect_port);
1344
1345 for listener in listeners {
1346 tokio::spawn(async move {
1347 loop {
1348 match listener.accept().await {
1349 Ok((stream, _peer)) => {
1350 tokio::spawn(Server::handle_redirect_connection(stream, server_port));
1351 }
1352 Err(e) => eprintln!("HTTP redirect accept error: {}", e),
1353 }
1354 }
1355 });
1356 }
1357
1358 loop {
1359 tokio::select! {
1360 _ = tokio::signal::ctrl_c() => {
1361 println!("\nShutting down HTTP redirect listener (SIGINT).");
1362 break;
1363 }
1364 _ = sigterm() => {
1365 println!("\nShutting down HTTP redirect listener (SIGTERM).");
1366 break;
1367 }
1368 _ = sighup() => {
1369 crate::config_reload::reload();
1370 }
1371 }
1372 }
1373 }
1374
1375 pub(crate) async fn handle_redirect_connection(mut stream: tokio::net::TcpStream, https_port: i32) {
1378 use tokio::io::{AsyncReadExt, AsyncWriteExt};
1379 let mut buf = vec![0u8; 4096];
1380 let n = match stream.read(&mut buf).await {
1381 Ok(n) => n,
1382 Err(_) => return,
1383 };
1384 let text = String::from_utf8_lossy(&buf[..n]);
1385
1386 let uri = text.lines()
1387 .next()
1388 .and_then(|line| line.split_whitespace().nth(1))
1389 .unwrap_or("/")
1390 .to_string();
1391
1392 #[cfg(feature = "acme")]
1395 if let Some(challenge) = crate::acme::challenge_http_response_shared(&uri).await {
1396 let _ = stream.write_all(challenge.as_bytes()).await;
1397 return;
1398 }
1399
1400 let host_header = text.lines()
1401 .find(|l| l.to_lowercase().starts_with("host:"))
1402 .map(|l| l[5..].trim().to_string());
1403
1404 let location = match host_header {
1405 Some(h) => {
1406 let h_no_port = if h.starts_with('[') {
1408 h.find(']')
1410 .map(|i| h[..=i].to_string())
1411 .unwrap_or(h.clone())
1412 } else {
1413 h.rfind(':')
1414 .map(|i| h[..i].to_string())
1415 .unwrap_or(h.clone())
1416 };
1417 if https_port == 443 {
1418 format!("https://{}{}", h_no_port, uri)
1419 } else {
1420 format!("https://{}:{}{}", h_no_port, https_port, uri)
1421 }
1422 }
1423 None => format!("https://localhost:{}{}", https_port, uri),
1424 };
1425
1426 let response = format!(
1427 "HTTP/1.1 301 Moved Permanently\r\nLocation: {}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n",
1428 location
1429 );
1430 let _ = stream.write_all(response.as_bytes()).await;
1431 }
1432
1433}
1434
1435#[cfg(feature = "http3")]
1436impl Server {
1437 pub async fn run_quic(
1438 app: impl Application + Send + 'static + Clone,
1439 ) {
1440 use crate::tls::create_quinn_server_config_from_vhosts;
1441 use crate::h3_handler;
1442
1443 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1444 .unwrap_or_default();
1445 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
1446 .unwrap_or_default();
1447
1448 if cert_path.is_empty() || key_path.is_empty() {
1449 return;
1450 }
1451
1452 let vhosts = crate::entry_point::get_virtual_hosts();
1453 let server_config = match create_quinn_server_config_from_vhosts(&vhosts, &cert_path, &key_path) {
1454 Ok(c) => c,
1455 Err(e) => {
1456 eprintln!("QUIC TLS setup failed: {}", e);
1457 return;
1458 }
1459 };
1460
1461 let (server_ip, server_port, _) = get_ip_port_thread_count();
1462 let bind_addr = format!("{}:{}", server_ip, server_port);
1463 let addr: std::net::SocketAddr = match bind_addr.parse() {
1464 Ok(a) => a,
1465 Err(e) => {
1466 eprintln!("Invalid QUIC bind address '{}': {}", bind_addr, e);
1467 return;
1468 }
1469 };
1470
1471 let endpoint = match quinn::Endpoint::server(server_config, addr) {
1472 Ok(e) => e,
1473 Err(e) => {
1474 eprintln!("QUIC endpoint error: {}", e);
1475 return;
1476 }
1477 };
1478
1479 println!("Listening for QUIC/HTTP3 on UDP {}:{}", server_ip, server_port);
1480
1481 loop {
1482 tokio::select! {
1483 maybe = endpoint.accept() => {
1484 match maybe {
1485 Some(incoming) => {
1486 let app = app.clone();
1487 tokio::spawn(async move {
1488 match incoming.await {
1489 Ok(conn) => {
1490 let peer_addr = conn.remote_address();
1491 if let Err(e) = h3_handler::handle_connection(conn, peer_addr, app).await {
1492 eprintln!("H3 connection error: {}", e);
1493 }
1494 }
1495 Err(e) => eprintln!("QUIC connection error: {}", e),
1496 }
1497 });
1498 }
1499 None => break,
1500 }
1501 }
1502 _ = tokio::signal::ctrl_c() => {
1503 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1504 println!("\nShutting down QUIC (SIGINT).");
1505 endpoint.close(0u32.into(), b"shutdown");
1506 break;
1507 }
1508 _ = sigterm() => {
1509 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1510 println!("\nShutting down QUIC (SIGTERM).");
1511 endpoint.close(0u32.into(), b"shutdown");
1512 break;
1513 }
1514 _ = sighup() => {
1515 crate::config_reload::reload();
1516 }
1517 }
1518 }
1519 }
1520}
1521
1522