1#[cfg(all(test, not(target_arch = "wasm32")))]
12pub mod tests;
13#[cfg(all(any(test, feature = "test-support"), not(target_arch = "wasm32")))]
15#[doc(hidden)]
16pub mod test_support {
17 use std::cmp::min;
18 use std::io::{Read, Write};
19
20 pub struct MockTcpStream {
21 pub read_data: Vec<u8>,
22 pub write_data: Vec<u8>,
23 }
24
25 impl Read for MockTcpStream {
26 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
27 let size : usize = min(self.read_data.len(), buf.len());
28 buf[..size].copy_from_slice(&self.read_data[..size]);
29 Ok(size)
30 }
31 }
32
33 impl Write for MockTcpStream {
34
35 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
36 self.write_data = Vec::from(buf);
37 Ok(buf.len())
38 }
39
40 fn flush(&mut self) -> std::io::Result<()> {
41 Ok(())
42 }
43 }
44
45 impl Unpin for MockTcpStream {}
46}
47#[cfg(all(test, not(target_arch = "wasm32")))]
48mod example;
49#[cfg(feature = "http2")]
50#[doc(hidden)]
51pub mod http1_async;
52mod chunked_decoder;
53#[cfg(feature = "http2")]
54#[doc(hidden)]
55pub mod body_stream;
56#[cfg(feature = "http2")]
57pub(crate) mod body_pump;
58#[cfg(feature = "http2")]
59pub(crate) mod sendfile;
60#[cfg(feature = "http2")]
61pub mod per_core;
62#[doc(hidden)]
63pub mod framing;
64pub mod proxy_protocol;
65
66#[cfg(not(target_arch = "wasm32"))]
72use std::io::prelude::*;
73#[cfg(not(target_arch = "wasm32"))]
74use std::borrow::Borrow;
75#[cfg(not(target_arch = "wasm32"))]
76use std::net::{IpAddr, SocketAddr, TcpListener};
77#[cfg(not(target_arch = "wasm32"))]
78use std::str::FromStr;
79#[cfg(not(target_arch = "wasm32"))]
80use std::time::Duration;
81
82#[cfg(not(target_arch = "wasm32"))]
83use crate::request::{METHOD, Request};
84#[cfg(not(target_arch = "wasm32"))]
85use crate::response::{Response, STATUS_CODE_REASON_PHRASE};
86#[cfg(not(target_arch = "wasm32"))]
87use crate::app::App;
88#[cfg(not(target_arch = "wasm32"))]
89use crate::application::Application;
90#[cfg(not(target_arch = "wasm32"))]
91use crate::entry_point::{bootstrap, get_ip_port_thread_count, get_request_allocation_size, set_default_values};
92#[cfg(not(target_arch = "wasm32"))]
93use crate::header::Header;
94#[cfg(not(target_arch = "wasm32"))]
95use crate::log::Log;
96#[cfg(not(target_arch = "wasm32"))]
97use crate::symbol::SYMBOL;
98#[cfg(not(target_arch = "wasm32"))]
99use crate::thread_pool::ThreadPool;
100
101#[cfg(not(target_arch = "wasm32"))]
102pub const REQUEST_HEAD_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(30);
107
108#[doc(hidden)]
112pub const PIPE_CHUNK: usize = 64 * 1024;
113
114#[cfg(not(target_arch = "wasm32"))]
118fn single_content_length(response: &Response) -> Option<u64> {
119 let mut found: Option<u64> = None;
120 for h in response.headers.iter().filter(|h| h.name.eq_ignore_ascii_case("content-length")) {
121 let value = h.value.trim();
122 if value.is_empty() || !value.bytes().all(|b| b.is_ascii_digit()) {
123 return None;
124 }
125 let len: u64 = value.parse().ok()?;
126 match found {
127 Some(prev) if prev != len => return None,
128 _ => found = Some(len),
129 }
130 }
131 found
132}
133
134pub struct Server {}
135#[cfg(not(target_arch = "wasm32"))]
136impl Server {
137 pub fn process_request(mut stream: impl Read + Write + Unpin, peer_addr: SocketAddr) -> Vec<u8> {
138 let request_allocation_size = get_request_allocation_size();
139 let mut buffer = vec![0; request_allocation_size as usize];
140 let boxed_read = stream.read(&mut buffer);
141 if boxed_read.is_err() {
142 let message = boxed_read.err().unwrap().to_string();
143 eprintln!("unable to read TCP stream {}", &message);
144
145 let raw_response = Server::bad_request_response(message);
146 let boxed_stream = stream.write(raw_response.borrow());
147 if boxed_stream.is_ok() {
148 stream.flush().unwrap();
149 };
150 return raw_response;
151 }
152
153 boxed_read.unwrap();
154 let request : &[u8] = &buffer;
155
156 let boxed_request = Request::parse_request(request);
161 if boxed_request.is_err() {
162 let message = boxed_request.err().unwrap();
163 eprintln!("unable to parse request: {}", &message);
164
165 let raw_response = Server::bad_request_response(message);
166 let boxed_stream = stream.write(raw_response.borrow());
167 if boxed_stream.is_ok() {
168 stream.flush().unwrap();
169 };
170 return raw_response;
171 }
172
173
174 let request: Request = boxed_request.unwrap();
175 let (response, request) = App::handle_request(request);
176
177
178 let log_request_response = Log::combined(&request, &response, &peer_addr);
179 println!("{}", log_request_response);
180 let raw_response = Response::generate_response(response, request);
181
182 let boxed_stream = stream.write(raw_response.borrow());
183 if boxed_stream.is_ok() {
184 stream.flush().unwrap();
185 };
186
187 raw_response
188 }
189
190 pub fn bad_request_response(message: String) -> Vec<u8> {
191 let error_request = Request {
192 method: METHOD.get.to_string(),
193 request_uri: "".to_string(),
194 http_version: "".to_string(),
195 headers: vec![],
196 body: Default::default(),
197 };
198
199 let (body, content_type) = crate::error::problem::from_text(STATUS_CODE_REASON_PHRASE.n400_bad_request, &message);
200 let content_range = crate::range::Range::get_content_range(body, content_type.to_string());
201
202 let header_list = Header::get_header_list(&error_request);
203 let error_response: Response = Response::get_response(
204 STATUS_CODE_REASON_PHRASE.n400_bad_request,
205 Some(header_list),
206 Some(vec![content_range])
207 );
208
209 let response = Response::generate_response(error_response, error_request);
210 return response;
211 }
212
213 pub fn payload_too_large_response(message: String) -> Vec<u8> {
219 let error_request = Request {
220 method: METHOD.get.to_string(),
221 request_uri: "".to_string(),
222 http_version: "".to_string(),
223 headers: vec![],
224 body: Default::default(),
225 };
226
227 let (body, content_type) = crate::error::problem::from_text(STATUS_CODE_REASON_PHRASE.n413_payload_too_large, &message);
228 let content_range = crate::range::Range::get_content_range(body, content_type.to_string());
229
230 let mut header_list = Header::get_header_list(&error_request);
231 header_list.push(Header { name: Header::_CONNECTION.into(), value: "close".into() });
232 let error_response: Response = Response::get_response(
233 STATUS_CODE_REASON_PHRASE.n413_payload_too_large,
234 Some(header_list),
235 Some(vec![content_range])
236 );
237
238 Response::generate_response(error_response, error_request)
239 }
240
241 pub fn header_fields_too_large_response() -> Vec<u8> {
245 Server::closing_error_response(
246 STATUS_CODE_REASON_PHRASE.n431_request_header_fields_too_large,
247 format!("431 Request Header Fields Too Large: the request head exceeds {} bytes", framing::MAX_HEAD_SIZE),
248 )
249 }
250
251 pub fn request_timeout_response() -> Vec<u8> {
255 Server::closing_error_response(
256 STATUS_CODE_REASON_PHRASE.n408_request_timeout,
257 format!("408 Request Timeout: the request head took longer than {} s", REQUEST_HEAD_TIMEOUT.as_secs()),
258 )
259 }
260
261 fn closing_error_response(status: &'static crate::response::StatusCodeReasonPhrase, message: String) -> Vec<u8> {
263 let error_request = Request {
264 method: METHOD.get.to_string(),
265 request_uri: "".to_string(),
266 http_version: "".to_string(),
267 headers: vec![],
268 body: Default::default(),
269 };
270
271 let (body, content_type) = crate::error::problem::from_text(status, &message);
272 let content_range = crate::range::Range::get_content_range(body, content_type.to_string());
273
274 let mut header_list = Header::get_header_list(&error_request);
275 header_list.push(Header { name: Header::_CONNECTION.into(), value: "close".into() });
276 let error_response: Response = Response::get_response(status, Some(header_list), Some(vec![content_range]));
277
278 Response::generate_response(error_response, error_request)
279 }
280
281 pub fn continue_response() -> Vec<u8> {
287 let dummy_request = Request {
288 method: METHOD.get.to_string(),
289 request_uri: "".to_string(),
290 http_version: "".to_string(),
291 headers: vec![],
292 body: Default::default(),
293 };
294 let response = Response::get_response(STATUS_CODE_REASON_PHRASE.n100_continue, None, None);
295 Response::generate_response(response, dummy_request)
296 }
297
298 pub fn expectation_failed_response(message: String) -> Vec<u8> {
303 let error_request = Request {
304 method: METHOD.get.to_string(),
305 request_uri: "".to_string(),
306 http_version: "".to_string(),
307 headers: vec![],
308 body: Default::default(),
309 };
310
311 let (body, content_type) = crate::error::problem::from_text(STATUS_CODE_REASON_PHRASE.n417_expectation_failed, &message);
312 let content_range = crate::range::Range::get_content_range(body, content_type.to_string());
313
314 let mut header_list = Header::get_header_list(&error_request);
315 header_list.push(Header { name: Header::_CONNECTION.into(), value: "close".into() });
316 let error_response: Response = Response::get_response(
317 STATUS_CODE_REASON_PHRASE.n417_expectation_failed,
318 Some(header_list),
319 Some(vec![content_range])
320 );
321
322 Response::generate_response(error_response, error_request)
323 }
324
325 pub fn process(stream: impl Read + Write + Unpin,
326 connection: ConnectionInfo,
327 app: impl Application) -> Result<(), String> {
328 Self::process_upgradable(stream, connection, app, |_| None)
330 }
331
332 fn process_upgradable<S: Read + Write + Unpin>(
336 mut stream: S,
337 connection: ConnectionInfo,
338 app: impl Application,
339 split: impl Fn(&mut S) -> Option<(Box<dyn Read + Send>, Box<dyn Write + Send>)>,
340 ) -> Result<(), String> {
341
342 let request_allocation_size = connection.request_size;
343 let client = connection.client.clone();
344 let client_addr = SocketAddr::new(IpAddr::from_str(client.ip.as_str()).unwrap(), client.port as u16);
345
346 let max_body_size = crate::entry_point::get_max_body_size();
347
348 let mut pending: Vec<u8> = Vec::new();
351 let mut read_buffer = vec![0u8; request_allocation_size as usize];
352
353 'session: loop {
354 let mut head_started: Option<std::time::Instant> = None;
359 let head_len = loop {
360 framing::skip_leading_empty_lines(&mut pending);
361 match framing::scan_head(&pending) {
362 framing::HeadScan::Complete(n) => break Some(n),
363 framing::HeadScan::TooLarge => {
364 let _ = stream.write_all(&Server::header_fields_too_large_response());
365 let _ = stream.flush();
366 return Err("request head too large".to_string());
367 }
368 framing::HeadScan::Incomplete => {}
369 }
370 if !pending.is_empty() && head_started.is_none() {
371 head_started = Some(std::time::Instant::now());
372 }
373 match stream.read(&mut read_buffer) {
374 Ok(0) | Err(_) => break None,
376 Ok(n) => pending.extend_from_slice(&read_buffer[..n]),
377 }
378 let started = *head_started.get_or_insert_with(std::time::Instant::now);
379 if started.elapsed() > REQUEST_HEAD_TIMEOUT && framing::scan_head(&pending) == framing::HeadScan::Incomplete {
380 let _ = stream.write_all(&Server::request_timeout_response());
381 let _ = stream.flush();
382 return Err("request head timed out".to_string());
383 }
384 };
385 let Some(head_len) = head_len else { break };
386
387 let parsed = Request::parse(&pending[..head_len])
388 .and_then(|request| framing::validate_head(&pending[..head_len], &request).map(|_| request))
389 .and_then(|request| framing::body_framing(&request).map(|f| (request, f)));
390 pending.drain(..head_len);
391 let (mut request, body_framing) = match parsed {
392 Ok(parsed) => parsed,
393 Err(message) => {
394 let _ = stream.write_all(&Server::bad_request_response(message.clone()));
395 let _ = stream.flush();
396 return Err(message);
397 }
398 };
399
400 let expects_continue = match request.header(Header::_EXPECT) {
404 Some(h) if h.value.trim().eq_ignore_ascii_case("100-continue") => true,
405 Some(h) => {
406 let raw_response = Server::expectation_failed_response(format!(
407 "417 Expectation Failed: unsupported Expect value '{}'", h.value.trim()
408 ));
409 let _ = stream.write_all(&raw_response);
410 let _ = stream.flush();
411 break;
412 }
413 None => false,
414 };
415
416 match body_framing {
417 framing::BodyFraming::None => {}
418 framing::BodyFraming::Length(declared_len) => {
419 if max_body_size > 0 && declared_len > max_body_size {
420 let raw_response = Server::payload_too_large_response(format!(
421 "413 Payload Too Large: declared Content-Length {} exceeds the {} byte limit",
422 declared_len, max_body_size
423 ));
424 let _ = stream.write_all(&raw_response);
425 let _ = stream.flush();
426 break;
427 }
428
429 if expects_continue && (pending.len() as u64) < declared_len {
432 if stream.write_all(&Server::continue_response()).and_then(|_| stream.flush()).is_err() {
433 break;
434 }
435 }
436
437 while (pending.len() as u64) < declared_len {
438 match stream.read(&mut read_buffer) {
439 Ok(0) | Err(_) => break 'session, Ok(k) => pending.extend_from_slice(&read_buffer[..k]),
441 }
442 }
443 request.body = pending.drain(..declared_len as usize).collect::<Vec<u8>>().into();
444 }
445 framing::BodyFraming::Chunked => {
446 if expects_continue && pending.is_empty() {
447 if stream.write_all(&Server::continue_response()).and_then(|_| stream.flush()).is_err() {
448 break;
449 }
450 }
451
452 let mut decoder = framing::ChunkedBody::new(max_body_size);
453 loop {
454 match decoder.feed(&pending) {
455 Ok((consumed, done)) => {
456 pending.drain(..consumed);
457 if done { break; }
458 }
459 Err(framing::ChunkError::TooLarge) => {
460 let raw_response = Server::payload_too_large_response(format!(
461 "413 Payload Too Large: chunked body exceeds the {} byte limit", max_body_size
462 ));
463 let _ = stream.write_all(&raw_response);
464 let _ = stream.flush();
465 break 'session;
466 }
467 Err(framing::ChunkError::Malformed(message)) => {
468 let _ = stream.write_all(&Server::bad_request_response(message.clone()));
469 let _ = stream.flush();
470 return Err(message);
471 }
472 }
473 match stream.read(&mut read_buffer) {
474 Ok(0) | Err(_) => break 'session,
475 Ok(k) => pending.extend_from_slice(&read_buffer[..k]),
476 }
477 }
478 request.body = decoder.body.into();
479 }
480 }
481
482 let keep_alive = framing::keep_alive(&request);
483
484 let started = std::time::Instant::now();
485 let result = if crate::early_hints::http1_wanted(&request) {
488 let hints: std::sync::Arc<std::sync::Mutex<Vec<Vec<String>>>> = Default::default();
489 let queue = std::sync::Arc::clone(&hints);
490 let sink = crate::early_hints::Sink::new(move |links| queue.lock().unwrap_or_else(|e| e.into_inner()).push(links));
491 let result = crate::early_hints::with_sink(Some(sink), || app.execute(&request, &connection));
492 for links in std::mem::take(&mut *hints.lock().unwrap_or_else(|e| e.into_inner())) {
493 if stream.write_all(&crate::early_hints::http1_head(&links)).is_err() {
494 return Err("client closed the connection".to_string());
495 }
496 }
497 result
498 } else {
499 app.execute(&request, &connection)
500 };
501 let mut response = match result {
502 Ok(r) => r,
503 Err(message) => {
504 crate::metrics::http::observe(&request.method, 400, false, &request.http_version, started);
505 let raw_response = Server::bad_request_response(message.clone());
506 let boxed_stream = stream.write(raw_response.borrow());
507 if boxed_stream.is_ok() { stream.flush().unwrap(); }
508 return Err(message);
509 }
510 };
511
512 crate::metrics::record_request();
513 crate::metrics::http::observe(&request.method, response.status_code, false, &request.http_version, started);
514 if let Some(upgrade) = crate::websocket::take_upgrade(&mut response) {
517 let Some((reader, writer)) = split(&mut stream) else {
518 let _ = stream.write_all(b"HTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\nConnection: close\r\n\r\n");
519 let _ = stream.flush();
520 return Err("WebSocket upgrade on a connection that can't be handed over".to_string());
521 };
522 Log::log_served(&request, &mut response, &client_addr);
523 stream.write_all(&crate::websocket::upgrade_head(&response)).and_then(|_| stream.flush()).map_err(|e| e.to_string())?;
524 let reader = std::io::Cursor::new(std::mem::take(&mut pending)).chain(reader);
525 std::thread::spawn(move || upgrade.run(Box::new(reader), writer));
526 return Ok(());
527 }
528 crate::compression::apply_compression(&request, &mut response);
529 response.drop_content_for_status();
530
531 response.headers.push(Header {
532 name: Header::_CONNECTION.into(),
533 value: if keep_alive { "keep-alive".into() } else { "close".into() },
534 });
535
536 Log::log_served(&request, &mut response, &client_addr);
537
538 if let Some(reader) = response.stream_pipe.take() {
539 if let Err(e) = Server::pipe_stream(&mut stream, response, request, reader) {
540 return Err(e);
541 }
542 } else if let Some(ref filepath) = response.stream_file.clone() {
543 if let Err(e) = Server::write_chunked_file(&mut stream, response, request, filepath) {
544 return Err(e);
545 }
546 } else {
547 let raw_response = Response::generate_response(response, request);
548 if let Err(e) = stream.write_all(raw_response.borrow()) {
550 return Err(e.to_string());
551 }
552 stream.flush().unwrap();
553 }
554
555 if !keep_alive { break; }
556 }
557
558 Ok(())
559 }
560
561 #[doc(hidden)]
564 pub fn write_chunked_file(
565 stream: &mut impl Write,
566 response: Response,
567 request: Request,
568 filepath: &str,
569 ) -> Result<(), String> {
570 use std::fs::File;
571 use std::io::Read as _;
572
573 let (head, chunked) = Server::stream_file_head(response);
574 stream.write_all(&head).map_err(|e| e.to_string())?;
575
576 if request.method != METHOD.head {
577 let mut file = File::open(filepath).map_err(|e| e.to_string())?;
578 let mut buf = vec![0u8; 65536];
579 loop {
580 let n = file.read(&mut buf).map_err(|e| e.to_string())?;
581 if n == 0 { break; }
582 if chunked {
583 stream.write_all(format!("{:x}\r\n", n).as_bytes()).map_err(|e| e.to_string())?;
585 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
586 stream.write_all(b"\r\n").map_err(|e| e.to_string())?;
587 } else {
588 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
589 }
590 }
591 if chunked {
592 stream.write_all(b"0\r\n\r\n").map_err(|e| e.to_string())?;
594 }
595 }
596
597 stream.flush().map_err(|e| e.to_string())
598 }
599
600 #[doc(hidden)]
607 pub fn stream_file_head(mut response: Response) -> (Vec<u8>, bool) {
608 let chunked = !response.headers.iter().any(|h| h.name.eq_ignore_ascii_case(Header::_CONTENT_LENGTH));
609 if chunked {
610 response.headers.push(Header {
611 name: Header::_TRANSFER_ENCODING.into(),
612 value: "chunked".into(),
613 });
614 }
615
616 let status = [
618 response.http_version.clone(),
619 response.status_code.to_string(),
620 Header::single_line(&response.reason_phrase).into_owned(),
621 ].join(SYMBOL.whitespace);
622
623 let mut headers_str = SYMBOL.new_line_carriage_return.to_string();
624 for header in &response.headers {
625 headers_str.push_str(&Header::single_line(&header.name));
626 headers_str.push_str(Header::NAME_VALUE_SEPARATOR);
627 headers_str.push_str(&Header::single_line(&header.value));
628 headers_str.push_str(SYMBOL.new_line_carriage_return);
629 }
630 let head = format!("{}{}{}", status, headers_str, SYMBOL.new_line_carriage_return);
631 (head.into_bytes(), chunked)
632 }
633
634 #[doc(hidden)]
649 pub fn pipe_stream(
650 stream: &mut impl Write,
651 mut response: Response,
652 request: Request,
653 mut reader: Box<dyn std::io::Read + Send>,
654 ) -> Result<(), String> {
655 let backend_is_chunked = response.headers.iter().any(|h| {
656 h.name.eq_ignore_ascii_case("transfer-encoding")
657 && h.value.to_lowercase().contains("chunked")
658 });
659 let declared_length = if backend_is_chunked { None } else { single_content_length(&response) };
660
661 response.headers.retain(|h| !h.name.eq_ignore_ascii_case("content-length"));
662 if let Some(len) = declared_length {
663 response.headers.push(Header { name: Header::_CONTENT_LENGTH.into(), value: len.to_string().into() });
664 } else if !backend_is_chunked {
665 response.headers.push(Header {
666 name: Header::_TRANSFER_ENCODING.into(),
667 value: "chunked".into(),
668 });
669 }
670
671 let status = [
672 response.http_version.clone(),
673 response.status_code.to_string(),
674 Header::single_line(&response.reason_phrase).into_owned(),
675 ].join(SYMBOL.whitespace);
676
677 let mut head = format!("{}\r\n", status);
678 for header in &response.headers {
679 head.push_str(&Header::single_line(&header.name));
680 head.push_str(Header::NAME_VALUE_SEPARATOR);
681 head.push_str(&Header::single_line(&header.value));
682 head.push_str(SYMBOL.new_line_carriage_return);
683 }
684 head.push_str(SYMBOL.new_line_carriage_return);
685 stream.write_all(head.as_bytes()).map_err(|e| e.to_string())?;
686
687 if request.method != METHOD.head {
688 const FRAME_ROOM: usize = 16;
691 let mut buf = vec![0u8; FRAME_ROOM + PIPE_CHUNK + 2];
692 let read_failed = |e: std::io::Error| format!("upstream body read failed: {}", e);
693 if backend_is_chunked {
694 reader = Box::new(chunked_decoder::ChunkedDecoder::new(reader));
699 }
700 if let Some(len) = declared_length {
701 let mut remaining = len;
703 while remaining > 0 {
704 let want = remaining.min(PIPE_CHUNK as u64) as usize;
705 let n = reader.read(&mut buf[..want]).map_err(read_failed)?;
706 if n == 0 {
707 return Err(format!("upstream body ended after {} of {} bytes", len - remaining, len));
708 }
709 stream.write_all(&buf[..n]).map_err(|e| e.to_string())?;
710 remaining -= n as u64;
711 }
712 } else {
713 loop {
716 let n = reader.read(&mut buf[FRAME_ROOM..FRAME_ROOM + PIPE_CHUNK]).map_err(read_failed)?;
717 if n == 0 {
718 break;
719 }
720 let size_line = format!("{:x}\r\n", n);
721 let start = FRAME_ROOM - size_line.len();
722 buf[start..FRAME_ROOM].copy_from_slice(size_line.as_bytes());
723 let end = FRAME_ROOM + n;
724 buf[end..end + 2].copy_from_slice(b"\r\n");
725 stream.write_all(&buf[start..end + 2]).map_err(|e| e.to_string())?;
726 stream.flush().map_err(|e| e.to_string())?;
727 }
728 stream.write_all(b"0\r\n\r\n").map_err(|e| e.to_string())?;
729 }
730 }
731
732 stream.flush().map_err(|e| e.to_string())
733 }
734
735 pub fn setup() -> Result<(TcpListener, ThreadPool), String> {
738 let info = Log::info("Rust Web Server");
739 println!("{}", info);
740
741 println!("Every setting: rws --help, or https://rws8.tech/docs/configuration/env-vars/\n");
744
745
746 println!("RWS Configuration Start: \n");
747
748 set_default_values();
749 bootstrap();
750
751 #[cfg(feature = "secrets")]
752 crate::secrets::resolve_env_vars().map_err(|e| e.to_string())?;
753
754 println!("\nRWS Configuration End\n\n");
755
756
757 let (ip, port, thread_count) = get_ip_port_thread_count();
758
759
760 let mut ip_readable = ip.to_string();
761
762 if ip.contains(":") {
763 ip_readable = [SYMBOL.opening_square_bracket, &ip, SYMBOL.closing_square_bracket].join("");
764 }
765
766 let bind_addr = [ip_readable, SYMBOL.colon.to_string(), port.to_string()].join(SYMBOL.empty_string);
767
768 #[cfg(feature = "http2")]
769 let protocol = {
770 let cert = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE).unwrap_or_default();
771 if cert.is_empty() { "http" } else { "https" }
772 };
773 #[cfg(not(feature = "http2"))]
774 let protocol = "http";
775
776 println!("Setting up {}://{}...", protocol, &bind_addr);
777
778 #[cfg(all(unix, any(feature = "http1", feature = "http2")))]
780 let inherited = bind_addr.parse::<std::net::SocketAddr>().ok().and_then(|addr| crate::systemd::tcp(addr, Some(protocol)));
781 #[cfg(not(all(unix, any(feature = "http1", feature = "http2"))))]
782 let inherited: Option<TcpListener> = None;
783 let boxed_listener = match inherited {
784 Some(listener) => Ok(listener),
785 None => TcpListener::bind(&bind_addr),
786 };
787 if boxed_listener.is_err() {
788 let message = format!("unable to set up TCP listener: {}", boxed_listener.err().unwrap());
789 return Err(message);
790 }
791
792 let listener = boxed_listener.unwrap();
793 let pool = ThreadPool::new(thread_count as usize);
794
795
796 let server_url_thread_count = Log::server_url_thread_count(protocol, &bind_addr, thread_count);
797 println!("{}", server_url_thread_count);
798
799 Ok((listener, pool))
800 }
801
802 pub fn run(listener: TcpListener,
810 pool: ThreadPool,
811 app: impl Application + Send + 'static + Clone) {
812 #[cfg(feature = "http1")]
813 {
814 use std::sync::Arc;
815 use std::sync::atomic::{AtomicBool, Ordering};
816
817 let shutdown = Arc::new(AtomicBool::new(false));
818 let s = shutdown.clone();
819 if let Err(e) = ctrlc::set_handler(move || {
820 s.store(true, Ordering::SeqCst);
821 }) {
822 eprintln!("unable to install signal handler: {}", e);
823 }
824 crate::config_reload::install_sighup_handler();
825 if let Err(e) = listener.set_nonblocking(true) {
826 eprintln!("unable to set non-blocking listener: {}", e);
827 }
828
829 loop {
830 if shutdown.load(Ordering::SeqCst) {
831 break;
832 }
833 if crate::config_reload::RELOAD_REQUESTED
834 .compare_exchange(true, false, Ordering::SeqCst, Ordering::Relaxed)
835 .is_ok()
836 {
837 crate::config_reload::reload();
838 }
839 match listener.accept() {
840 Ok((stream, peer_addr)) => {
841 Server::dispatch_connection(stream, peer_addr, &pool, app.clone());
842 }
843 Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
844 std::thread::sleep(Duration::from_millis(10));
845 }
846 Err(e) => {
847 eprintln!("accept error: {}", e);
848 break;
849 }
850 }
851 }
852
853 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
854 #[cfg(unix)]
855 crate::systemd::stopping();
856 println!("Shutting down — waiting for in-flight connections to finish");
857 pool.join();
858 println!("Server stopped");
859 }
860
861 #[cfg(not(feature = "http1"))]
862 {
863 for boxed_stream in listener.incoming() {
864 match boxed_stream {
865 Err(e) => {
866 eprintln!("unable to get TCP stream: {}", e);
867 return;
868 }
869 Ok(stream) => {
870 let peer_addr = match stream.peer_addr() {
871 Ok(a) => a,
872 Err(e) => {
873 eprintln!("unable to read peer addr: {}", e);
874 return;
875 }
876 };
877 Server::dispatch_connection(stream, peer_addr, &pool, app.clone());
878 }
879 }
880 }
881 }
882 }
883
884 fn dispatch_connection(
885 stream: std::net::TcpStream,
886 peer_addr: std::net::SocketAddr,
887 pool: &ThreadPool,
888 app: impl Application + Send + 'static + Clone,
889 ) {
890 print!("Connection established, ");
891 if let Ok(local) = stream.local_addr() {
892 print!("local addr: {}", local);
893 }
894 println!(", peer addr: {}", peer_addr);
895
896 let (server_ip, server_port, _thread_count) = get_ip_port_thread_count();
897 let connection = ConnectionInfo {
898 client: Address {
899 ip: peer_addr.ip().to_string(),
900 port: peer_addr.port() as i32,
901 },
902 server: Address {
903 ip: server_ip,
904 port: server_port,
905 },
906 request_size: get_request_allocation_size(),
907 sni_hostname: None,
908 tls: false,
909 };
910
911 if let Err(e) = stream.set_read_timeout(Some(Duration::from_secs(30))) {
912 eprintln!("failed to set read timeout: {}", e);
913 }
914
915 pool.execute(move || {
916 let mut stream = stream;
917 let mut connection = connection;
918 if proxy_protocol::enabled() {
919 match proxy_protocol::read_blocking(&mut stream) {
921 Ok(Some(source)) => {
922 connection.client = Address { ip: source.ip().to_string(), port: source.port() as i32 };
923 }
924 Ok(None) => {}
925 Err(e) => {
926 eprintln!("PROXY protocol header from {}: {}", peer_addr, e);
927 return;
928 }
929 }
930 }
931 crate::metrics::connection_open();
932 let result = Server::process_upgradable(stream, connection, app, |stream| {
933 let reader = stream.try_clone().ok()?;
934 let writer = stream.try_clone().ok()?;
935 let _ = reader.set_read_timeout(None);
937 Some((Box::new(reader) as Box<dyn Read + Send>, Box::new(writer) as Box<dyn Write + Send>))
938 });
939 crate::metrics::connection_close();
940 if let Err(msg) = result {
941 crate::metrics::record_error();
942 eprintln!("{}", msg);
943 }
944 });
945 }
946
947}
948
949#[derive(Clone)]
951pub struct ConnectionInfo {
952 pub client: Address,
954 pub server: Address,
956 pub request_size: i64,
958 pub sni_hostname: Option<String>,
961 pub tls: bool,
964}
965
966impl Default for ConnectionInfo {
967 fn default() -> Self {
970 let unknown = Address { ip: "0.0.0.0".to_string(), port: 0 };
971 ConnectionInfo { client: unknown.clone(), server: unknown, request_size: 0, sni_hostname: None, tls: false }
972 }
973}
974
975#[derive(Clone)]
977pub struct Address {
978 pub ip: String,
979 pub port: i32
980}
981
982impl ConnectionInfo {
983 pub fn new(client: Address, server: Address) -> Self {
986 ConnectionInfo { client, server, request_size: 0, sni_hostname: None, tls: false }
987 }
988
989 pub fn peer_addr(&self) -> Option<std::net::SocketAddr> {
992 self.client.to_socket_addr()
993 }
994}
995
996impl Address {
997 pub fn to_socket_addr(&self) -> Option<std::net::SocketAddr> {
1000 let ip: std::net::IpAddr = self.ip.parse().ok()?;
1001 let port = u16::try_from(self.port).ok()?;
1002 Some(std::net::SocketAddr::new(ip, port))
1003 }
1004}
1005
1006#[cfg(feature = "http2")]
1009#[doc(hidden)]
1010pub async fn serve_tls_connection(
1011 mut tcp_stream: tokio::net::TcpStream,
1012 peer_addr: std::net::SocketAddr,
1013 acceptor: tokio_rustls::TlsAcceptor,
1014 app: impl Application + Send + 'static + Clone,
1015) {
1016 let _ = tcp_stream.set_nodelay(true);
1017 let Some(peer_addr) = client_address(&mut tcp_stream, peer_addr).await else { return };
1018 let timed_out = || std::io::Error::from(std::io::ErrorKind::TimedOut);
1019 let handshake = async {
1020 if let Some(acme) = crate::tls::acme_hooks().filter(|acme| (acme.on_demand_enabled)()) {
1021 let lazy = tokio_rustls::LazyConfigAcceptor::new(rustls::server::Acceptor::default(), tcp_stream);
1025 let start = tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, lazy).await.map_err(|_| timed_out())??;
1026 let hello = start.client_hello();
1027 let name = hello.server_name().filter(|_| !(acme.is_challenge)(&hello)).map(str::to_string);
1028 if let Some(name) = name {
1029 (acme.on_demand_ensure)(&name).await;
1030 }
1031 let finish = start.into_stream(acceptor.config().clone());
1032 return tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, finish).await.map_err(|_| timed_out())?;
1033 }
1034 tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, acceptor.accept(tcp_stream)).await.map_err(|_| timed_out())?
1035 };
1036 match handshake.await {
1037 Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {} Err(e) => {
1039 crate::metrics::tls::record_handshake_failure();
1040 eprintln!("TLS handshake failed: {}", e)
1041 }
1042 Ok(tls_stream) => {
1043 let server_conn = tls_stream.get_ref().1;
1044 crate::metrics::tls::record_rustls(server_conn);
1045 let sni = server_conn.server_name().map(|s| s.to_string());
1046 let protocol = server_conn.alpn_protocol().map(|p| p.to_vec());
1047
1048 match protocol.as_deref() {
1049 Some(crate::tls::ACME_TLS_ALPN) => {}
1051 Some(b"h2") => {
1052 if let Err(e) = crate::h2_server::handle_connection(tls_stream, peer_addr, sni, app).await {
1053 eprintln!("H2 connection error: {}", e);
1054 }
1055 }
1056 _ => {
1057 crate::metrics::connection_open();
1058 let result = http1_async::serve(tls_stream, peer_addr, sni, true, app).await;
1059 crate::metrics::connection_close();
1060 if let Err(e) = result {
1061 crate::metrics::record_error();
1062 eprintln!("H1 TLS error: {}", e);
1063 }
1064 }
1065 }
1066 }
1067 }
1068}
1069
1070#[cfg(feature = "http2")]
1072#[doc(hidden)]
1073pub async fn serve_plain_connection(
1074 tcp_stream: tokio::net::TcpStream,
1075 peer_addr: std::net::SocketAddr,
1076 app: impl Application + Send + 'static + Clone,
1077) {
1078 let mut tcp_stream = tcp_stream;
1081 let _ = tcp_stream.set_nodelay(true);
1082 let Some(peer_addr) = client_address(&mut tcp_stream, peer_addr).await else { return };
1083 if starts_with_h2_preface(&tcp_stream).await {
1084 if let Err(e) = crate::h2_server::serve(tcp_stream, peer_addr, None, false, app).await {
1085 eprintln!("H2C connection error: {}", e);
1086 }
1087 return;
1088 }
1089 crate::metrics::connection_open();
1090 let result = http1_async::serve(tcp_stream, peer_addr, None, false, app).await;
1091 crate::metrics::connection_close();
1092 if let Err(e) = result {
1093 crate::metrics::record_error();
1094 eprintln!("{}", e);
1095 }
1096}
1097
1098#[cfg(feature = "http2")]
1102async fn client_address(tcp_stream: &mut tokio::net::TcpStream, peer_addr: std::net::SocketAddr) -> Option<std::net::SocketAddr> {
1103 if !proxy_protocol::enabled() {
1104 return Some(peer_addr);
1105 }
1106 match tokio::time::timeout(http1_async::TLS_HANDSHAKE_TIMEOUT, proxy_protocol::read_async(tcp_stream)).await {
1107 Ok(Ok(source)) => Some(source.unwrap_or(peer_addr)),
1108 Ok(Err(e)) => {
1109 eprintln!("PROXY protocol header from {}: {}", peer_addr, e);
1110 None
1111 }
1112 Err(_) => None,
1113 }
1114}
1115
1116#[cfg(feature = "http2")]
1121async fn starts_with_h2_preface(tcp_stream: &tokio::net::TcpStream) -> bool {
1122 const PREFACE: &[u8; 24] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
1123 let mut seen = [0u8; 24];
1124 let deadline = tokio::time::Instant::now() + http1_async::READ_TIMEOUT;
1125 loop {
1126 let n = match tokio::time::timeout_at(deadline, tcp_stream.peek(&mut seen)).await {
1127 Ok(Ok(n)) => n,
1128 _ => return false,
1129 };
1130 if n == 0 || seen[..n] != PREFACE[..n] {
1131 return false;
1132 }
1133 if n == PREFACE.len() {
1134 return true;
1135 }
1136 tokio::time::sleep(std::time::Duration::from_millis(5)).await;
1138 }
1139}
1140
1141#[cfg(feature = "http2")]
1144async fn accept_backoff(e: std::io::Error) {
1145 eprintln!("TCP accept error: {}", e);
1146 tokio::time::sleep(std::time::Duration::from_millis(50)).await;
1147}
1148
1149#[cfg(feature = "http2")]
1151fn shutdown_requests() -> &'static tokio::sync::watch::Sender<bool> {
1152 static REQUESTS: std::sync::OnceLock<tokio::sync::watch::Sender<bool>> = std::sync::OnceLock::new();
1153 REQUESTS.get_or_init(|| tokio::sync::watch::channel(false).0)
1154}
1155
1156#[cfg(feature = "http2")]
1160pub fn request_shutdown() {
1161 shutdown_requests().send_replace(true);
1162}
1163
1164#[cfg(feature = "http2")]
1173async fn sigterm() {
1174 static DEADLINE: std::sync::OnceLock<tokio::time::Instant> = std::sync::OnceLock::new();
1175 if let Some(deadline) = DEADLINE.get() {
1176 return tokio::time::sleep_until(*deadline).await;
1177 }
1178 if terminate_or_requested().await {
1179 let delay = std::time::Duration::from_secs(crate::server_config::ServerConfig::current().shutdown_delay_secs);
1180 let mut first = false;
1181 let deadline = *DEADLINE.get_or_init(|| {
1182 first = true;
1183 tokio::time::Instant::now() + delay
1184 });
1185 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1186 #[cfg(unix)]
1187 crate::systemd::stopping();
1188 if first && !delay.is_zero() {
1189 println!("SIGTERM: not ready; draining in {} s (shutdown_delay_secs)", delay.as_secs());
1190 }
1191 tokio::time::sleep_until(deadline).await;
1192 } else {
1193 #[cfg(unix)]
1194 crate::systemd::stopping();
1195 }
1196}
1197
1198#[cfg(feature = "http2")]
1201async fn terminate_or_requested() -> bool {
1202 let requested = async {
1203 let mut requests = shutdown_requests().subscribe();
1204 let _ = requests.wait_for(|stop| *stop).await;
1205 };
1206 #[cfg(unix)]
1207 {
1208 if let Ok(mut s) = tokio::signal::unix::signal(
1209 tokio::signal::unix::SignalKind::terminate()
1210 ) {
1211 tokio::select! {
1212 _ = s.recv() => true,
1213 _ = requested => false,
1214 }
1215 } else {
1216 requested.await;
1217 false
1218 }
1219 }
1220 #[cfg(not(unix))]
1221 {
1222 requested.await;
1223 false
1224 }
1225}
1226
1227#[cfg(feature = "http2")]
1229async fn sighup() {
1230 #[cfg(unix)]
1231 {
1232 if let Ok(mut s) = tokio::signal::unix::signal(
1233 tokio::signal::unix::SignalKind::hangup()
1234 ) {
1235 s.recv().await;
1236 } else {
1237 std::future::pending::<()>().await
1238 }
1239 }
1240 #[cfg(not(unix))]
1241 std::future::pending::<()>().await
1242}
1243
1244#[cfg(feature = "http2")]
1251#[doc(hidden)]
1252pub async fn bind_all_families(ip: &str, port: u16) -> Result<Vec<tokio::net::TcpListener>, String> {
1253 use tokio::net::TcpListener;
1254 #[cfg(unix)]
1255 {
1256 let wanted = if ip.contains(':') { format!("[{ip}]:{port}") } else { format!("{ip}:{port}") };
1257 if let Some(listener) = wanted.parse().ok().and_then(|addr| crate::systemd::tcp(addr, Some("redirect"))) {
1258 listener.set_nonblocking(true).map_err(|e| e.to_string())?;
1259 return TcpListener::from_std(listener).map(|l| vec![l]).map_err(|e| e.to_string());
1260 }
1261 }
1262 if ip != "0.0.0.0" {
1263 let addr = if ip.contains(':') { format!("[{ip}]:{port}") } else { format!("{ip}:{port}") };
1264 return TcpListener::bind(&addr).await.map(|l| vec![l]).map_err(|e| format!("{addr}: {e}"));
1265 }
1266 let mut listeners = Vec::new();
1267 let mut errors = Vec::new();
1268 for addr in [format!("[::]:{port}"), format!("0.0.0.0:{port}")] {
1269 match TcpListener::bind(&addr).await {
1270 Ok(l) => listeners.push(l),
1271 Err(e) => errors.push(format!("{addr}: {e}")),
1272 }
1273 }
1274 if listeners.is_empty() {
1275 return Err(errors.join("; "));
1276 }
1277 Ok(listeners)
1278}
1279
1280#[cfg(feature = "http2")]
1281impl Server {
1282 pub async fn run_tls(
1283 listener: TcpListener,
1284 pool: ThreadPool,
1285 app: impl Application + Send + 'static + Clone,
1286 ) {
1287 use crate::tls::create_tls_acceptor_from_vhosts;
1288
1289 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1290 .unwrap_or_default();
1291 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
1292 .unwrap_or_default();
1293
1294 if cert_path.is_empty() || key_path.is_empty() {
1295 println!("No TLS certificate configured — serving plain HTTP/1.1.");
1296 drop(pool);
1297 Server::run_plain(listener, app).await;
1298 return;
1299 }
1300
1301 let vhosts = crate::entry_point::get_virtual_hosts();
1302 let mut tls_acceptor = match create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1303 Ok(a) => a,
1304 Err(e) => {
1305 eprintln!("TLS setup failed: {}", e);
1306 return;
1307 }
1308 };
1309 if let Some(acme) = crate::tls::acme_hooks() {
1311 (acme.note_tls_listener)();
1312 }
1313
1314 #[cfg(unix)]
1315 if per_core::enabled() {
1316 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2), per-core runtimes...");
1317 let (acceptor_tx, acceptor_rx) = tokio::sync::watch::channel(tls_acceptor);
1318 let accept_loop = move |listener: tokio::net::TcpListener, mut stop: tokio::sync::watch::Receiver<bool>| {
1319 let app = app.clone();
1320 let acceptor_rx = acceptor_rx.clone();
1321 async move {
1322 loop {
1323 tokio::select! {
1324 result = listener.accept() => match result {
1325 Ok((tcp_stream, peer_addr)) => {
1326 let acceptor = acceptor_rx.borrow().clone();
1327 tokio::spawn(serve_tls_connection(tcp_stream, peer_addr, acceptor, app.clone()));
1328 }
1329 Err(e) => accept_backoff(e).await,
1330 },
1331 _ = per_core::stopped(&mut stop) => break,
1332 }
1333 }
1334 }
1335 };
1336 Server::run_per_core(listener, accept_loop, move || {
1337 let vhosts = crate::entry_point::get_virtual_hosts();
1338 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1339 let _ = acceptor_tx.send(new_acceptor);
1340 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
1341 }
1342 })
1343 .await;
1344 return;
1345 }
1346
1347 listener
1348 .set_nonblocking(true)
1349 .expect("failed to set TCP listener to non-blocking");
1350 let tokio_listener = tokio::net::TcpListener::from_std(listener)
1351 .expect("failed to convert TCP listener to tokio");
1352
1353 println!("Listening for TLS connections (HTTP/1.1 + HTTP/2)...");
1354
1355 loop {
1356 tokio::select! {
1357 result = tokio_listener.accept() => {
1358 match result {
1359 Ok((tcp_stream, peer_addr)) => {
1360 tokio::spawn(serve_tls_connection(tcp_stream, peer_addr, tls_acceptor.clone(), app.clone()));
1361 }
1362 Err(e) => eprintln!("TCP accept error: {}", e),
1363 }
1364 }
1365 _ = tokio::signal::ctrl_c() => {
1366 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1367 println!("\nShutting down gracefully (SIGINT).");
1368 break;
1369 }
1370 _ = sigterm() => {
1371 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1372 println!("\nShutting down gracefully (SIGTERM).");
1373 break;
1374 }
1375 _ = sighup() => {
1376 crate::config_reload::reload();
1377 let vhosts = crate::entry_point::get_virtual_hosts();
1378 if let Ok(new_acceptor) = create_tls_acceptor_from_vhosts(&vhosts, &cert_path, &key_path) {
1379 tls_acceptor = new_acceptor;
1380 println!("[TLS] Certificates reloaded ({} virtual hosts).", vhosts.len());
1381 }
1382 }
1383 }
1384 }
1385 }
1386
1387 pub async fn run_plain(listener: TcpListener, app: impl Application + Send + 'static + Clone) {
1393 #[cfg(unix)]
1394 if per_core::enabled() {
1395 let accept_loop = move |listener: tokio::net::TcpListener, mut stop: tokio::sync::watch::Receiver<bool>| {
1396 let app = app.clone();
1397 async move {
1398 loop {
1399 tokio::select! {
1400 result = listener.accept() => match result {
1401 Ok((tcp_stream, peer_addr)) => {
1402 tokio::spawn(serve_plain_connection(tcp_stream, peer_addr, app.clone()));
1403 }
1404 Err(e) => accept_backoff(e).await,
1405 },
1406 _ = per_core::stopped(&mut stop) => break,
1407 }
1408 }
1409 }
1410 };
1411 Server::run_per_core(listener, accept_loop, || {}).await;
1412 return;
1413 }
1414
1415 listener
1416 .set_nonblocking(true)
1417 .expect("failed to set TCP listener to non-blocking");
1418 let tokio_listener = tokio::net::TcpListener::from_std(listener)
1419 .expect("failed to convert TCP listener to tokio");
1420
1421 loop {
1422 tokio::select! {
1423 result = tokio_listener.accept() => {
1424 match result {
1425 Ok((tcp_stream, peer_addr)) => {
1426 tokio::spawn(serve_plain_connection(tcp_stream, peer_addr, app.clone()));
1427 }
1428 Err(e) => accept_backoff(e).await,
1429 }
1430 }
1431 _ = tokio::signal::ctrl_c() => {
1432 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1433 println!("\nShutting down gracefully (SIGINT).");
1434 break;
1435 }
1436 _ = sigterm() => {
1437 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1438 println!("\nShutting down gracefully (SIGTERM).");
1439 break;
1440 }
1441 _ = sighup() => {
1442 crate::config_reload::reload();
1443 }
1444 }
1445 }
1446 }
1447
1448 #[cfg(unix)]
1453 async fn run_per_core<F, Fut>(listener: TcpListener, accept_loop: F, on_reload: impl Fn())
1454 where
1455 F: Fn(tokio::net::TcpListener, tokio::sync::watch::Receiver<bool>) -> Fut + Send + Clone + 'static,
1456 Fut: std::future::Future<Output = ()>,
1457 {
1458 let addr = match listener.local_addr() {
1459 Ok(a) => a,
1460 Err(e) => return eprintln!("per-core runtimes: {}", e),
1461 };
1462 drop(listener);
1464 let count = per_core::runtime_count();
1465 let (stop_tx, stop_rx) = tokio::sync::watch::channel(false);
1466 let handles = per_core::spawn(addr, count, stop_rx, accept_loop);
1467 println!("Started {} per-core runtimes on {}.", handles.len(), addr);
1468
1469 loop {
1470 tokio::select! {
1471 _ = tokio::signal::ctrl_c() => {
1472 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1473 println!("\nShutting down gracefully (SIGINT).");
1474 break;
1475 }
1476 _ = sigterm() => {
1477 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1478 println!("\nShutting down gracefully (SIGTERM).");
1479 break;
1480 }
1481 _ = sighup() => {
1482 crate::config_reload::reload();
1483 on_reload();
1484 }
1485 }
1486 }
1487 let _ = stop_tx.send(true);
1488 let _ = tokio::task::spawn_blocking(move || {
1489 for h in handles {
1490 let _ = h.join();
1491 }
1492 })
1493 .await;
1494 }
1495
1496 pub async fn run_redirect() {
1500 use std::env;
1501
1502 let cert_path = env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1503 .unwrap_or_default();
1504 if cert_path.is_empty() {
1505 return;
1506 }
1507
1508 let redirect_port_str = env::var(crate::entry_point::Config::RWS_CONFIG_HTTP_REDIRECT_PORT)
1509 .unwrap_or_default();
1510 if redirect_port_str.is_empty() {
1511 return;
1512 }
1513
1514 let redirect_port: u16 = match redirect_port_str.parse() {
1515 Ok(p) => p,
1516 Err(_) => {
1517 eprintln!("Invalid RWS_CONFIG_HTTP_REDIRECT_PORT: {}", redirect_port_str);
1518 return;
1519 }
1520 };
1521
1522 let (server_ip, server_port, _) = get_ip_port_thread_count();
1523 let listeners = match bind_all_families(&server_ip, redirect_port).await {
1524 Ok(l) => l,
1525 Err(e) => {
1526 eprintln!("HTTP redirect listener error on port {}: {}", redirect_port, e);
1527 return;
1528 }
1529 };
1530
1531 println!("HTTP→HTTPS redirect listening on http://{}:{}", server_ip, redirect_port);
1532 if let Some(acme) = crate::tls::acme_hooks() {
1533 (acme.note_redirect_listener)(redirect_port);
1534 }
1535
1536 for listener in listeners {
1537 tokio::spawn(async move {
1538 loop {
1539 match listener.accept().await {
1540 Ok((stream, _peer)) => {
1541 tokio::spawn(Server::handle_redirect_connection(stream, server_port));
1542 }
1543 Err(e) => eprintln!("HTTP redirect accept error: {}", e),
1544 }
1545 }
1546 });
1547 }
1548
1549 loop {
1550 tokio::select! {
1551 _ = tokio::signal::ctrl_c() => {
1552 println!("\nShutting down HTTP redirect listener (SIGINT).");
1553 break;
1554 }
1555 _ = sigterm() => {
1556 println!("\nShutting down HTTP redirect listener (SIGTERM).");
1557 break;
1558 }
1559 _ = sighup() => {
1560 crate::config_reload::reload();
1561 }
1562 }
1563 }
1564 }
1565
1566 #[doc(hidden)]
1569 pub async fn handle_redirect_connection(mut stream: tokio::net::TcpStream, https_port: i32) {
1570 use tokio::io::{AsyncReadExt, AsyncWriteExt};
1571 let mut buf = vec![0u8; 4096];
1572 let n = match stream.read(&mut buf).await {
1573 Ok(n) => n,
1574 Err(_) => return,
1575 };
1576 let text = String::from_utf8_lossy(&buf[..n]);
1577
1578 let uri = text.lines()
1579 .next()
1580 .and_then(|line| line.split_whitespace().nth(1))
1581 .unwrap_or("/")
1582 .to_string();
1583
1584 let challenge = match crate::tls::acme_hooks() {
1587 Some(acme) => (acme.http_challenge)(&uri).await,
1588 None => None,
1589 };
1590 if let Some(challenge) = challenge {
1591 let _ = stream.write_all(challenge.as_bytes()).await;
1592 return;
1593 }
1594
1595 let host_header = text.lines()
1596 .find(|l| l.to_lowercase().starts_with("host:"))
1597 .map(|l| l[5..].trim().to_string());
1598
1599 let location = match host_header {
1600 Some(h) => {
1601 let h_no_port = if h.starts_with('[') {
1603 h.find(']')
1605 .map(|i| h[..=i].to_string())
1606 .unwrap_or(h.clone())
1607 } else {
1608 h.rfind(':')
1609 .map(|i| h[..i].to_string())
1610 .unwrap_or(h.clone())
1611 };
1612 if https_port == 443 {
1613 format!("https://{}{}", h_no_port, uri)
1614 } else {
1615 format!("https://{}:{}{}", h_no_port, https_port, uri)
1616 }
1617 }
1618 None => format!("https://localhost:{}{}", https_port, uri),
1619 };
1620
1621 let response = format!(
1622 "HTTP/1.1 301 Moved Permanently\r\nLocation: {}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n",
1623 location
1624 );
1625 let _ = stream.write_all(response.as_bytes()).await;
1626 }
1627
1628}
1629
1630#[cfg(feature = "http3")]
1631impl Server {
1632 pub async fn run_quic(
1633 app: impl Application + Send + 'static + Clone,
1634 ) {
1635 use crate::tls::create_quinn_server_config_from_vhosts;
1636 use crate::h3_handler;
1637
1638 let cert_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_CERT_FILE)
1639 .unwrap_or_default();
1640 let key_path = std::env::var(crate::entry_point::Config::RWS_CONFIG_TLS_KEY_FILE)
1641 .unwrap_or_default();
1642
1643 if cert_path.is_empty() || key_path.is_empty() {
1644 return;
1645 }
1646
1647 let vhosts = crate::entry_point::get_virtual_hosts();
1648 let server_config = match create_quinn_server_config_from_vhosts(&vhosts, &cert_path, &key_path) {
1649 Ok(c) => c,
1650 Err(e) => {
1651 eprintln!("QUIC TLS setup failed: {}", e);
1652 return;
1653 }
1654 };
1655
1656 let (server_ip, server_port, _) = get_ip_port_thread_count();
1657 let bind_addr = format!("{}:{}", server_ip, server_port);
1658 let addr: std::net::SocketAddr = match bind_addr.parse() {
1659 Ok(a) => a,
1660 Err(e) => {
1661 eprintln!("Invalid QUIC bind address '{}': {}", bind_addr, e);
1662 return;
1663 }
1664 };
1665
1666 #[cfg(unix)]
1668 let inherited = crate::systemd::udp(addr, Some("quic"));
1669 #[cfg(not(unix))]
1670 let inherited: Option<std::net::UdpSocket> = None;
1671 let endpoint = match inherited {
1672 Some(socket) => quinn::Endpoint::new(quinn::EndpointConfig::default(), Some(server_config), socket, std::sync::Arc::new(quinn::TokioRuntime)),
1673 None => quinn::Endpoint::server(server_config, addr),
1674 };
1675 let endpoint = match endpoint {
1676 Ok(e) => e,
1677 Err(e) => {
1678 eprintln!("QUIC endpoint error: {}", e);
1679 return;
1680 }
1681 };
1682
1683 println!("Listening for QUIC/HTTP3 on UDP {}:{}", server_ip, server_port);
1684
1685 loop {
1686 tokio::select! {
1687 maybe = endpoint.accept() => {
1688 match maybe {
1689 Some(incoming) => {
1690 let app = app.clone();
1691 tokio::spawn(async move {
1692 match incoming.await {
1693 Ok(conn) => {
1694 let peer_addr = conn.remote_address();
1695 if let Err(e) = h3_handler::handle_connection(conn, peer_addr, app).await {
1696 eprintln!("H3 connection error: {}", e);
1697 }
1698 }
1699 Err(e) => eprintln!("QUIC connection error: {}", e),
1700 }
1701 });
1702 }
1703 None => break,
1704 }
1705 }
1706 _ = tokio::signal::ctrl_c() => {
1707 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1708 println!("\nShutting down QUIC (SIGINT).");
1709 endpoint.close(0u32.into(), b"shutdown");
1710 break;
1711 }
1712 _ = sigterm() => {
1713 crate::metrics::SERVER_READY.store(false, std::sync::atomic::Ordering::SeqCst);
1714 println!("\nShutting down QUIC (SIGTERM).");
1715 endpoint.close(0u32.into(), b"shutdown");
1716 break;
1717 }
1718 _ = sighup() => {
1719 crate::config_reload::reload();
1720 }
1721 }
1722 }
1723 }
1724}
1725
1726