actori_http/
config.rs

1use std::cell::UnsafeCell;
2use std::fmt::Write;
3use std::rc::Rc;
4use std::time::Duration;
5use std::{fmt, net};
6
7use actori_rt::time::{delay_for, delay_until, Delay, Instant};
8use bytes::BytesMut;
9use futures_util::{future, FutureExt};
10use time;
11
12// "Sun, 06 Nov 1994 08:49:37 GMT".len()
13const DATE_VALUE_LENGTH: usize = 29;
14
15#[derive(Debug, PartialEq, Clone, Copy)]
16/// Server keep-alive setting
17pub enum KeepAlive {
18    /// Keep alive in seconds
19    Timeout(usize),
20    /// Relay on OS to shutdown tcp connection
21    Os,
22    /// Disabled
23    Disabled,
24}
25
26impl From<usize> for KeepAlive {
27    fn from(keepalive: usize) -> Self {
28        KeepAlive::Timeout(keepalive)
29    }
30}
31
32impl From<Option<usize>> for KeepAlive {
33    fn from(keepalive: Option<usize>) -> Self {
34        if let Some(keepalive) = keepalive {
35            KeepAlive::Timeout(keepalive)
36        } else {
37            KeepAlive::Disabled
38        }
39    }
40}
41
42/// Http service configuration
43pub struct ServiceConfig(Rc<Inner>);
44
45struct Inner {
46    keep_alive: Option<Duration>,
47    client_timeout: u64,
48    client_disconnect: u64,
49    ka_enabled: bool,
50    secure: bool,
51    local_addr: Option<std::net::SocketAddr>,
52    timer: DateService,
53}
54
55impl Clone for ServiceConfig {
56    fn clone(&self) -> Self {
57        ServiceConfig(self.0.clone())
58    }
59}
60
61impl Default for ServiceConfig {
62    fn default() -> Self {
63        Self::new(KeepAlive::Timeout(5), 0, 0, false, None)
64    }
65}
66
67impl ServiceConfig {
68    /// Create instance of `ServiceConfig`
69    pub fn new(
70        keep_alive: KeepAlive,
71        client_timeout: u64,
72        client_disconnect: u64,
73        secure: bool,
74        local_addr: Option<net::SocketAddr>,
75    ) -> ServiceConfig {
76        let (keep_alive, ka_enabled) = match keep_alive {
77            KeepAlive::Timeout(val) => (val as u64, true),
78            KeepAlive::Os => (0, true),
79            KeepAlive::Disabled => (0, false),
80        };
81        let keep_alive = if ka_enabled && keep_alive > 0 {
82            Some(Duration::from_secs(keep_alive))
83        } else {
84            None
85        };
86
87        ServiceConfig(Rc::new(Inner {
88            keep_alive,
89            ka_enabled,
90            client_timeout,
91            client_disconnect,
92            secure,
93            local_addr,
94            timer: DateService::new(),
95        }))
96    }
97
98    #[inline]
99    /// Returns true if connection is secure(https)
100    pub fn secure(&self) -> bool {
101        self.0.secure
102    }
103
104    #[inline]
105    /// Returns the local address that this server is bound to.
106    pub fn local_addr(&self) -> Option<net::SocketAddr> {
107        self.0.local_addr
108    }
109
110    #[inline]
111    /// Keep alive duration if configured.
112    pub fn keep_alive(&self) -> Option<Duration> {
113        self.0.keep_alive
114    }
115
116    #[inline]
117    /// Return state of connection keep-alive funcitonality
118    pub fn keep_alive_enabled(&self) -> bool {
119        self.0.ka_enabled
120    }
121
122    #[inline]
123    /// Client timeout for first request.
124    pub fn client_timer(&self) -> Option<Delay> {
125        let delay_time = self.0.client_timeout;
126        if delay_time != 0 {
127            Some(delay_until(
128                self.0.timer.now() + Duration::from_millis(delay_time),
129            ))
130        } else {
131            None
132        }
133    }
134
135    /// Client timeout for first request.
136    pub fn client_timer_expire(&self) -> Option<Instant> {
137        let delay = self.0.client_timeout;
138        if delay != 0 {
139            Some(self.0.timer.now() + Duration::from_millis(delay))
140        } else {
141            None
142        }
143    }
144
145    /// Client disconnect timer
146    pub fn client_disconnect_timer(&self) -> Option<Instant> {
147        let delay = self.0.client_disconnect;
148        if delay != 0 {
149            Some(self.0.timer.now() + Duration::from_millis(delay))
150        } else {
151            None
152        }
153    }
154
155    #[inline]
156    /// Return keep-alive timer delay is configured.
157    pub fn keep_alive_timer(&self) -> Option<Delay> {
158        if let Some(ka) = self.0.keep_alive {
159            Some(delay_until(self.0.timer.now() + ka))
160        } else {
161            None
162        }
163    }
164
165    /// Keep-alive expire time
166    pub fn keep_alive_expire(&self) -> Option<Instant> {
167        if let Some(ka) = self.0.keep_alive {
168            Some(self.0.timer.now() + ka)
169        } else {
170            None
171        }
172    }
173
174    #[inline]
175    pub(crate) fn now(&self) -> Instant {
176        self.0.timer.now()
177    }
178
179    #[doc(hidden)]
180    pub fn set_date(&self, dst: &mut BytesMut) {
181        let mut buf: [u8; 39] = [0; 39];
182        buf[..6].copy_from_slice(b"date: ");
183        self.0
184            .timer
185            .set_date(|date| buf[6..35].copy_from_slice(&date.bytes));
186        buf[35..].copy_from_slice(b"\r\n\r\n");
187        dst.extend_from_slice(&buf);
188    }
189
190    pub(crate) fn set_date_header(&self, dst: &mut BytesMut) {
191        self.0
192            .timer
193            .set_date(|date| dst.extend_from_slice(&date.bytes));
194    }
195}
196
197#[derive(Copy, Clone)]
198struct Date {
199    bytes: [u8; DATE_VALUE_LENGTH],
200    pos: usize,
201}
202
203impl Date {
204    fn new() -> Date {
205        let mut date = Date {
206            bytes: [0; DATE_VALUE_LENGTH],
207            pos: 0,
208        };
209        date.update();
210        date
211    }
212    fn update(&mut self) {
213        self.pos = 0;
214        write!(self, "{}", time::at_utc(time::get_time()).rfc822()).unwrap();
215    }
216}
217
218impl fmt::Write for Date {
219    fn write_str(&mut self, s: &str) -> fmt::Result {
220        let len = s.len();
221        self.bytes[self.pos..self.pos + len].copy_from_slice(s.as_bytes());
222        self.pos += len;
223        Ok(())
224    }
225}
226
227#[derive(Clone)]
228struct DateService(Rc<DateServiceInner>);
229
230struct DateServiceInner {
231    current: UnsafeCell<Option<(Date, Instant)>>,
232}
233
234impl DateServiceInner {
235    fn new() -> Self {
236        DateServiceInner {
237            current: UnsafeCell::new(None),
238        }
239    }
240
241    fn reset(&self) {
242        unsafe { (&mut *self.current.get()).take() };
243    }
244
245    fn update(&self) {
246        let now = Instant::now();
247        let date = Date::new();
248        *(unsafe { &mut *self.current.get() }) = Some((date, now));
249    }
250}
251
252impl DateService {
253    fn new() -> Self {
254        DateService(Rc::new(DateServiceInner::new()))
255    }
256
257    fn check_date(&self) {
258        if unsafe { (&*self.0.current.get()).is_none() } {
259            self.0.update();
260
261            // periodic date update
262            let s = self.clone();
263            actori_rt::spawn(delay_for(Duration::from_millis(500)).then(move |_| {
264                s.0.reset();
265                future::ready(())
266            }));
267        }
268    }
269
270    fn now(&self) -> Instant {
271        self.check_date();
272        unsafe { (&*self.0.current.get()).as_ref().unwrap().1 }
273    }
274
275    fn set_date<F: FnMut(&Date)>(&self, mut f: F) {
276        self.check_date();
277        f(&unsafe { (&*self.0.current.get()).as_ref().unwrap().0 })
278    }
279}
280
281#[cfg(test)]
282mod tests {
283    use super::*;
284
285    #[test]
286    fn test_date_len() {
287        assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len());
288    }
289
290    #[actori_rt::test]
291    async fn test_date() {
292        let settings = ServiceConfig::new(KeepAlive::Os, 0, 0, false, None);
293        let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
294        settings.set_date(&mut buf1);
295        let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
296        settings.set_date(&mut buf2);
297        assert_eq!(buf1, buf2);
298    }
299}