1use std::{
2 net::SocketAddr,
3 rc::Rc,
4 time::{Duration, Instant},
5};
6
7use bytes::BytesMut;
8
9use crate::{date::DateService, KeepAlive};
10
11pub(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;
23
24#[derive(Default, Debug)]
26pub struct ServiceConfigBuilder {
27 inner: Inner,
28}
29
30impl ServiceConfigBuilder {
31 pub fn new() -> Self {
42 Self::default()
43 }
44
45 pub fn secure(mut self, secure: bool) -> Self {
47 self.inner.secure = secure;
48 self
49 }
50
51 pub fn local_addr(mut self, local_addr: Option<SocketAddr>) -> Self {
53 self.inner.local_addr = local_addr;
54 self
55 }
56
57 pub fn keep_alive(mut self, keep_alive: KeepAlive) -> Self {
59 self.inner.keep_alive = keep_alive;
60 self
61 }
62
63 pub fn client_request_timeout(mut self, timeout: Duration) -> Self {
65 self.inner.client_request_timeout = timeout;
66 self
67 }
68
69 pub fn client_disconnect_timeout(mut self, timeout: Duration) -> Self {
72 self.inner.client_disconnect_timeout = timeout;
73 self
74 }
75
76 pub fn tcp_nodelay(mut self, nodelay: Option<bool>) -> Self {
78 self.inner.tcp_nodelay = nodelay;
79 self
80 }
81
82 pub fn h1_allow_half_closed(mut self, allow: bool) -> Self {
88 self.inner.h1_allow_half_closed = allow;
89 self
90 }
91
92 pub fn h1_write_buffer_size(mut self, size: usize) -> Self {
102 assert!(
103 size > 0,
104 "HTTP/1 write buffer size must be greater than zero"
105 );
106
107 self.inner.h1_write_buffer_size = size;
108 self
109 }
110
111 pub fn h2_initial_window_size(mut self, size: u32) -> Self {
118 self.inner.h2_stream_window_size = size;
119 self
120 }
121
122 pub fn h2_initial_connection_window_size(mut self, size: u32) -> Self {
129 self.inner.h2_conn_window_size = size;
130 self
131 }
132
133 pub fn build(self) -> ServiceConfig {
135 ServiceConfig(Rc::new(self.inner))
136 }
137}
138
139#[derive(Debug, Clone, Default)]
141pub struct ServiceConfig(Rc<Inner>);
142
143#[derive(Debug)]
144struct Inner {
145 keep_alive: KeepAlive,
146 client_request_timeout: Duration,
147 client_disconnect_timeout: Duration,
148 secure: bool,
149 local_addr: Option<SocketAddr>,
150 tcp_nodelay: Option<bool>,
151 date_service: DateService,
152 h1_allow_half_closed: bool,
153 h1_write_buffer_size: usize,
154 h2_conn_window_size: u32,
155 h2_stream_window_size: u32,
156}
157
158impl Default for Inner {
159 fn default() -> Self {
160 Self {
161 keep_alive: KeepAlive::default(),
162 client_request_timeout: Duration::from_secs(5),
163 client_disconnect_timeout: Duration::ZERO,
164 secure: false,
165 local_addr: None,
166 tcp_nodelay: None,
167 date_service: DateService::new(),
168 h1_allow_half_closed: true,
169 h1_write_buffer_size: DEFAULT_H1_WRITE_BUFFER_SIZE,
170 h2_conn_window_size: DEFAULT_H2_CONN_WINDOW_SIZE,
171 h2_stream_window_size: DEFAULT_H2_STREAM_WINDOW_SIZE,
172 }
173 }
174}
175
176impl ServiceConfig {
177 pub fn new(
179 keep_alive: KeepAlive,
180 client_request_timeout: Duration,
181 client_disconnect_timeout: Duration,
182 secure: bool,
183 local_addr: Option<SocketAddr>,
184 ) -> ServiceConfig {
185 ServiceConfig(Rc::new(Inner {
186 keep_alive: keep_alive.normalize(),
187 client_request_timeout,
188 client_disconnect_timeout,
189 secure,
190 local_addr,
191 tcp_nodelay: None,
192 date_service: DateService::new(),
193 h1_allow_half_closed: true,
194 h1_write_buffer_size: DEFAULT_H1_WRITE_BUFFER_SIZE,
195 h2_conn_window_size: DEFAULT_H2_CONN_WINDOW_SIZE,
196 h2_stream_window_size: DEFAULT_H2_STREAM_WINDOW_SIZE,
197 }))
198 }
199
200 #[inline]
202 pub fn secure(&self) -> bool {
203 self.0.secure
204 }
205
206 #[inline]
210 pub fn local_addr(&self) -> Option<SocketAddr> {
211 self.0.local_addr
212 }
213
214 #[inline]
216 pub fn keep_alive(&self) -> KeepAlive {
217 self.0.keep_alive
218 }
219
220 pub fn keep_alive_deadline(&self) -> Option<Instant> {
225 match self.keep_alive() {
226 KeepAlive::Timeout(dur) => Some(self.now() + dur),
227 KeepAlive::Os => None,
228 KeepAlive::Disabled => None,
229 }
230 }
231
232 pub fn client_request_deadline(&self) -> Option<Instant> {
237 let timeout = self.0.client_request_timeout;
238 (timeout != Duration::ZERO).then(|| self.now() + timeout)
239 }
240
241 pub fn client_disconnect_deadline(&self) -> Option<Instant> {
243 let timeout = self.0.client_disconnect_timeout;
244 (timeout != Duration::ZERO).then(|| self.now() + timeout)
245 }
246
247 pub fn h1_allow_half_closed(&self) -> bool {
253 self.0.h1_allow_half_closed
254 }
255
256 pub fn h1_write_buffer_size(&self) -> usize {
258 self.0.h1_write_buffer_size
259 }
260
261 pub fn tcp_nodelay(&self) -> Option<bool> {
263 self.0.tcp_nodelay
264 }
265
266 pub fn h2_initial_window_size(&self) -> u32 {
268 self.0.h2_stream_window_size
269 }
270
271 pub fn h2_initial_connection_window_size(&self) -> u32 {
273 self.0.h2_conn_window_size
274 }
275
276 pub(crate) fn now(&self) -> Instant {
277 self.0.date_service.now()
278 }
279
280 #[doc(hidden)]
285 pub fn write_date_header(&self, dst: &mut BytesMut, camel_case: bool) {
286 let mut buf: [u8; 37] = [0; 37];
287
288 buf[..6].copy_from_slice(if camel_case { b"Date: " } else { b"date: " });
289
290 self.0
291 .date_service
292 .with_date(|date| buf[6..35].copy_from_slice(&date.bytes));
293
294 buf[35..].copy_from_slice(b"\r\n");
295 dst.extend_from_slice(&buf);
296 }
297
298 #[allow(unused)] pub(crate) fn write_date_header_value(&self, dst: &mut BytesMut) {
300 self.0
301 .date_service
302 .with_date(|date| dst.extend_from_slice(&date.bytes));
303 }
304}
305
306#[cfg(test)]
307mod tests {
308 use actix_rt::{
309 task::yield_now,
310 time::{sleep, sleep_until},
311 };
312 use memchr::memmem;
313
314 use super::*;
315 use crate::{date::DATE_VALUE_LENGTH, notify_on_drop};
316
317 #[actix_rt::test]
318 async fn test_date_service_update() {
319 let settings =
320 ServiceConfig::new(KeepAlive::Os, Duration::ZERO, Duration::ZERO, false, None);
321
322 yield_now().await;
323
324 let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
325 settings.write_date_header(&mut buf1, false);
326 let now1 = settings.now();
327
328 sleep_until((Instant::now() + Duration::from_secs(2)).into()).await;
329 yield_now().await;
330
331 let now2 = settings.now();
332 let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
333 settings.write_date_header(&mut buf2, false);
334
335 assert_ne!(now1, now2);
336
337 assert_ne!(buf1, buf2);
338
339 drop(settings);
340
341 let mut times = 0;
343 while !notify_on_drop::is_dropped() {
344 sleep(Duration::from_millis(100)).await;
345 times += 1;
346 assert!(times < 10, "Timeout waiting for task drop");
347 }
348 }
349
350 #[actix_rt::test]
351 async fn test_date_service_drop() {
352 let service = Rc::new(DateService::new());
353
354 yield_now().await;
356
357 let clone1 = service.clone();
358 let clone2 = service.clone();
359 let clone3 = service.clone();
360
361 drop(clone1);
362 assert!(!notify_on_drop::is_dropped());
363 drop(clone2);
364 assert!(!notify_on_drop::is_dropped());
365 drop(clone3);
366 assert!(!notify_on_drop::is_dropped());
367
368 drop(service);
369
370 let mut times = 0;
372 while !notify_on_drop::is_dropped() {
373 sleep(Duration::from_millis(100)).await;
374 times += 1;
375 assert!(times < 10, "Timeout waiting for task drop");
376 }
377 }
378
379 #[test]
380 fn test_date_len() {
381 assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len());
382 }
383
384 #[actix_rt::test]
385 async fn test_date() {
386 let settings = ServiceConfig::default();
387
388 let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
389 settings.write_date_header(&mut buf1, false);
390
391 let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
392 settings.write_date_header(&mut buf2, false);
393
394 assert_eq!(buf1, buf2);
395 }
396
397 #[actix_rt::test]
398 async fn test_date_camel_case() {
399 let settings = ServiceConfig::default();
400
401 let mut buf = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
402 settings.write_date_header(&mut buf, false);
403 assert!(memmem::find(&buf, b"date:").is_some());
404
405 let mut buf = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
406 settings.write_date_header(&mut buf, true);
407 assert!(memmem::find(&buf, b"Date:").is_some());
408 }
409}