1use std::{cell::Ref, cell::RefCell, cell::RefMut, fmt, net, rc::Rc};
2
3use bitflags::bitflags;
4use urly::Url;
5
6use crate::http::header::HeaderMap;
7use crate::http::{HeaderItem, Method, StatusCode, Version, h1::Codec};
8use crate::io::{IoBoxed, IoRef, types};
9use crate::util::Extensions;
10
11#[derive(Copy, Clone, PartialEq, Eq, Debug)]
13pub enum ConnectionType {
14 Close,
16 KeepAlive,
18 Upgrade,
20}
21
22bitflags! {
23 #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
24 pub(crate) struct Flags: u8 {
25 const CLOSE = 0b0000_0001;
26 const KEEP_ALIVE = 0b0000_0010;
27 const UPGRADE = 0b0000_0100;
28 const EXPECT = 0b0000_1000;
29 const NO_CHUNKING = 0b0001_0000;
30 }
31}
32
33pub(crate) trait Head: Default + 'static + fmt::Debug {
34 fn clear(&mut self);
35
36 fn with_pool<F, R>(f: F) -> Option<R>
38 where
39 F: FnOnce(&MessagePool<Self>) -> R;
40}
41
42#[derive(Clone, Debug)]
43pub(crate) enum CurrentIo {
44 Ref(IoRef),
45 Io(Rc<dyn IoAccess>),
46 None,
47}
48
49pub(crate) trait IoAccess: fmt::Debug {
50 fn get(&self) -> Option<&IoRef>;
51
52 fn take(&self) -> Option<(IoBoxed, Codec)>;
53}
54
55impl CurrentIo {
56 pub(crate) fn new(io: Rc<dyn IoAccess>) -> Self {
57 CurrentIo::Io(io)
58 }
59
60 pub(crate) fn as_ref(&self) -> Option<&IoRef> {
61 match self {
62 CurrentIo::Ref(io) => Some(io),
63 CurrentIo::Io(io) => io.get(),
64 CurrentIo::None => None,
65 }
66 }
67
68 pub(crate) fn take(&self) -> Option<(IoBoxed, Codec)> {
69 match self {
70 CurrentIo::Io(io) => io.take(),
71 _ => None,
72 }
73 }
74}
75
76#[derive(Debug)]
78pub struct RequestHead {
79 pub id: usize,
81 pub uri: Url,
83 pub method: Method,
85 pub version: Version,
87 pub headers: HeaderMap,
89 pub headers_vec: Vec<HeaderItem>,
95 pub extensions: RefCell<Extensions>,
97 pub(crate) io: CurrentIo,
98 pub(crate) flags: Flags,
99}
100
101impl Default for RequestHead {
102 fn default() -> RequestHead {
103 RequestHead {
104 id: 0,
105 io: CurrentIo::None,
106 uri: Url::new(),
107 method: Method::default(),
108 version: Version::HTTP_11,
109 headers: HeaderMap::with_capacity(16),
110 headers_vec: Vec::default(),
111 flags: Flags::empty(),
112 extensions: RefCell::new(Extensions::new()),
113 }
114 }
115}
116
117impl Head for RequestHead {
118 fn clear(&mut self) {
119 self.io = CurrentIo::None;
120 self.uri = Url::new();
123 self.flags = Flags::empty();
124 self.version = Version::HTTP_11;
125 self.headers.clear();
126 self.headers_vec.clear();
127 self.extensions.get_mut().clear();
128 }
129
130 fn with_pool<F, R>(f: F) -> Option<R>
131 where
132 F: FnOnce(&MessagePool<Self>) -> R,
133 {
134 REQUEST_POOL.try_with(|p| f(p)).ok()
135 }
136}
137
138impl RequestHead {
139 #[inline]
141 pub fn extensions(&self) -> Ref<'_, Extensions> {
142 self.extensions.borrow()
143 }
144
145 #[inline]
147 pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
148 self.extensions.borrow_mut()
149 }
150
151 pub fn headers(&self) -> &HeaderMap {
153 &self.headers
154 }
155
156 pub fn headers_mut(&mut self) -> &mut HeaderMap {
158 &mut self.headers
159 }
160
161 pub fn headers_vec(&self) -> &[HeaderItem] {
163 &self.headers_vec
164 }
165
166 #[inline]
167 pub fn set_connection_type(&mut self, ctype: ConnectionType) {
173 match ctype {
174 ConnectionType::Close => self.flags.insert(Flags::CLOSE),
175 ConnectionType::KeepAlive => self.flags.insert(Flags::KEEP_ALIVE),
176 ConnectionType::Upgrade => self.flags.insert(Flags::UPGRADE),
177 }
178 }
179
180 #[inline]
181 pub fn connection_type(&self) -> ConnectionType {
183 if self.flags.contains(Flags::CLOSE) {
184 ConnectionType::Close
185 } else if self.flags.contains(Flags::KEEP_ALIVE) {
186 ConnectionType::KeepAlive
187 } else if self.flags.contains(Flags::UPGRADE) {
188 ConnectionType::Upgrade
189 } else if self.version < Version::HTTP_11 {
190 ConnectionType::Close
191 } else {
192 ConnectionType::KeepAlive
193 }
194 }
195
196 #[inline]
197 pub fn upgrade(&self) -> bool {
199 self.flags.contains(Flags::UPGRADE)
200 }
201
202 #[inline]
203 pub fn expect(&self) -> bool {
205 self.flags.contains(Flags::EXPECT)
206 }
207
208 #[inline]
209 pub fn chunked(&self) -> bool {
211 !self.flags.contains(Flags::NO_CHUNKING)
212 }
213
214 #[inline]
215 pub fn no_chunking(&mut self, val: bool) {
219 if val {
220 self.flags.insert(Flags::NO_CHUNKING);
221 } else {
222 self.flags.remove(Flags::NO_CHUNKING);
223 }
224 }
225
226 #[inline]
227 pub(crate) fn set_expect(&mut self) {
228 self.flags.insert(Flags::EXPECT);
229 }
230
231 #[inline]
232 pub(crate) fn set_upgrade(&mut self) {
233 self.flags.insert(Flags::UPGRADE);
234 }
235
236 #[inline]
241 pub fn peer_addr(&self) -> Option<net::SocketAddr> {
242 self.io.as_ref().and_then(|io| {
243 io.query::<types::PeerAddr>()
244 .get()
245 .map(types::PeerAddr::into_inner)
246 })
247 }
248
249 pub fn take_io(&self) -> Option<(IoBoxed, Codec)> {
255 self.io.take()
256 }
257
258 #[doc(hidden)]
259 pub fn remove_io(&mut self) {
260 self.io = CurrentIo::None;
261 }
262}
263
264#[derive(Debug)]
266pub struct ResponseHead {
267 pub version: Version,
269 pub status: StatusCode,
271 pub headers: HeaderMap,
273 pub headers_vec: Vec<HeaderItem>,
279 pub reason: Option<&'static str>,
281 pub(crate) io: CurrentIo,
282 pub(crate) extensions: RefCell<Extensions>,
283 flags: Flags,
284}
285
286impl ResponseHead {
287 #[inline]
289 pub fn new(status: StatusCode, version: Version) -> ResponseHead {
290 ResponseHead {
291 status,
292 version,
293 headers: HeaderMap::with_capacity(12),
294 headers_vec: Vec::default(),
295 reason: None,
296 flags: Flags::empty(),
297 io: CurrentIo::None,
298 extensions: RefCell::new(Extensions::new()),
299 }
300 }
301
302 #[inline]
304 pub fn extensions(&self) -> Ref<'_, Extensions> {
305 self.extensions.borrow()
306 }
307
308 #[inline]
310 pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
311 self.extensions.borrow_mut()
312 }
313
314 #[inline]
315 pub fn headers(&self) -> &HeaderMap {
317 &self.headers
318 }
319
320 #[inline]
321 pub fn headers_mut(&mut self) -> &mut HeaderMap {
323 &mut self.headers
324 }
325
326 pub fn headers_vec(&self) -> &[HeaderItem] {
328 &self.headers_vec
329 }
330
331 #[inline]
332 pub fn set_connection_type(&mut self, ctype: ConnectionType) {
338 match ctype {
339 ConnectionType::Close => self.flags.insert(Flags::CLOSE),
340 ConnectionType::KeepAlive => self.flags.insert(Flags::KEEP_ALIVE),
341 ConnectionType::Upgrade => self.flags.insert(Flags::UPGRADE),
342 }
343 }
344
345 #[inline]
346 pub fn connection_type(&self) -> ConnectionType {
348 if self.flags.contains(Flags::CLOSE) {
349 ConnectionType::Close
350 } else if self.flags.contains(Flags::KEEP_ALIVE) {
351 ConnectionType::KeepAlive
352 } else if self.flags.contains(Flags::UPGRADE) {
353 ConnectionType::Upgrade
354 } else if self.version < Version::HTTP_11 {
355 ConnectionType::Close
356 } else {
357 ConnectionType::KeepAlive
358 }
359 }
360
361 #[inline]
362 pub fn keep_alive(&self) -> bool {
364 self.connection_type() == ConnectionType::KeepAlive
365 }
366
367 #[inline]
368 pub fn upgrade(&self) -> bool {
370 self.connection_type() == ConnectionType::Upgrade
371 }
372
373 #[inline]
377 pub fn reason(&self) -> &str {
378 if let Some(reason) = self.reason {
379 reason
380 } else {
381 self.status.canonical_reason().unwrap_or("")
382 }
383 }
384
385 #[inline]
386 pub(crate) fn ctype(&self) -> Option<ConnectionType> {
387 if self.flags.contains(Flags::CLOSE) {
388 Some(ConnectionType::Close)
389 } else if self.flags.contains(Flags::KEEP_ALIVE) {
390 Some(ConnectionType::KeepAlive)
391 } else if self.flags.contains(Flags::UPGRADE) {
392 Some(ConnectionType::Upgrade)
393 } else {
394 None
395 }
396 }
397
398 #[inline]
399 pub fn chunked(&self) -> bool {
401 !self.flags.contains(Flags::NO_CHUNKING)
402 }
403
404 #[inline]
405 pub fn no_chunking(&mut self, val: bool) {
407 if val {
408 self.flags.insert(Flags::NO_CHUNKING);
409 } else {
410 self.flags.remove(Flags::NO_CHUNKING);
411 }
412 }
413}
414
415impl Default for ResponseHead {
416 fn default() -> Self {
417 Self::new(StatusCode::default(), Version::default())
418 }
419}
420
421impl Head for ResponseHead {
422 fn clear(&mut self) {
423 self.reason = None;
424 self.headers.clear();
425 self.headers_vec.clear();
426 self.io = CurrentIo::None;
427 self.flags = Flags::empty();
428 self.extensions.get_mut().clear();
429 }
430
431 fn with_pool<F, R>(f: F) -> Option<R>
432 where
433 F: FnOnce(&MessagePool<Self>) -> R,
434 {
435 RESPONSE_POOL.try_with(|p| f(p)).ok()
436 }
437}
438
439#[derive(Debug)]
440pub(crate) struct Message<T: Head> {
441 head: Rc<T>,
442}
443
444impl<T: Head> Message<T> {
445 pub(crate) fn new() -> Self {
447 let head = T::with_pool(MessagePool::get_head)
448 .flatten()
449 .unwrap_or_else(|| Rc::new(T::default()));
450 Message { head }
451 }
452
453 pub(crate) fn clear(&mut self) {
455 if let Some(head) = Rc::get_mut(&mut self.head) {
456 head.clear();
457 }
458 }
459}
460
461impl Message<ResponseHead> {
462 pub(crate) fn with_status(status: StatusCode) -> Self {
464 let mut msg = Self::new();
465 msg.status = status;
466 msg
467 }
468
469 pub(crate) fn copy(&self) -> Self {
471 let mut msg = Self::with_status(self.status);
472 msg.version = self.version;
473 msg.headers = self.headers.clone();
474 msg.headers_vec.clone_from(&self.headers_vec);
475 msg.reason = self.reason;
476 msg.io = self.io.clone();
477 msg.flags = self.flags;
478 msg
479 }
480}
481
482impl<T: Head> Clone for Message<T> {
483 fn clone(&self) -> Self {
484 Self {
485 head: self.head.clone(),
486 }
487 }
488}
489
490impl<T: Head> std::ops::Deref for Message<T> {
491 type Target = T;
492
493 fn deref(&self) -> &Self::Target {
494 self.head.as_ref()
495 }
496}
497
498impl<T: Head> std::ops::DerefMut for Message<T> {
499 fn deref_mut(&mut self) -> &mut Self::Target {
500 Rc::get_mut(&mut self.head).expect("Multiple copies exist")
501 }
502}
503
504impl<T: Head> Drop for Message<T> {
505 fn drop(&mut self) {
506 if let Some(head) = Rc::get_mut(&mut self.head) {
507 head.clear();
510 T::with_pool(|pool| {
511 if let Ok(mut v) = pool.0.try_borrow_mut()
512 && v.len() < 128
513 {
514 v.push(self.head.clone());
515 }
516 });
517 }
518 }
519}
520
521pub(crate) struct MessagePool<T: Head>(RefCell<Vec<Rc<T>>>);
523
524thread_local!(static REQUEST_POOL: MessagePool<RequestHead> = MessagePool::<RequestHead>::new());
525thread_local!(static RESPONSE_POOL: MessagePool<ResponseHead> = MessagePool::<ResponseHead>::new());
526
527impl<T: Head> MessagePool<T> {
528 fn new() -> MessagePool<T> {
529 MessagePool(RefCell::new(Vec::with_capacity(256)))
530 }
531
532 #[inline]
534 fn get_head(&self) -> Option<Rc<T>> {
535 self.0.try_borrow_mut().ok()?.pop()
536 }
537}
538
539#[cfg(test)]
540mod tests {
541 use super::*;
542
543 #[test]
544 fn nested_message_drop() {
545 let inner = Message::<RequestHead>::new();
546 let outer = Message::<RequestHead>::new();
547 outer.extensions_mut().insert(inner);
548 let mut res = Message::<ResponseHead>::with_status(StatusCode::OK);
549 res.extensions
550 .get_mut()
551 .insert(Message::<ResponseHead>::new());
552 outer.extensions_mut().insert(res);
553 drop(outer);
554
555 let _ = Message::<RequestHead>::new();
556 let _ = Message::<ResponseHead>::new();
557 }
558
559 #[test]
560 fn message_drop_after_pool_destroyed() {
561 struct Holder(Option<Message<RequestHead>>, Option<Message<ResponseHead>>);
562
563 impl Drop for Holder {
564 fn drop(&mut self) {
565 drop(self.0.take());
566 drop(self.1.take());
567 drop(Message::<RequestHead>::new());
568 }
569 }
570
571 thread_local!(static HOLDER: RefCell<Option<Holder>> = const { RefCell::new(None) });
572
573 std::thread::spawn(|| {
574 HOLDER.with(|_| ());
576 let req = Message::<RequestHead>::new();
577 let res = Message::<ResponseHead>::new();
578 HOLDER.with(|h| *h.borrow_mut() = Some(Holder(Some(req), Some(res))));
579 })
580 .join()
581 .unwrap();
582 }
583
584 #[test]
585 fn response_connection_type() {
586 let mut res = Message::<ResponseHead>::with_status(StatusCode::OK);
587 assert_eq!(res.connection_type(), ConnectionType::KeepAlive);
588 res.version = Version::HTTP_10;
589 assert_eq!(res.connection_type(), ConnectionType::Close);
590 res.set_connection_type(ConnectionType::KeepAlive);
591 assert_eq!(res.connection_type(), ConnectionType::KeepAlive);
592 }
593
594 #[test]
595 fn message_clone() {
596 let mut msg = Message::<RequestHead>::new();
597 msg.method = Method::POST;
598 let msg2 = msg.clone();
599 assert_eq!(msg2.method, Method::POST);
600 assert!(CurrentIo::None.take().is_none());
601 }
602}