wreq-rb 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +1922 -397
  3. data/LICENSE +203 -0
  4. data/README.md +19 -15
  5. data/ext/wreq_rb/Cargo.toml +4 -6
  6. data/ext/wreq_rb/src/client.rs +41 -48
  7. data/lib/wreq-rb/version.rb +1 -1
  8. data/patches/0001-add-transfer-size-tracking.patch +76 -67
  9. data/vendor/wreq/Cargo.toml +119 -71
  10. data/vendor/wreq/README.md +25 -20
  11. data/vendor/wreq/bench/http1.rs +25 -0
  12. data/vendor/wreq/bench/http1_over_tls.rs +25 -0
  13. data/vendor/wreq/bench/http2.rs +25 -0
  14. data/vendor/wreq/bench/http2_over_tls.rs +25 -0
  15. data/vendor/wreq/bench/support/bench.rs +91 -0
  16. data/vendor/wreq/bench/support/client.rs +217 -0
  17. data/vendor/wreq/bench/support/server.rs +188 -0
  18. data/vendor/wreq/bench/support.rs +56 -0
  19. data/vendor/wreq/examples/cert_store.rs +4 -4
  20. data/vendor/wreq/examples/{emulation.rs → emulate.rs} +2 -2
  21. data/vendor/wreq/examples/http2_websocket.rs +2 -2
  22. data/vendor/wreq/examples/keylog.rs +3 -3
  23. data/vendor/wreq/examples/{request_with_emulation.rs → request_with_emulate.rs} +2 -2
  24. data/vendor/wreq/examples/rt.rs +23 -0
  25. data/vendor/wreq/src/client/body.rs +23 -61
  26. data/vendor/wreq/src/client/emulate.rs +119 -0
  27. data/vendor/wreq/src/client/{http/future.rs → future.rs} +11 -32
  28. data/vendor/wreq/src/client/{http → layer}/client/pool.rs +66 -61
  29. data/vendor/wreq/src/client/{http → layer}/client.rs +416 -270
  30. data/vendor/wreq/src/client/layer/config.rs +27 -6
  31. data/vendor/wreq/src/client/layer/decoder.rs +9 -4
  32. data/vendor/wreq/src/client/layer/redirect/future.rs +6 -3
  33. data/vendor/wreq/src/client/layer/redirect.rs +4 -5
  34. data/vendor/wreq/src/client/layer/retry.rs +8 -5
  35. data/vendor/wreq/src/client/layer/timeout/body.rs +15 -6
  36. data/vendor/wreq/src/client/layer/timeout/future.rs +23 -18
  37. data/vendor/wreq/src/client/layer/timeout.rs +24 -74
  38. data/vendor/wreq/src/client/layer.rs +1 -2
  39. data/vendor/wreq/src/client/multipart.rs +137 -154
  40. data/vendor/wreq/src/client/request.rs +202 -118
  41. data/vendor/wreq/src/client/response.rs +46 -45
  42. data/vendor/wreq/src/client/upgrade.rs +15 -0
  43. data/vendor/wreq/src/client/ws.rs +73 -25
  44. data/vendor/wreq/src/client.rs +1655 -17
  45. data/vendor/wreq/src/config.rs +11 -11
  46. data/vendor/wreq/src/{client/conn → conn}/connector.rs +139 -137
  47. data/vendor/wreq/src/conn/descriptor.rs +143 -0
  48. data/vendor/wreq/src/conn/http.rs +484 -0
  49. data/vendor/wreq/src/conn/net/io.rs +75 -0
  50. data/vendor/wreq/src/conn/net/tcp/compio.rs +71 -0
  51. data/vendor/wreq/src/conn/net/tcp/tokio.rs +57 -0
  52. data/vendor/wreq/src/conn/net/tcp.rs +561 -0
  53. data/vendor/wreq/src/conn/net/uds/compio.rs +60 -0
  54. data/vendor/wreq/src/{client/conn/uds.rs → conn/net/uds/tokio.rs} +18 -12
  55. data/vendor/wreq/src/conn/net/uds.rs +11 -0
  56. data/vendor/wreq/src/conn/net.rs +130 -0
  57. data/vendor/wreq/src/{client/conn → conn}/proxy/socks.rs +2 -9
  58. data/vendor/wreq/src/{client/conn → conn}/proxy/tunnel.rs +21 -56
  59. data/vendor/wreq/src/conn/tls_info.rs +47 -0
  60. data/vendor/wreq/src/{client/conn.rs → conn.rs} +202 -54
  61. data/vendor/wreq/src/cookie.rs +302 -142
  62. data/vendor/wreq/src/dns/gai/compio.rs +77 -0
  63. data/vendor/wreq/src/dns/gai/tokio.rs +90 -0
  64. data/vendor/wreq/src/dns/gai.rs +14 -164
  65. data/vendor/wreq/src/dns/hickory.rs +16 -23
  66. data/vendor/wreq/src/dns/resolve.rs +7 -41
  67. data/vendor/wreq/src/dns.rs +90 -7
  68. data/vendor/wreq/src/error.rs +57 -31
  69. data/vendor/wreq/src/ext.rs +25 -0
  70. data/vendor/wreq/src/group.rs +211 -0
  71. data/vendor/wreq/src/header.rs +100 -112
  72. data/vendor/wreq/src/lib.rs +124 -73
  73. data/vendor/wreq/src/proxy.rs +6 -20
  74. data/vendor/wreq/src/redirect.rs +1 -1
  75. data/vendor/wreq/src/rt.rs +208 -0
  76. data/vendor/wreq/src/sync.rs +97 -98
  77. data/vendor/wreq/src/tls/compress.rs +124 -0
  78. data/vendor/wreq/src/tls/conn/ext.rs +54 -45
  79. data/vendor/wreq/src/tls/conn/service.rs +14 -18
  80. data/vendor/wreq/src/tls/conn.rs +169 -241
  81. data/vendor/wreq/src/tls/keylog.rs +68 -5
  82. data/vendor/wreq/src/tls/session.rs +205 -0
  83. data/vendor/wreq/src/tls/{x509 → trust}/identity.rs +4 -21
  84. data/vendor/wreq/src/tls/{x509/parser.rs → trust/parse.rs} +1 -1
  85. data/vendor/wreq/src/tls/{x509 → trust}/store.rs +42 -81
  86. data/vendor/wreq/src/tls/{x509.rs → trust.rs} +8 -2
  87. data/vendor/wreq/src/tls.rs +489 -25
  88. data/vendor/wreq/src/trace.rs +0 -12
  89. data/vendor/wreq/src/util.rs +1 -1
  90. data/vendor/wreq/tests/badssl.rs +10 -10
  91. data/vendor/wreq/tests/client.rs +3 -9
  92. data/vendor/wreq/tests/cookie.rs +6 -8
  93. data/vendor/wreq/tests/{emulation.rs → emulate.rs} +130 -22
  94. data/vendor/wreq/tests/multipart.rs +43 -1
  95. data/vendor/wreq/tests/proxy.rs +1 -1
  96. data/vendor/wreq/tests/support/layer.rs +1 -0
  97. metadata +49 -71
  98. data/patches/0002-add-cancel-connections.patch +0 -181
  99. data/vendor/wreq/src/client/conn/conn.rs +0 -231
  100. data/vendor/wreq/src/client/conn/http.rs +0 -1023
  101. data/vendor/wreq/src/client/conn/tls_info.rs +0 -98
  102. data/vendor/wreq/src/client/core/body/incoming.rs +0 -485
  103. data/vendor/wreq/src/client/core/body/length.rs +0 -118
  104. data/vendor/wreq/src/client/core/body.rs +0 -34
  105. data/vendor/wreq/src/client/core/common/buf.rs +0 -149
  106. data/vendor/wreq/src/client/core/common/rewind.rs +0 -141
  107. data/vendor/wreq/src/client/core/common/watch.rs +0 -76
  108. data/vendor/wreq/src/client/core/common.rs +0 -3
  109. data/vendor/wreq/src/client/core/conn/http1.rs +0 -342
  110. data/vendor/wreq/src/client/core/conn/http2.rs +0 -307
  111. data/vendor/wreq/src/client/core/conn.rs +0 -11
  112. data/vendor/wreq/src/client/core/dispatch.rs +0 -299
  113. data/vendor/wreq/src/client/core/error.rs +0 -435
  114. data/vendor/wreq/src/client/core/ext.rs +0 -201
  115. data/vendor/wreq/src/client/core/http1.rs +0 -178
  116. data/vendor/wreq/src/client/core/http2.rs +0 -483
  117. data/vendor/wreq/src/client/core/proto/h1/conn.rs +0 -988
  118. data/vendor/wreq/src/client/core/proto/h1/decode.rs +0 -1170
  119. data/vendor/wreq/src/client/core/proto/h1/dispatch.rs +0 -684
  120. data/vendor/wreq/src/client/core/proto/h1/encode.rs +0 -580
  121. data/vendor/wreq/src/client/core/proto/h1/io.rs +0 -879
  122. data/vendor/wreq/src/client/core/proto/h1/role.rs +0 -694
  123. data/vendor/wreq/src/client/core/proto/h1.rs +0 -104
  124. data/vendor/wreq/src/client/core/proto/h2/client.rs +0 -650
  125. data/vendor/wreq/src/client/core/proto/h2/ping.rs +0 -539
  126. data/vendor/wreq/src/client/core/proto/h2.rs +0 -379
  127. data/vendor/wreq/src/client/core/proto/headers.rs +0 -138
  128. data/vendor/wreq/src/client/core/proto.rs +0 -58
  129. data/vendor/wreq/src/client/core/rt/bounds.rs +0 -57
  130. data/vendor/wreq/src/client/core/rt/timer.rs +0 -150
  131. data/vendor/wreq/src/client/core/rt/tokio.rs +0 -99
  132. data/vendor/wreq/src/client/core/rt.rs +0 -25
  133. data/vendor/wreq/src/client/core/upgrade.rs +0 -267
  134. data/vendor/wreq/src/client/core.rs +0 -16
  135. data/vendor/wreq/src/client/emulation.rs +0 -161
  136. data/vendor/wreq/src/client/http/client/error.rs +0 -142
  137. data/vendor/wreq/src/client/http/client/exec.rs +0 -29
  138. data/vendor/wreq/src/client/http/client/extra.rs +0 -77
  139. data/vendor/wreq/src/client/http/client/util.rs +0 -104
  140. data/vendor/wreq/src/client/http.rs +0 -1629
  141. data/vendor/wreq/src/client/layer/config/options.rs +0 -156
  142. data/vendor/wreq/src/client/layer/cookie.rs +0 -161
  143. data/vendor/wreq/src/hash.rs +0 -143
  144. data/vendor/wreq/src/tls/conn/cache.rs +0 -123
  145. data/vendor/wreq/src/tls/conn/cert_compression.rs +0 -125
  146. data/vendor/wreq/src/tls/keylog/handle.rs +0 -64
  147. data/vendor/wreq/src/tls/options.rs +0 -464
  148. /data/vendor/wreq/src/client/{http → layer}/client/lazy.rs +0 -0
  149. /data/vendor/wreq/src/{client/conn → conn}/proxy.rs +0 -0
  150. /data/vendor/wreq/src/{client/conn → conn}/verbose.rs +0 -0
