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
12const DATE_VALUE_LENGTH: usize = 29;
14
15#[derive(Debug, PartialEq, Clone, Copy)]
16pub enum KeepAlive {
18 Timeout(usize),
20 Os,
22 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
42pub 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 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 pub fn secure(&self) -> bool {
101 self.0.secure
102 }
103
104 #[inline]
105 pub fn local_addr(&self) -> Option<net::SocketAddr> {
107 self.0.local_addr
108 }
109
110 #[inline]
111 pub fn keep_alive(&self) -> Option<Duration> {
113 self.0.keep_alive
114 }
115
116 #[inline]
117 pub fn keep_alive_enabled(&self) -> bool {
119 self.0.ka_enabled
120 }
121
122 #[inline]
123 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 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 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 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 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 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}