1use std::{
2 net::SocketAddr,
3 rc::Rc,
4 time::{Duration, Instant},
5};
6
7use bytes::BytesMut;
8
9use crate::{date::DateService, KeepAlive};
10
11#[derive(Default, Debug)]
13pub struct ServiceConfigBuilder {
14 inner: Inner,
15}
16
17impl ServiceConfigBuilder {
18 pub fn new() -> Self {
29 Self::default()
30 }
31
32 pub fn secure(mut self, secure: bool) -> Self {
34 self.inner.secure = secure;
35 self
36 }
37
38 pub fn local_addr(mut self, local_addr: Option<SocketAddr>) -> Self {
40 self.inner.local_addr = local_addr;
41 self
42 }
43
44 pub fn keep_alive(mut self, keep_alive: KeepAlive) -> Self {
46 self.inner.keep_alive = keep_alive;
47 self
48 }
49
50 pub fn client_request_timeout(mut self, timeout: Duration) -> Self {
52 self.inner.client_request_timeout = timeout;
53 self
54 }
55
56 pub fn client_disconnect_timeout(mut self, timeout: Duration) -> Self {
59 self.inner.client_disconnect_timeout = timeout;
60 self
61 }
62
63 pub fn h1_allow_half_closed(mut self, allow: bool) -> Self {
69 self.inner.h1_allow_half_closed = allow;
70 self
71 }
72
73 pub fn build(self) -> ServiceConfig {
75 ServiceConfig(Rc::new(self.inner))
76 }
77}
78
79#[derive(Debug, Clone, Default)]
81pub struct ServiceConfig(Rc<Inner>);
82
83#[derive(Debug)]
84struct Inner {
85 keep_alive: KeepAlive,
86 client_request_timeout: Duration,
87 client_disconnect_timeout: Duration,
88 secure: bool,
89 local_addr: Option<SocketAddr>,
90 date_service: DateService,
91 h1_allow_half_closed: bool,
92}
93
94impl Default for Inner {
95 fn default() -> Self {
96 Self {
97 keep_alive: KeepAlive::default(),
98 client_request_timeout: Duration::from_secs(5),
99 client_disconnect_timeout: Duration::ZERO,
100 secure: false,
101 local_addr: None,
102 date_service: DateService::new(),
103 h1_allow_half_closed: true,
104 }
105 }
106}
107
108impl ServiceConfig {
109 pub fn new(
111 keep_alive: KeepAlive,
112 client_request_timeout: Duration,
113 client_disconnect_timeout: Duration,
114 secure: bool,
115 local_addr: Option<SocketAddr>,
116 ) -> ServiceConfig {
117 ServiceConfig(Rc::new(Inner {
118 keep_alive: keep_alive.normalize(),
119 client_request_timeout,
120 client_disconnect_timeout,
121 secure,
122 local_addr,
123 date_service: DateService::new(),
124 h1_allow_half_closed: true,
125 }))
126 }
127
128 #[inline]
130 pub fn secure(&self) -> bool {
131 self.0.secure
132 }
133
134 #[inline]
138 pub fn local_addr(&self) -> Option<SocketAddr> {
139 self.0.local_addr
140 }
141
142 #[inline]
144 pub fn keep_alive(&self) -> KeepAlive {
145 self.0.keep_alive
146 }
147
148 pub fn keep_alive_deadline(&self) -> Option<Instant> {
153 match self.keep_alive() {
154 KeepAlive::Timeout(dur) => Some(self.now() + dur),
155 KeepAlive::Os => None,
156 KeepAlive::Disabled => None,
157 }
158 }
159
160 pub fn client_request_deadline(&self) -> Option<Instant> {
165 let timeout = self.0.client_request_timeout;
166 (timeout != Duration::ZERO).then(|| self.now() + timeout)
167 }
168
169 pub fn client_disconnect_deadline(&self) -> Option<Instant> {
171 let timeout = self.0.client_disconnect_timeout;
172 (timeout != Duration::ZERO).then(|| self.now() + timeout)
173 }
174
175 pub fn h1_allow_half_closed(&self) -> bool {
181 self.0.h1_allow_half_closed
182 }
183
184 pub(crate) fn now(&self) -> Instant {
185 self.0.date_service.now()
186 }
187
188 #[doc(hidden)]
193 pub fn write_date_header(&self, dst: &mut BytesMut, camel_case: bool) {
194 let mut buf: [u8; 37] = [0; 37];
195
196 buf[..6].copy_from_slice(if camel_case { b"Date: " } else { b"date: " });
197
198 self.0
199 .date_service
200 .with_date(|date| buf[6..35].copy_from_slice(&date.bytes));
201
202 buf[35..].copy_from_slice(b"\r\n");
203 dst.extend_from_slice(&buf);
204 }
205
206 #[allow(unused)] pub(crate) fn write_date_header_value(&self, dst: &mut BytesMut) {
208 self.0
209 .date_service
210 .with_date(|date| dst.extend_from_slice(&date.bytes));
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use actix_rt::{
217 task::yield_now,
218 time::{sleep, sleep_until},
219 };
220 use memchr::memmem;
221
222 use super::*;
223 use crate::{date::DATE_VALUE_LENGTH, notify_on_drop};
224
225 #[actix_rt::test]
226 async fn test_date_service_update() {
227 let settings =
228 ServiceConfig::new(KeepAlive::Os, Duration::ZERO, Duration::ZERO, false, None);
229
230 yield_now().await;
231
232 let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
233 settings.write_date_header(&mut buf1, false);
234 let now1 = settings.now();
235
236 sleep_until((Instant::now() + Duration::from_secs(2)).into()).await;
237 yield_now().await;
238
239 let now2 = settings.now();
240 let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
241 settings.write_date_header(&mut buf2, false);
242
243 assert_ne!(now1, now2);
244
245 assert_ne!(buf1, buf2);
246
247 drop(settings);
248
249 let mut times = 0;
251 while !notify_on_drop::is_dropped() {
252 sleep(Duration::from_millis(100)).await;
253 times += 1;
254 assert!(times < 10, "Timeout waiting for task drop");
255 }
256 }
257
258 #[actix_rt::test]
259 async fn test_date_service_drop() {
260 let service = Rc::new(DateService::new());
261
262 yield_now().await;
264
265 let clone1 = service.clone();
266 let clone2 = service.clone();
267 let clone3 = service.clone();
268
269 drop(clone1);
270 assert!(!notify_on_drop::is_dropped());
271 drop(clone2);
272 assert!(!notify_on_drop::is_dropped());
273 drop(clone3);
274 assert!(!notify_on_drop::is_dropped());
275
276 drop(service);
277
278 let mut times = 0;
280 while !notify_on_drop::is_dropped() {
281 sleep(Duration::from_millis(100)).await;
282 times += 1;
283 assert!(times < 10, "Timeout waiting for task drop");
284 }
285 }
286
287 #[test]
288 fn test_date_len() {
289 assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len());
290 }
291
292 #[actix_rt::test]
293 async fn test_date() {
294 let settings = ServiceConfig::default();
295
296 let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
297 settings.write_date_header(&mut buf1, false);
298
299 let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
300 settings.write_date_header(&mut buf2, false);
301
302 assert_eq!(buf1, buf2);
303 }
304
305 #[actix_rt::test]
306 async fn test_date_camel_case() {
307 let settings = ServiceConfig::default();
308
309 let mut buf = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
310 settings.write_date_header(&mut buf, false);
311 assert!(memmem::find(&buf, b"date:").is_some());
312
313 let mut buf = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
314 settings.write_date_header(&mut buf, true);
315 assert!(memmem::find(&buf, b"Date:").is_some());
316 }
317}