@@ -1,156 +0,0 @@
1
- use http::Version;
2
-
3
- use crate::{
4
- client::{
5
- conn::TcpConnectOptions,
6
- core::{http1::Http1Options, http2::Http2Options},
7
- },
8
- proxy::Matcher,
9
- tls::TlsOptions,
10
- };
11
-
12
- /// Per-request configuration for proxy, protocol, and transport options.
13
- /// Overrides client defaults for a single request.
14
- #[derive(Debug, Default, Clone, Hash, PartialEq, Eq)]
15
- #[non_exhaustive]
16
- pub struct RequestOptions {
17
- proxy_matcher: Option<Matcher>,
18
- enforced_version: Option<Version>,
19
- tcp_connect_opts: TcpConnectOptions,
20
- transport_opts: TransportOptions,
21
- }
22
-
23
- /// Transport options for HTTP/1, HTTP/2, and TLS layers.
24
- ///
25
- /// This struct allows you to customize protocol-specific and TLS settings
26
- /// for network connections made by the client.
27
- #[derive(Debug, Default, Clone, Hash, PartialEq, Eq)]
28
- #[non_exhaustive]
29
- pub struct TransportOptions {
30
- tls_options: Option<TlsOptions>,
31
- http1_options: Option<Http1Options>,
32
- http2_options: Option<Http2Options>,
33
- }
34
-
35
- // ===== impl RequestOptions =====
36
-
37
- impl_request_config_value!(RequestOptions);
38
-
39
- // ===== impl TransportOptions =====
40
-
41
- impl TransportOptions {
42
- /// Get the reference to the TLS options.
43
- #[inline]
44
- pub fn tls_options(&self) -> Option<&TlsOptions> {
45
- self.tls_options.as_ref()
46
- }
47
-
48
- /// Get a mutable reference to the TLS options.
49
- #[inline]
50
- pub fn tls_options_mut(&mut self) -> &mut Option<TlsOptions> {
51
- &mut self.tls_options
52
- }
53
-
54
- /// Get the reference to the HTTP/1 options.
55
- #[inline]
56
- pub fn http1_options(&self) -> Option<&Http1Options> {
57
- self.http1_options.as_ref()
58
- }
59
-
60
- /// Get a mutable reference to the HTTP/1 options.
61
- #[inline]
62
- pub fn http1_options_mut(&mut self) -> &mut Option<Http1Options> {
63
- &mut self.http1_options
64
- }
65
-
66
- /// Get the reference to the HTTP/2 options.
67
- #[inline]
68
- pub fn http2_options(&self) -> Option<&Http2Options> {
69
- self.http2_options.as_ref()
70
- }
71
-
72
- /// Get a mutable reference to the HTTP/2 options.
73
- #[inline]
74
- pub fn http2_options_mut(&mut self) -> &mut Option<Http2Options> {
75
- &mut self.http2_options
76
- }
77
-
78
- /// Apply the transport options for HTTP/1, HTTP/2, and TLS.
79
- pub(crate) fn apply_transport_options(&mut self, opts: TransportOptions) -> &mut Self {
80
- if let Some(tls) = opts.tls_options {
81
- *self.tls_options_mut() = Some(tls);
82
- }
83
- if let Some(http1) = opts.http1_options {
84
- *self.http1_options_mut() = Some(http1);
85
- }
86
- if let Some(http2) = opts.http2_options {
87
- *self.http2_options_mut() = Some(http2);
88
- }
89
- self
90
- }
91
- }
92
-
93
- impl From<TransportOptions>
94
- for (
95
- Option<TlsOptions>,
96
- Option<Http1Options>,
97
- Option<Http2Options>,
98
- )
99
- {
100
- #[inline]
101
- fn from(value: TransportOptions) -> Self {
102
- (value.tls_options, value.http1_options, value.http2_options)
103
- }
104
- }
105
-
106
- // ===== impl RequestOptions =====
107
-
108
- impl RequestOptions {
109
- /// Get a reference to the proxy matcher.
110
- #[inline]
111
- pub fn proxy_matcher(&self) -> Option<&Matcher> {
112
- self.proxy_matcher.as_ref()
113
- }
114
-
115
- /// Get a mutable reference to the proxy matcher.
116
- #[inline]
117
- pub fn proxy_matcher_mut(&mut self) -> &mut Option<Matcher> {
118
- &mut self.proxy_matcher
119
- }
120
-
121
- /// Get the enforced HTTP version.
122
- #[inline]
123
- pub fn enforced_version(&self) -> Option<Version> {
124
- self.enforced_version
125
- }
126
-
127
- /// Get a mutable reference to the enforced HTTP version.
128
- #[inline]
129
- pub fn enforced_version_mut(&mut self) -> &mut Option<Version> {
130
- &mut self.enforced_version
131
- }
132
-
133
- /// Get a reference to the TCP connection options.
134
- #[inline]
135
- pub fn tcp_connect_opts(&self) -> &TcpConnectOptions {
136
- &self.tcp_connect_opts
137
- }
138
-
139
- /// Get a mutable reference to the TCP connection options.
140
- #[inline]
141
- pub fn tcp_connect_opts_mut(&mut self) -> &mut TcpConnectOptions {
142
- &mut self.tcp_connect_opts
143
- }
144
-
145
- /// Get a reference to the transport options.
146
- #[inline]
147
- pub fn transport_opts(&self) -> &TransportOptions {
148
- &self.transport_opts
149
- }
150
-
151
- /// Get a mutable reference to the transport options.
152
- #[inline]
153
- pub fn transport_opts_mut(&mut self) -> &mut TransportOptions {
154
- &mut self.transport_opts
155
- }
156
- }
@@ -1,161 +0,0 @@
1
- //! Middleware to use Cookie.
2
-
3
- use std::{
4
- future::Future,
5
- pin::Pin,
6
- sync::Arc,
7
- task::{Context, Poll, ready},
8
- };
9
-
10
- use http::{Request, Response, Uri, header::COOKIE};
11
- use pin_project_lite::pin_project;
12
- use tower::{Layer, Service};
13
-
14
- use crate::{
15
- config::RequestConfig,
16
- cookie::{CookieStore, Cookies},
17
- };
18
-
19
- pin_project! {
20
- /// Response future for [`CookieService`].
21
- #[project = ResponseFutureProj]
22
- pub enum ResponseFuture<Fut> {
23
- Managed {
24
- #[pin]
25
- fut: Fut,
26
- uri: Uri,
27
- store: Arc<dyn CookieStore>,
28
- },
29
- Plain {
30
- #[pin]
31
- fut: Fut,
32
- },
33
- }
34
- }
35
-
36
- /// Layer to apply [`CookieService`] middleware.
37
- #[derive(Clone)]
38
- pub struct CookieServiceLayer {
39
- store: RequestConfig<Arc<dyn CookieStore>>,
40
- }
41
-
42
- /// Middleware to use [`CookieStore`].
43
- #[derive(Clone)]
44
- pub struct CookieService<S> {
45
- inner: S,
46
- store: RequestConfig<Arc<dyn CookieStore>>,
47
- }
48
-
49
- // ===== impl ResponseFuture =====
50
-
51
- impl<F, ResBody, E> Future for ResponseFuture<F>
52
- where
53
- F: Future<Output = Result<Response<ResBody>, E>>,
54
- {
55
- type Output = F::Output;
56
-
57
- fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
58
- match self.project() {
59
- ResponseFutureProj::Managed { fut, uri, store } => {
60
- let res = ready!(fut.poll(cx)?);
61
- let mut cookies = res
62
- .headers()
63
- .get_all(http::header::SET_COOKIE)
64
- .iter()
65
- .peekable();
66
- if cookies.peek().is_some() {
67
- store.set_cookies(&mut cookies, uri);
68
- }
69
-
70
- Poll::Ready(Ok(res))
71
- }
72
- ResponseFutureProj::Plain { fut: mut future } => future.as_mut().poll(cx),
73
- }
74
- }
75
- }
76
-
77
- // ===== impl CookieServiceLayer =====
78
-
79
- impl CookieServiceLayer {
80
- /// Create a new [`CookieServiceLayer`].
81
- #[inline(always)]
82
- pub const fn new(store: Option<Arc<dyn CookieStore + 'static>>) -> Self {
83
- Self {
84
- store: RequestConfig::new(store),
85
- }
86
- }
87
- }
88
-
89
- impl<S> Layer<S> for CookieServiceLayer {
90
- type Service = CookieService<S>;
91
-
92
- #[inline(always)]
93
- fn layer(&self, inner: S) -> Self::Service {
94
- CookieService {
95
- inner,
96
- store: self.store.clone(),
97
- }
98
- }
99
- }
100
-
101
- // ===== impl CookieService =====
102
-
103
- impl<S> CookieService<S> {
104
- fn inject_cookies<B>(
105
- &self,
106
- req: &mut Request<B>,
107
- store: Arc<dyn CookieStore>,
108
- ) -> (Arc<dyn CookieStore>, Uri) {
109
- let uri = req.uri().clone();
110
- let headers = req.headers_mut();
111
-
112
- // Only inject cookies if request doesn't already have them
113
- if !headers.contains_key(COOKIE) {
114
- match store.cookies(&uri) {
115
- Cookies::Compressed(value) => {
116
- headers.insert(COOKIE, value);
117
- }
118
- Cookies::Uncompressed(values) => {
119
- for value in values {
120
- headers.append(COOKIE, value);
121
- }
122
- }
123
- Cookies::Empty => (),
124
- }
125
- }
126
-
127
- (store, uri)
128
- }
129
- }
130
-
131
- impl<ReqBody, ResBody, S> Service<Request<ReqBody>> for CookieService<S>
132
- where
133
- S: Service<Request<ReqBody>, Response = Response<ResBody>>,
134
- {
135
- type Response = S::Response;
136
- type Error = S::Error;
137
- type Future = ResponseFuture<S::Future>;
138
-
139
- #[inline(always)]
140
- fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
141
- self.inner.poll_ready(cx)
142
- }
143
-
144
- fn call(&mut self, mut req: Request<ReqBody>) -> Self::Future {
145
- match self
146
- .store
147
- .fetch(req.extensions())
148
- .cloned()
149
- .map(|store| self.inject_cookies(&mut req, store))
150
- {
151
- Some((store, uri)) => ResponseFuture::Managed {
152
- uri,
153
- store,
154
- fut: self.inner.call(req),
155
- },
156
- None => ResponseFuture::Plain {
157
- fut: self.inner.call(req),
158
- },
159
- }
160
- }
161
- }
@@ -1,143 +0,0 @@
1
- use std::{
2
- borrow::Borrow,
3
- hash::{BuildHasher, Hash, Hasher},
4
- num::NonZeroU64,
5
- sync::atomic::{AtomicU64, Ordering},
6
- };
7
-
8
- use ahash::RandomState;
9
- use schnellru::ByLength;
10
-
11
- /// Pre-seeded [`RandomState`] for consistent internal hashing.
12
- ///
13
- /// Uses fixed seeds to ensure deterministic hashing behavior across
14
- /// program runs. Primarily used for connection pools and internal caches.
15
- ///
16
- /// **Note**: Not cryptographically secure due to fixed seeds.
17
- pub const HASHER: RandomState = RandomState::with_seeds(
18
- 0x6b68_d618_a4b5_3c57,
19
- 0xadc8_c4d5_82bb_1313,
20
- 0x2f72_c2c1_9b04_2d4c,
21
- 0x94e5_8d83_a26c_3f28,
22
- );
23
-
24
- /// A type alias for a hash set using `ahash` with a pre-seeded `RandomState`.
25
- pub type HashSet<T> = std::collections::HashSet<T, RandomState>;
26
-
27
- /// A type alias for a hash map using `ahash` with a pre-seeded `RandomState`.
28
- pub type HashMap<K, V> = std::collections::HashMap<K, V, RandomState>;
29
-
30
- /// A specialized LRU cache using `schnellru` with a fixed capacity
31
- pub type LruMap<K, V> = schnellru::LruMap<K, V, ByLength, RandomState>;
32
-
33
- /// A wrapper that memoizes the hash value of its contained data.
34
- #[derive(Debug)]
35
- pub struct HashMemo<T, H: BuildHasher = RandomState>
36
- where
37
- T: Eq + PartialEq + Hash,
38
- {
39
- value: T,
40
- hash: AtomicU64,
41
- hasher: H,
42
- }
43
-
44
- impl<T, H> HashMemo<T, H>
45
- where
46
- T: Eq + Hash,
47
- H: BuildHasher,
48
- {
49
- /// Creates a new `HashMemo` with a custom hasher.
50
- ///
51
- /// This allows you to specify a custom `BuildHasher` implementation for
52
- /// controlling how hash values are computed.
53
- pub const fn with_hasher(value: T, hasher: H) -> Self {
54
- Self {
55
- value,
56
- hash: AtomicU64::new(u64::MIN),
57
- hasher,
58
- }
59
- }
60
- }
61
-
62
- impl<T, H> Hash for HashMemo<T, H>
63
- where
64
- T: Eq + Hash,
65
- H: BuildHasher,
66
- {
67
- fn hash<H2: Hasher>(&self, state: &mut H2) {
68
- let hash = self.hash.load(Ordering::Relaxed);
69
- if hash != 0 {
70
- state.write_u64(hash);
71
- return;
72
- }
73
-
74
- let computed_hash = NonZeroU64::new(self.hasher.hash_one(&self.value))
75
- .map(NonZeroU64::get)
76
- .unwrap_or(1);
77
-
78
- let _ = self.hash.compare_exchange(
79
- u64::MIN,
80
- computed_hash,
81
- Ordering::Relaxed,
82
- Ordering::Relaxed,
83
- );
84
- state.write_u64(computed_hash);
85
- }
86
- }
87
-
88
- impl<T, H> PartialOrd for HashMemo<T, H>
89
- where
90
- T: Eq + Hash + PartialOrd,
91
- H: BuildHasher,
92
- {
93
- fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
94
- self.value.partial_cmp(&other.value)
95
- }
96
- }
97
-
98
- impl<T, H> Ord for HashMemo<T, H>
99
- where
100
- T: Eq + Hash + Ord,
101
- H: BuildHasher,
102
- {
103
- fn cmp(&self, other: &Self) -> std::cmp::Ordering {
104
- self.value.cmp(&other.value)
105
- }
106
- }
107
-
108
- impl<T, H> PartialEq for HashMemo<T, H>
109
- where
110
- T: Eq + Hash,
111
- H: BuildHasher,
112
- {
113
- fn eq(&self, other: &Self) -> bool {
114
- self.value == other.value
115
- }
116
- }
117
-
118
- impl<T, H> Eq for HashMemo<T, H>
119
- where
120
- T: Eq + Hash,
121
- H: BuildHasher,
122
- {
123
- }
124
-
125
- impl<T, H> AsRef<T> for HashMemo<T, H>
126
- where
127
- T: Eq + Hash,
128
- H: BuildHasher,
129
- {
130
- fn as_ref(&self) -> &T {
131
- &self.value
132
- }
133
- }
134
-
135
- impl<T, H> Borrow<T> for HashMemo<T, H>
136
- where
137
- T: Eq + Hash,
138
- H: BuildHasher,
139
- {
140
- fn borrow(&self) -> &T {
141
- &self.value
142
- }
143
- }
@@ -1,123 +0,0 @@
1
- use std::{
2
- borrow::Borrow,
3
- collections::hash_map::Entry,
4
- hash::{Hash, Hasher},
5
- };
6
-
7
- use boring2::ssl::{SslSession, SslSessionRef, SslVersion};
8
- use schnellru::ByLength;
9
-
10
- use crate::hash::{HASHER, HashMap, LruMap};
11
-
12
- /// A typed key for indexing TLS sessions in the cache.
13
- ///
14
- /// This wrapper provides type safety and allows different key types
15
- /// (e.g., hostname, connection parameters) to be used for session lookup.
16
- #[derive(Hash, PartialEq, Eq, Clone)]
17
- pub struct SessionKey<T>(pub T);
18
-
19
- /// A hashable wrapper around `SslSession` for use in hash-based collections.
20
- ///
21
- /// Uses the session ID for hashing and equality, enabling efficient
22
- /// storage and lookup in HashMap/HashSet while maintaining session semantics.
23
- #[derive(Clone)]
24
- struct HashSession(SslSession);
25
-
26
- impl PartialEq for HashSession {
27
- fn eq(&self, other: &HashSession) -> bool {
28
- self.0.id() == other.0.id()
29
- }
30
- }
31
-
32
- impl Eq for HashSession {}
33
-
34
- impl Hash for HashSession {
35
- fn hash<H>(&self, state: &mut H)
36
- where
37
- H: Hasher,
38
- {
39
- self.0.id().hash(state);
40
- }
41
- }
42
-
43
- impl Borrow<[u8]> for HashSession {
44
- fn borrow(&self) -> &[u8] {
45
- self.0.id()
46
- }
47
- }
48
-
49
- /// A two-level cache for TLS sessions organized by host keys with LRU eviction.
50
- ///
51
- /// Maintains both forward (key → sessions) and reverse (session → key) lookups
52
- /// for efficient session storage, retrieval, and cleanup operations.
53
- pub struct SessionCache<T> {
54
- reverse: HashMap<HashSession, SessionKey<T>>,
55
- per_host_sessions: HashMap<SessionKey<T>, LruMap<HashSession, ()>>,
56
- per_host_session_capacity: usize,
57
- }
58
-
59
- impl<T> SessionCache<T>
60
- where
61
- T: Hash + Eq + Clone,
62
- {
63
- pub fn with_capacity(per_host_session_capacity: usize) -> SessionCache<T> {
64
- SessionCache {
65
- per_host_sessions: HashMap::with_hasher(HASHER),
66
- reverse: HashMap::with_hasher(HASHER),
67
- per_host_session_capacity,
68
- }
69
- }
70
-
71
- pub fn insert(&mut self, key: SessionKey<T>, session: SslSession) {
72
- let per_host_sessions = self
73
- .per_host_sessions
74
- .entry(key.clone())
75
- .or_insert_with(|| {
76
- LruMap::with_hasher(ByLength::new(self.per_host_session_capacity as _), HASHER)
77
- });
78
-
79
- // Enforce per-key capacity limit by evicting the least recently used session
80
- if per_host_sessions.len() >= self.per_host_session_capacity {
81
- if let Some((evicted_session, _)) = per_host_sessions.pop_oldest() {
82
- // Remove from reverse lookup to maintain consistency
83
- self.reverse.remove(&evicted_session);
84
- }
85
- }
86
-
87
- let session = HashSession(session);
88
- per_host_sessions.insert(session.clone(), ());
89
- self.reverse.insert(session, key);
90
- }
91
-
92
- pub fn get(&mut self, key: &SessionKey<T>) -> Option<SslSession> {
93
- let session = {
94
- let per_host_sessions = self.per_host_sessions.get_mut(key)?;
95
- per_host_sessions.peek_oldest()?.0.clone().0
96
- };
97
-
98
- // https://tools.ietf.org/html/rfc8446#appendix-C.4
99
- // OpenSSL will remove the session from its cache after the handshake completes anyway, but
100
- // this ensures that concurrent handshakes don't end up with the same session.
101
- if session.protocol_version() == SslVersion::TLS1_3 {
102
- self.remove(&session);
103
- }
104
-
105
- Some(session)
106
- }
107
-
108
- fn remove(&mut self, session: &SslSessionRef) {
109
- let key = match self.reverse.remove(session.id()) {
110
- Some(key) => key,
111
- None => return,
112
- };
113
-
114
- if let Entry::Occupied(mut per_host_sessions) = self.per_host_sessions.entry(key) {
115
- per_host_sessions
116
- .get_mut()
117
- .remove(&HashSession(session.to_owned()));
118
- if per_host_sessions.get().is_empty() {
119
- per_host_sessions.remove();
120
- }
121
- }
122
- }
123
- }
@@ -1,125 +0,0 @@
1
- use std::io::{self, Read, Result, Write};
2
-
3
- use boring2::ssl::{CertificateCompressionAlgorithm, CertificateCompressor};
4
- use brotli::{CompressorWriter, Decompressor};
5
- use flate2::{Compression, read::ZlibDecoder, write::ZlibEncoder};
6
- use zstd::stream::{Decoder as ZstdDecoder, Encoder as ZstdEncoder};
7
-
8
- #[derive(Debug, Clone, Default)]
9
- #[non_exhaustive]
10
- pub struct BrotliCertificateCompressor;
11
-
12
- impl CertificateCompressor for BrotliCertificateCompressor {
13
- const ALGORITHM: CertificateCompressionAlgorithm = CertificateCompressionAlgorithm::BROTLI;
14
- const CAN_COMPRESS: bool = true;
15
- const CAN_DECOMPRESS: bool = true;
16
-
17
- fn compress<W>(&self, input: &[u8], output: &mut W) -> Result<()>
18
- where
19
- W: Write,
20
- {
21
- let mut writer = CompressorWriter::new(output, input.len(), 11, 22);
22
- writer.write_all(input)?;
23
- writer.flush()?;
24
- Ok(())
25
- }
26
-
27
- fn decompress<W>(&self, input: &[u8], output: &mut W) -> Result<()>
28
- where
29
- W: Write,
30
- {
31
- let mut reader = Decompressor::new(input, 4096);
32
- let mut buf = [0u8; 4096];
33
- loop {
34
- match reader.read(&mut buf[..]) {
35
- Err(e) => {
36
- if let io::ErrorKind::Interrupted = e.kind() {
37
- continue;
38
- }
39
- return Err(e);
40
- }
41
- Ok(size) => {
42
- if size == 0 {
43
- break;
44
- }
45
- output.write_all(&buf[..size])?;
46
- }
47
- }
48
- }
49
- Ok(())
50
- }
51
- }
52
-
53
- #[derive(Debug, Clone, Default)]
54
- #[non_exhaustive]
55
- pub struct ZlibCertificateCompressor;
56
-
57
- impl CertificateCompressor for ZlibCertificateCompressor {
58
- const ALGORITHM: CertificateCompressionAlgorithm = CertificateCompressionAlgorithm::ZLIB;
59
- const CAN_COMPRESS: bool = true;
60
- const CAN_DECOMPRESS: bool = true;
61
-
62
- fn compress<W>(&self, input: &[u8], output: &mut W) -> Result<()>
63
- where
64
- W: Write,
65
- {
66
- let mut encoder = ZlibEncoder::new(output, Compression::default());
67
- encoder.write_all(input)?;
68
- encoder.finish()?;
69
- Ok(())
70
- }
71
-
72
- fn decompress<W>(&self, input: &[u8], output: &mut W) -> Result<()>
73
- where
74
- W: Write,
75
- {
76
- let mut decoder = ZlibDecoder::new(input);
77
- io::copy(&mut decoder, output)?;
78
- Ok(())
79
- }
80
- }
81
-
82
- #[derive(Debug, Clone, Default)]
83
- #[non_exhaustive]
84
- pub struct ZstdCertificateCompressor;
85
-
86
- impl CertificateCompressor for ZstdCertificateCompressor {
87
- const ALGORITHM: CertificateCompressionAlgorithm = CertificateCompressionAlgorithm::ZSTD;
88
- const CAN_COMPRESS: bool = true;
89
- const CAN_DECOMPRESS: bool = true;
90
-
91
- fn compress<W>(&self, input: &[u8], output: &mut W) -> Result<()>
92
- where
93
- W: Write,
94
- {
95
- let mut writer = ZstdEncoder::new(output, 0)?;
96
- writer.write_all(input)?;
97
- writer.flush()?;
98
- Ok(())
99
- }
100
-
101
- fn decompress<W>(&self, input: &[u8], output: &mut W) -> Result<()>
102
- where
103
- W: Write,
104
- {
105
- let mut reader = ZstdDecoder::new(input)?;
106
- let mut buf = [0u8; 4096];
107
- loop {
108
- match reader.read(&mut buf[..]) {
109
- Err(e) => {
110
- if let io::ErrorKind::Interrupted = e.kind() {
111
- continue;
112
- }
113
- return Err(e);
114
- }
115
- Ok(size) => {
116
- if size == 0 {
117
- break;
118
- }
119
- output.write_all(&buf[..size])?;
120
- }
121
- }
122
- }
123
- Ok(())
124
- }
125
- }