1use std::{
2 fmt,
3 future::Future,
4 net::SocketAddr,
5 pin::Pin,
6 rc::Rc,
7 time::{Duration, Instant},
8};
9
10use bytes::BytesMut;
11
12use crate::{
13 date::{DateService, DATE_VALUE_LENGTH},
14 KeepAlive,
15};
16
17pub(crate) type GracefulShutdownFuture = Pin<Box<dyn Future<Output = ()>>>;
18
19#[derive(Clone)]
20pub(crate) struct GracefulShutdownSignal(Rc<dyn Fn() -> GracefulShutdownFuture>);
21
22impl GracefulShutdownSignal {
23 pub(crate) fn new<F, Fut>(signal: F) -> Self
24 where
25 F: Fn() -> Fut + 'static,
26 Fut: Future<Output = ()> + 'static,
27 {
28 Self(Rc::new(move || Box::pin(signal())))
29 }
30
31 fn notified(&self) -> GracefulShutdownFuture {
32 (self.0)()
33 }
34}
35
36impl fmt::Debug for GracefulShutdownSignal {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 f.debug_struct("GracefulShutdownSignal")
39 .finish_non_exhaustive()
40 }
41}
42
43pub(crate) const DEFAULT_H2_CONN_WINDOW_SIZE: u32 = 1024 * 1024 * 2; pub(crate) const DEFAULT_H2_STREAM_WINDOW_SIZE: u32 = 1024 * 1024; pub(crate) const DEFAULT_H1_WRITE_BUFFER_SIZE: usize = 32_768;
55
56#[derive(Default, Debug)]
58pub struct ServiceConfigBuilder {
59 inner: Inner,
60}
61
62impl ServiceConfigBuilder {
63 pub fn new() -> Self {
74 Self::default()
75 }
76
77 pub fn secure(mut self, secure: bool) -> Self {
79 self.inner.secure = secure;
80 self
81 }
82
83 pub fn local_addr(mut self, local_addr: Option<SocketAddr>) -> Self {
85 self.inner.local_addr = local_addr;
86 self
87 }
88
89 pub fn keep_alive(mut self, keep_alive: KeepAlive) -> Self {
91 self.inner.keep_alive = keep_alive;
92 self
93 }
94
95 pub fn client_request_timeout(mut self, timeout: Duration) -> Self {
97 self.inner.client_request_timeout = timeout;
98 self
99 }
100
101 pub fn client_disconnect_timeout(mut self, timeout: Duration) -> Self {
104 self.inner.client_disconnect_timeout = timeout;
105 self
106 }
107
108 pub fn tcp_nodelay(mut self, nodelay: Option<bool>) -> Self {
110 self.inner.tcp_nodelay = nodelay;
111 self
112 }
113
114 pub fn h1_allow_half_closed(mut self, allow: bool) -> Self {
120 self.inner.h1_allow_half_closed = allow;
121 self
122 }
123
124 pub fn h1_write_buffer_size(mut self, size: usize) -> Self {
134 assert!(
135 size > 0,
136 "HTTP/1 write buffer size must be greater than zero"
137 );
138
139 self.inner.h1_write_buffer_size = size;
140 self
141 }
142
143 pub(crate) fn graceful_shutdown_signal(
144 mut self,
145 signal: Option<GracefulShutdownSignal>,
146 ) -> Self {
147 self.inner.graceful_shutdown_signal = signal;
148 self
149 }
150
151 pub fn h2_initial_window_size(mut self, size: u32) -> Self {
158 self.inner.h2_stream_window_size = size;
159 self
160 }
161
162 pub fn h2_initial_connection_window_size(mut self, size: u32) -> Self {
169 self.inner.h2_conn_window_size = size;
170 self
171 }
172
173 pub fn build(self) -> ServiceConfig {
175 ServiceConfig(Rc::new(self.inner))
176 }
177}
178
179#[derive(Debug, Clone, Default)]
181pub struct ServiceConfig(Rc<Inner>);
182
183#[derive(Debug)]
184struct Inner {
185 keep_alive: KeepAlive,
186 client_request_timeout: Duration,
187 client_disconnect_timeout: Duration,
188 secure: bool,
189 local_addr: Option<SocketAddr>,
190 tcp_nodelay: Option<bool>,
191 date_service: DateService,
192 h1_allow_half_closed: bool,
193 h1_write_buffer_size: usize,
194 h2_conn_window_size: u32,
195 h2_stream_window_size: u32,
196 graceful_shutdown_signal: Option<GracefulShutdownSignal>,
197}
198
199impl Default for Inner {
200 fn default() -> Self {
201 Self {
202 keep_alive: KeepAlive::default(),
203 client_request_timeout: Duration::from_secs(5),
204 client_disconnect_timeout: Duration::ZERO,
205 secure: false,
206 local_addr: None,
207 tcp_nodelay: None,
208 date_service: DateService::new(),
209 h1_allow_half_closed: true,
210 h1_write_buffer_size: DEFAULT_H1_WRITE_BUFFER_SIZE,
211 h2_conn_window_size: DEFAULT_H2_CONN_WINDOW_SIZE,
212 h2_stream_window_size: DEFAULT_H2_STREAM_WINDOW_SIZE,
213 graceful_shutdown_signal: None,
214 }
215 }
216}
217
218impl ServiceConfig {
219 pub fn new(
221 keep_alive: KeepAlive,
222 client_request_timeout: Duration,
223 client_disconnect_timeout: Duration,
224 secure: bool,
225 local_addr: Option<SocketAddr>,
226 ) -> ServiceConfig {
227 ServiceConfig(Rc::new(Inner {
228 keep_alive: keep_alive.normalize(),
229 client_request_timeout,
230 client_disconnect_timeout,
231 secure,
232 local_addr,
233 tcp_nodelay: None,
234 date_service: DateService::new(),
235 h1_allow_half_closed: true,
236 h1_write_buffer_size: DEFAULT_H1_WRITE_BUFFER_SIZE,
237 h2_conn_window_size: DEFAULT_H2_CONN_WINDOW_SIZE,
238 h2_stream_window_size: DEFAULT_H2_STREAM_WINDOW_SIZE,
239 graceful_shutdown_signal: None,
240 }))
241 }
242
243 #[inline]
245 pub fn secure(&self) -> bool {
246 self.0.secure
247 }
248
249 #[inline]
253 pub fn local_addr(&self) -> Option<SocketAddr> {
254 self.0.local_addr
255 }
256
257 #[inline]
259 pub fn keep_alive(&self) -> KeepAlive {
260 self.0.keep_alive
261 }
262
263 pub fn keep_alive_deadline(&self) -> Option<Instant> {
268 match self.keep_alive() {
269 KeepAlive::Timeout(dur) => Some(self.now() + dur),
270 KeepAlive::Os => None,
271 KeepAlive::Disabled => None,
272 }
273 }
274
275 pub fn client_request_deadline(&self) -> Option<Instant> {
280 let timeout = self.0.client_request_timeout;
281 (timeout != Duration::ZERO).then(|| self.now() + timeout)
282 }
283
284 pub fn client_disconnect_deadline(&self) -> Option<Instant> {
286 let timeout = self.0.client_disconnect_timeout;
287 (timeout != Duration::ZERO).then(|| self.now() + timeout)
288 }
289
290 pub fn h1_allow_half_closed(&self) -> bool {
296 self.0.h1_allow_half_closed
297 }
298
299 pub fn h1_write_buffer_size(&self) -> usize {
301 self.0.h1_write_buffer_size
302 }
303
304 pub(crate) fn graceful_shutdown(&self) -> Option<GracefulShutdownFuture> {
305 self.0
306 .graceful_shutdown_signal
307 .as_ref()
308 .map(GracefulShutdownSignal::notified)
309 }
310
311 pub fn tcp_nodelay(&self) -> Option<bool> {
313 self.0.tcp_nodelay
314 }
315
316 pub fn h2_initial_window_size(&self) -> u32 {
318 self.0.h2_stream_window_size
319 }
320
321 pub fn h2_initial_connection_window_size(&self) -> u32 {
323 self.0.h2_conn_window_size
324 }
325
326 pub(crate) fn now(&self) -> Instant {
327 self.0.date_service.now()
328 }
329
330 #[doc(hidden)]
335 pub fn write_date_header(&self, dst: &mut BytesMut, camel_case: bool) {
336 const PREFIX_LEN: usize = 6;
337 const CRLF_LEN: usize = 2;
338 const DATE_HEADER_LEN: usize = PREFIX_LEN + DATE_VALUE_LENGTH + CRLF_LEN;
339
340 let mut buf: [u8; DATE_HEADER_LEN] = [0; DATE_HEADER_LEN];
341
342 buf[..PREFIX_LEN].copy_from_slice(if camel_case { b"Date: " } else { b"date: " });
343
344 self.0.date_service.with_date(|date| {
345 buf[PREFIX_LEN..PREFIX_LEN + DATE_VALUE_LENGTH].copy_from_slice(&date.bytes)
346 });
347
348 buf[PREFIX_LEN + DATE_VALUE_LENGTH..].copy_from_slice(b"\r\n");
349 dst.extend_from_slice(&buf);
350 }
351
352 #[allow(unused)] pub(crate) fn write_date_header_value(&self, dst: &mut BytesMut) {
354 self.0
355 .date_service
356 .with_date(|date| dst.extend_from_slice(&date.bytes));
357 }
358}
359
360#[cfg(test)]
361mod tests {
362 use memchr::memmem;
363 use tokio::{
364 task::yield_now,
365 time::{sleep, sleep_until},
366 };
367
368 use super::*;
369 use crate::{date::DATE_VALUE_LENGTH, notify_on_drop};
370
371 #[actix_rt::test]
372 async fn test_date_service_update() {
373 let settings =
374 ServiceConfig::new(KeepAlive::Os, Duration::ZERO, Duration::ZERO, false, None);
375
376 yield_now().await;
377
378 let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
379 settings.write_date_header(&mut buf1, false);
380 let now1 = settings.now();
381
382 sleep_until((Instant::now() + Duration::from_secs(2)).into()).await;
383 yield_now().await;
384
385 let now2 = settings.now();
386 let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
387 settings.write_date_header(&mut buf2, false);
388
389 assert_ne!(now1, now2);
390
391 assert_ne!(buf1, buf2);
392
393 drop(settings);
394
395 let mut times = 0;
397 while !notify_on_drop::is_dropped() {
398 sleep(Duration::from_millis(100)).await;
399 times += 1;
400 assert!(times < 10, "Timeout waiting for task drop");
401 }
402 }
403
404 #[actix_rt::test]
405 async fn test_date_service_drop() {
406 let service = Rc::new(DateService::new());
407
408 yield_now().await;
410
411 let clone1 = service.clone();
412 let clone2 = service.clone();
413 let clone3 = service.clone();
414
415 drop(clone1);
416 assert!(!notify_on_drop::is_dropped());
417 drop(clone2);
418 assert!(!notify_on_drop::is_dropped());
419 drop(clone3);
420 assert!(!notify_on_drop::is_dropped());
421
422 drop(service);
423
424 let mut times = 0;
426 while !notify_on_drop::is_dropped() {
427 sleep(Duration::from_millis(100)).await;
428 times += 1;
429 assert!(times < 10, "Timeout waiting for task drop");
430 }
431 }
432
433 #[test]
434 fn test_date_len() {
435 assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len());
436 }
437
438 #[actix_rt::test]
439 async fn test_date() {
440 let settings = ServiceConfig::default();
441
442 let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
443 settings.write_date_header(&mut buf1, false);
444
445 let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
446 settings.write_date_header(&mut buf2, false);
447
448 assert_eq!(buf1, buf2);
449 }
450
451 #[actix_rt::test]
452 async fn test_date_camel_case() {
453 let settings = ServiceConfig::default();
454
455 let mut buf = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
456 settings.write_date_header(&mut buf, false);
457 assert!(memmem::find(&buf, b"date:").is_some());
458
459 let mut buf = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
460 settings.write_date_header(&mut buf, true);
461 assert!(memmem::find(&buf, b"Date:").is_some());
462 }
463}