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::{date::DateService, KeepAlive};
13
14pub(crate) type GracefulShutdownFuture = Pin<Box<dyn Future<Output = ()>>>;
15
16#[derive(Clone)]
17pub(crate) struct GracefulShutdownSignal(Rc<dyn Fn() -> GracefulShutdownFuture>);
18
19impl GracefulShutdownSignal {
20 pub(crate) fn new<F, Fut>(signal: F) -> Self
21 where
22 F: Fn() -> Fut + 'static,
23 Fut: Future<Output = ()> + 'static,
24 {
25 Self(Rc::new(move || Box::pin(signal())))
26 }
27
28 fn notified(&self) -> GracefulShutdownFuture {
29 (self.0)()
30 }
31}
32
33impl fmt::Debug for GracefulShutdownSignal {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 f.debug_struct("GracefulShutdownSignal")
36 .finish_non_exhaustive()
37 }
38}
39
40pub(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;
52
53#[derive(Default, Debug)]
55pub struct ServiceConfigBuilder {
56 inner: Inner,
57}
58
59impl ServiceConfigBuilder {
60 pub fn new() -> Self {
71 Self::default()
72 }
73
74 pub fn secure(mut self, secure: bool) -> Self {
76 self.inner.secure = secure;
77 self
78 }
79
80 pub fn local_addr(mut self, local_addr: Option<SocketAddr>) -> Self {
82 self.inner.local_addr = local_addr;
83 self
84 }
85
86 pub fn keep_alive(mut self, keep_alive: KeepAlive) -> Self {
88 self.inner.keep_alive = keep_alive;
89 self
90 }
91
92 pub fn client_request_timeout(mut self, timeout: Duration) -> Self {
94 self.inner.client_request_timeout = timeout;
95 self
96 }
97
98 pub fn client_disconnect_timeout(mut self, timeout: Duration) -> Self {
101 self.inner.client_disconnect_timeout = timeout;
102 self
103 }
104
105 pub fn tcp_nodelay(mut self, nodelay: Option<bool>) -> Self {
107 self.inner.tcp_nodelay = nodelay;
108 self
109 }
110
111 pub fn h1_allow_half_closed(mut self, allow: bool) -> Self {
117 self.inner.h1_allow_half_closed = allow;
118 self
119 }
120
121 pub fn h1_write_buffer_size(mut self, size: usize) -> Self {
131 assert!(
132 size > 0,
133 "HTTP/1 write buffer size must be greater than zero"
134 );
135
136 self.inner.h1_write_buffer_size = size;
137 self
138 }
139
140 pub(crate) fn graceful_shutdown_signal(
141 mut self,
142 signal: Option<GracefulShutdownSignal>,
143 ) -> Self {
144 self.inner.graceful_shutdown_signal = signal;
145 self
146 }
147
148 pub fn h2_initial_window_size(mut self, size: u32) -> Self {
155 self.inner.h2_stream_window_size = size;
156 self
157 }
158
159 pub fn h2_initial_connection_window_size(mut self, size: u32) -> Self {
166 self.inner.h2_conn_window_size = size;
167 self
168 }
169
170 pub fn build(self) -> ServiceConfig {
172 ServiceConfig(Rc::new(self.inner))
173 }
174}
175
176#[derive(Debug, Clone, Default)]
178pub struct ServiceConfig(Rc<Inner>);
179
180#[derive(Debug)]
181struct Inner {
182 keep_alive: KeepAlive,
183 client_request_timeout: Duration,
184 client_disconnect_timeout: Duration,
185 secure: bool,
186 local_addr: Option<SocketAddr>,
187 tcp_nodelay: Option<bool>,
188 date_service: DateService,
189 h1_allow_half_closed: bool,
190 h1_write_buffer_size: usize,
191 h2_conn_window_size: u32,
192 h2_stream_window_size: u32,
193 graceful_shutdown_signal: Option<GracefulShutdownSignal>,
194}
195
196impl Default for Inner {
197 fn default() -> Self {
198 Self {
199 keep_alive: KeepAlive::default(),
200 client_request_timeout: Duration::from_secs(5),
201 client_disconnect_timeout: Duration::ZERO,
202 secure: false,
203 local_addr: None,
204 tcp_nodelay: None,
205 date_service: DateService::new(),
206 h1_allow_half_closed: true,
207 h1_write_buffer_size: DEFAULT_H1_WRITE_BUFFER_SIZE,
208 h2_conn_window_size: DEFAULT_H2_CONN_WINDOW_SIZE,
209 h2_stream_window_size: DEFAULT_H2_STREAM_WINDOW_SIZE,
210 graceful_shutdown_signal: None,
211 }
212 }
213}
214
215impl ServiceConfig {
216 pub fn new(
218 keep_alive: KeepAlive,
219 client_request_timeout: Duration,
220 client_disconnect_timeout: Duration,
221 secure: bool,
222 local_addr: Option<SocketAddr>,
223 ) -> ServiceConfig {
224 ServiceConfig(Rc::new(Inner {
225 keep_alive: keep_alive.normalize(),
226 client_request_timeout,
227 client_disconnect_timeout,
228 secure,
229 local_addr,
230 tcp_nodelay: None,
231 date_service: DateService::new(),
232 h1_allow_half_closed: true,
233 h1_write_buffer_size: DEFAULT_H1_WRITE_BUFFER_SIZE,
234 h2_conn_window_size: DEFAULT_H2_CONN_WINDOW_SIZE,
235 h2_stream_window_size: DEFAULT_H2_STREAM_WINDOW_SIZE,
236 graceful_shutdown_signal: None,
237 }))
238 }
239
240 #[inline]
242 pub fn secure(&self) -> bool {
243 self.0.secure
244 }
245
246 #[inline]
250 pub fn local_addr(&self) -> Option<SocketAddr> {
251 self.0.local_addr
252 }
253
254 #[inline]
256 pub fn keep_alive(&self) -> KeepAlive {
257 self.0.keep_alive
258 }
259
260 pub fn keep_alive_deadline(&self) -> Option<Instant> {
265 match self.keep_alive() {
266 KeepAlive::Timeout(dur) => Some(self.now() + dur),
267 KeepAlive::Os => None,
268 KeepAlive::Disabled => None,
269 }
270 }
271
272 pub fn client_request_deadline(&self) -> Option<Instant> {
277 let timeout = self.0.client_request_timeout;
278 (timeout != Duration::ZERO).then(|| self.now() + timeout)
279 }
280
281 pub fn client_disconnect_deadline(&self) -> Option<Instant> {
283 let timeout = self.0.client_disconnect_timeout;
284 (timeout != Duration::ZERO).then(|| self.now() + timeout)
285 }
286
287 pub fn h1_allow_half_closed(&self) -> bool {
293 self.0.h1_allow_half_closed
294 }
295
296 pub fn h1_write_buffer_size(&self) -> usize {
298 self.0.h1_write_buffer_size
299 }
300
301 pub(crate) fn graceful_shutdown(&self) -> Option<GracefulShutdownFuture> {
302 self.0
303 .graceful_shutdown_signal
304 .as_ref()
305 .map(GracefulShutdownSignal::notified)
306 }
307
308 pub fn tcp_nodelay(&self) -> Option<bool> {
310 self.0.tcp_nodelay
311 }
312
313 pub fn h2_initial_window_size(&self) -> u32 {
315 self.0.h2_stream_window_size
316 }
317
318 pub fn h2_initial_connection_window_size(&self) -> u32 {
320 self.0.h2_conn_window_size
321 }
322
323 pub(crate) fn now(&self) -> Instant {
324 self.0.date_service.now()
325 }
326
327 #[doc(hidden)]
332 pub fn write_date_header(&self, dst: &mut BytesMut, camel_case: bool) {
333 let mut buf: [u8; 37] = [0; 37];
334
335 buf[..6].copy_from_slice(if camel_case { b"Date: " } else { b"date: " });
336
337 self.0
338 .date_service
339 .with_date(|date| buf[6..35].copy_from_slice(&date.bytes));
340
341 buf[35..].copy_from_slice(b"\r\n");
342 dst.extend_from_slice(&buf);
343 }
344
345 #[allow(unused)] pub(crate) fn write_date_header_value(&self, dst: &mut BytesMut) {
347 self.0
348 .date_service
349 .with_date(|date| dst.extend_from_slice(&date.bytes));
350 }
351}
352
353#[cfg(test)]
354mod tests {
355 use actix_rt::{
356 task::yield_now,
357 time::{sleep, sleep_until},
358 };
359 use memchr::memmem;
360
361 use super::*;
362 use crate::{date::DATE_VALUE_LENGTH, notify_on_drop};
363
364 #[actix_rt::test]
365 async fn test_date_service_update() {
366 let settings =
367 ServiceConfig::new(KeepAlive::Os, Duration::ZERO, Duration::ZERO, false, None);
368
369 yield_now().await;
370
371 let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
372 settings.write_date_header(&mut buf1, false);
373 let now1 = settings.now();
374
375 sleep_until((Instant::now() + Duration::from_secs(2)).into()).await;
376 yield_now().await;
377
378 let now2 = settings.now();
379 let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
380 settings.write_date_header(&mut buf2, false);
381
382 assert_ne!(now1, now2);
383
384 assert_ne!(buf1, buf2);
385
386 drop(settings);
387
388 let mut times = 0;
390 while !notify_on_drop::is_dropped() {
391 sleep(Duration::from_millis(100)).await;
392 times += 1;
393 assert!(times < 10, "Timeout waiting for task drop");
394 }
395 }
396
397 #[actix_rt::test]
398 async fn test_date_service_drop() {
399 let service = Rc::new(DateService::new());
400
401 yield_now().await;
403
404 let clone1 = service.clone();
405 let clone2 = service.clone();
406 let clone3 = service.clone();
407
408 drop(clone1);
409 assert!(!notify_on_drop::is_dropped());
410 drop(clone2);
411 assert!(!notify_on_drop::is_dropped());
412 drop(clone3);
413 assert!(!notify_on_drop::is_dropped());
414
415 drop(service);
416
417 let mut times = 0;
419 while !notify_on_drop::is_dropped() {
420 sleep(Duration::from_millis(100)).await;
421 times += 1;
422 assert!(times < 10, "Timeout waiting for task drop");
423 }
424 }
425
426 #[test]
427 fn test_date_len() {
428 assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len());
429 }
430
431 #[actix_rt::test]
432 async fn test_date() {
433 let settings = ServiceConfig::default();
434
435 let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
436 settings.write_date_header(&mut buf1, false);
437
438 let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
439 settings.write_date_header(&mut buf2, false);
440
441 assert_eq!(buf1, buf2);
442 }
443
444 #[actix_rt::test]
445 async fn test_date_camel_case() {
446 let settings = ServiceConfig::default();
447
448 let mut buf = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
449 settings.write_date_header(&mut buf, false);
450 assert!(memmem::find(&buf, b"date:").is_some());
451
452 let mut buf = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
453 settings.write_date_header(&mut buf, true);
454 assert!(memmem::find(&buf, b"Date:").is_some());
455 }
456}