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.
- checksums.yaml +4 -4
- data/Cargo.lock +1922 -397
- data/LICENSE +203 -0
- data/README.md +19 -15
- data/ext/wreq_rb/Cargo.toml +4 -6
- data/ext/wreq_rb/src/client.rs +41 -48
- data/lib/wreq-rb/version.rb +1 -1
- data/patches/0001-add-transfer-size-tracking.patch +76 -67
- data/vendor/wreq/Cargo.toml +119 -71
- data/vendor/wreq/README.md +25 -20
- data/vendor/wreq/bench/http1.rs +25 -0
- data/vendor/wreq/bench/http1_over_tls.rs +25 -0
- data/vendor/wreq/bench/http2.rs +25 -0
- data/vendor/wreq/bench/http2_over_tls.rs +25 -0
- data/vendor/wreq/bench/support/bench.rs +91 -0
- data/vendor/wreq/bench/support/client.rs +217 -0
- data/vendor/wreq/bench/support/server.rs +188 -0
- data/vendor/wreq/bench/support.rs +56 -0
- data/vendor/wreq/examples/cert_store.rs +4 -4
- data/vendor/wreq/examples/{emulation.rs → emulate.rs} +2 -2
- data/vendor/wreq/examples/http2_websocket.rs +2 -2
- data/vendor/wreq/examples/keylog.rs +3 -3
- data/vendor/wreq/examples/{request_with_emulation.rs → request_with_emulate.rs} +2 -2
- data/vendor/wreq/examples/rt.rs +23 -0
- data/vendor/wreq/src/client/body.rs +23 -61
- data/vendor/wreq/src/client/emulate.rs +119 -0
- data/vendor/wreq/src/client/{http/future.rs → future.rs} +11 -32
- data/vendor/wreq/src/client/{http → layer}/client/pool.rs +66 -61
- data/vendor/wreq/src/client/{http → layer}/client.rs +416 -270
- data/vendor/wreq/src/client/layer/config.rs +27 -6
- data/vendor/wreq/src/client/layer/decoder.rs +9 -4
- data/vendor/wreq/src/client/layer/redirect/future.rs +6 -3
- data/vendor/wreq/src/client/layer/redirect.rs +4 -5
- data/vendor/wreq/src/client/layer/retry.rs +8 -5
- data/vendor/wreq/src/client/layer/timeout/body.rs +15 -6
- data/vendor/wreq/src/client/layer/timeout/future.rs +23 -18
- data/vendor/wreq/src/client/layer/timeout.rs +24 -74
- data/vendor/wreq/src/client/layer.rs +1 -2
- data/vendor/wreq/src/client/multipart.rs +137 -154
- data/vendor/wreq/src/client/request.rs +202 -118
- data/vendor/wreq/src/client/response.rs +46 -45
- data/vendor/wreq/src/client/upgrade.rs +15 -0
- data/vendor/wreq/src/client/ws.rs +73 -25
- data/vendor/wreq/src/client.rs +1655 -17
- data/vendor/wreq/src/config.rs +11 -11
- data/vendor/wreq/src/{client/conn → conn}/connector.rs +139 -137
- data/vendor/wreq/src/conn/descriptor.rs +143 -0
- data/vendor/wreq/src/conn/http.rs +484 -0
- data/vendor/wreq/src/conn/net/io.rs +75 -0
- data/vendor/wreq/src/conn/net/tcp/compio.rs +71 -0
- data/vendor/wreq/src/conn/net/tcp/tokio.rs +57 -0
- data/vendor/wreq/src/conn/net/tcp.rs +561 -0
- data/vendor/wreq/src/conn/net/uds/compio.rs +60 -0
- data/vendor/wreq/src/{client/conn/uds.rs → conn/net/uds/tokio.rs} +18 -12
- data/vendor/wreq/src/conn/net/uds.rs +11 -0
- data/vendor/wreq/src/conn/net.rs +130 -0
- data/vendor/wreq/src/{client/conn → conn}/proxy/socks.rs +2 -9
- data/vendor/wreq/src/{client/conn → conn}/proxy/tunnel.rs +21 -56
- data/vendor/wreq/src/conn/tls_info.rs +47 -0
- data/vendor/wreq/src/{client/conn.rs → conn.rs} +202 -54
- data/vendor/wreq/src/cookie.rs +302 -142
- data/vendor/wreq/src/dns/gai/compio.rs +77 -0
- data/vendor/wreq/src/dns/gai/tokio.rs +90 -0
- data/vendor/wreq/src/dns/gai.rs +14 -164
- data/vendor/wreq/src/dns/hickory.rs +16 -23
- data/vendor/wreq/src/dns/resolve.rs +7 -41
- data/vendor/wreq/src/dns.rs +90 -7
- data/vendor/wreq/src/error.rs +57 -31
- data/vendor/wreq/src/ext.rs +25 -0
- data/vendor/wreq/src/group.rs +211 -0
- data/vendor/wreq/src/header.rs +100 -112
- data/vendor/wreq/src/lib.rs +124 -73
- data/vendor/wreq/src/proxy.rs +6 -20
- data/vendor/wreq/src/redirect.rs +1 -1
- data/vendor/wreq/src/rt.rs +208 -0
- data/vendor/wreq/src/sync.rs +97 -98
- data/vendor/wreq/src/tls/compress.rs +124 -0
- data/vendor/wreq/src/tls/conn/ext.rs +54 -45
- data/vendor/wreq/src/tls/conn/service.rs +14 -18
- data/vendor/wreq/src/tls/conn.rs +169 -241
- data/vendor/wreq/src/tls/keylog.rs +68 -5
- data/vendor/wreq/src/tls/session.rs +205 -0
- data/vendor/wreq/src/tls/{x509 → trust}/identity.rs +4 -21
- data/vendor/wreq/src/tls/{x509/parser.rs → trust/parse.rs} +1 -1
- data/vendor/wreq/src/tls/{x509 → trust}/store.rs +42 -81
- data/vendor/wreq/src/tls/{x509.rs → trust.rs} +8 -2
- data/vendor/wreq/src/tls.rs +489 -25
- data/vendor/wreq/src/trace.rs +0 -12
- data/vendor/wreq/src/util.rs +1 -1
- data/vendor/wreq/tests/badssl.rs +10 -10
- data/vendor/wreq/tests/client.rs +3 -9
- data/vendor/wreq/tests/cookie.rs +6 -8
- data/vendor/wreq/tests/{emulation.rs → emulate.rs} +130 -22
- data/vendor/wreq/tests/multipart.rs +43 -1
- data/vendor/wreq/tests/proxy.rs +1 -1
- data/vendor/wreq/tests/support/layer.rs +1 -0
- metadata +49 -71
- data/patches/0002-add-cancel-connections.patch +0 -181
- data/vendor/wreq/src/client/conn/conn.rs +0 -231
- data/vendor/wreq/src/client/conn/http.rs +0 -1023
- data/vendor/wreq/src/client/conn/tls_info.rs +0 -98
- data/vendor/wreq/src/client/core/body/incoming.rs +0 -485
- data/vendor/wreq/src/client/core/body/length.rs +0 -118
- data/vendor/wreq/src/client/core/body.rs +0 -34
- data/vendor/wreq/src/client/core/common/buf.rs +0 -149
- data/vendor/wreq/src/client/core/common/rewind.rs +0 -141
- data/vendor/wreq/src/client/core/common/watch.rs +0 -76
- data/vendor/wreq/src/client/core/common.rs +0 -3
- data/vendor/wreq/src/client/core/conn/http1.rs +0 -342
- data/vendor/wreq/src/client/core/conn/http2.rs +0 -307
- data/vendor/wreq/src/client/core/conn.rs +0 -11
- data/vendor/wreq/src/client/core/dispatch.rs +0 -299
- data/vendor/wreq/src/client/core/error.rs +0 -435
- data/vendor/wreq/src/client/core/ext.rs +0 -201
- data/vendor/wreq/src/client/core/http1.rs +0 -178
- data/vendor/wreq/src/client/core/http2.rs +0 -483
- data/vendor/wreq/src/client/core/proto/h1/conn.rs +0 -988
- data/vendor/wreq/src/client/core/proto/h1/decode.rs +0 -1170
- data/vendor/wreq/src/client/core/proto/h1/dispatch.rs +0 -684
- data/vendor/wreq/src/client/core/proto/h1/encode.rs +0 -580
- data/vendor/wreq/src/client/core/proto/h1/io.rs +0 -879
- data/vendor/wreq/src/client/core/proto/h1/role.rs +0 -694
- data/vendor/wreq/src/client/core/proto/h1.rs +0 -104
- data/vendor/wreq/src/client/core/proto/h2/client.rs +0 -650
- data/vendor/wreq/src/client/core/proto/h2/ping.rs +0 -539
- data/vendor/wreq/src/client/core/proto/h2.rs +0 -379
- data/vendor/wreq/src/client/core/proto/headers.rs +0 -138
- data/vendor/wreq/src/client/core/proto.rs +0 -58
- data/vendor/wreq/src/client/core/rt/bounds.rs +0 -57
- data/vendor/wreq/src/client/core/rt/timer.rs +0 -150
- data/vendor/wreq/src/client/core/rt/tokio.rs +0 -99
- data/vendor/wreq/src/client/core/rt.rs +0 -25
- data/vendor/wreq/src/client/core/upgrade.rs +0 -267
- data/vendor/wreq/src/client/core.rs +0 -16
- data/vendor/wreq/src/client/emulation.rs +0 -161
- data/vendor/wreq/src/client/http/client/error.rs +0 -142
- data/vendor/wreq/src/client/http/client/exec.rs +0 -29
- data/vendor/wreq/src/client/http/client/extra.rs +0 -77
- data/vendor/wreq/src/client/http/client/util.rs +0 -104
- data/vendor/wreq/src/client/http.rs +0 -1629
- data/vendor/wreq/src/client/layer/config/options.rs +0 -156
- data/vendor/wreq/src/client/layer/cookie.rs +0 -161
- data/vendor/wreq/src/hash.rs +0 -143
- data/vendor/wreq/src/tls/conn/cache.rs +0 -123
- data/vendor/wreq/src/tls/conn/cert_compression.rs +0 -125
- data/vendor/wreq/src/tls/keylog/handle.rs +0 -64
- data/vendor/wreq/src/tls/options.rs +0 -464
- /data/vendor/wreq/src/client/{http → layer}/client/lazy.rs +0 -0
- /data/vendor/wreq/src/{client/conn → conn}/proxy.rs +0 -0
- /data/vendor/wreq/src/{client/conn → conn}/verbose.rs +0 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
//! Runtime components — executor and timer abstractions.
|
|
2
|
+
//!
|
|
3
|
+
//! This module provides [`Executor`] and [`Timer`], the two runtime primitives
|
|
4
|
+
//! used by the HTTP client for spawning background tasks and driving timeouts.
|
|
5
|
+
//!
|
|
6
|
+
//! # Feature flags
|
|
7
|
+
//!
|
|
8
|
+
//! At least one of the following features must be enabled:
|
|
9
|
+
//!
|
|
10
|
+
//! - `tokio-rt` — uses [tokio] as the underlying runtime (default).
|
|
11
|
+
//! - `compio-rt` — uses [compio] as the underlying runtime.
|
|
12
|
+
//!
|
|
13
|
+
//! When both are enabled, `tokio-rt` takes precedence for both [`Executor`]
|
|
14
|
+
//! and [`Timer`]. When neither is enabled, [`Executor::default`] and
|
|
15
|
+
//! [`Timer::default`] return empty placeholders that panic on use, so a
|
|
16
|
+
//! runtime feature flag **must** be active in practice.
|
|
17
|
+
//!
|
|
18
|
+
//! [tokio]: https://docs.rs/tokio
|
|
19
|
+
//! [compio]: https://docs.rs/compio
|
|
20
|
+
|
|
21
|
+
use std::{
|
|
22
|
+
future::Future,
|
|
23
|
+
pin::Pin,
|
|
24
|
+
sync::Arc,
|
|
25
|
+
time::{Duration, Instant},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
use wreq_proto::rt::{self, Sleep, Time};
|
|
29
|
+
|
|
30
|
+
/// A heap-allocated, type-erased future that is [`Send`] and resolves to `()`.
|
|
31
|
+
///
|
|
32
|
+
/// This is the concrete future type passed to [`rt::Executor::execute`] by the
|
|
33
|
+
/// client's background task machinery. Callers do not need to construct this
|
|
34
|
+
/// type directly; the [`rt::Executor<F>`] blanket implementation boxes and
|
|
35
|
+
/// pins any qualifying `F` automatically.
|
|
36
|
+
pub type BoxSendFuture = Pin<Box<dyn Future<Output = ()> + Send>>;
|
|
37
|
+
|
|
38
|
+
/// A handle to an async task executor.
|
|
39
|
+
///
|
|
40
|
+
/// `Executor` is used by the HTTP client to spawn background tasks such as
|
|
41
|
+
/// connection-pool cleanup and keep-alive management, without coupling the
|
|
42
|
+
/// client to a specific async runtime.
|
|
43
|
+
///
|
|
44
|
+
/// # Default behavior
|
|
45
|
+
///
|
|
46
|
+
/// [`Executor::default`] picks the runtime-appropriate implementation based
|
|
47
|
+
/// on the active feature flags:
|
|
48
|
+
///
|
|
49
|
+
/// | Feature flags active | Executor |
|
|
50
|
+
/// |-----------------------------------|-------------------|
|
|
51
|
+
/// | `tokio-rt` only | `TokioExecutor` |
|
|
52
|
+
/// | `compio-rt` only | `CompioExecutor` |
|
|
53
|
+
/// | both `tokio-rt` and `compio-rt` | `TokioExecutor` |
|
|
54
|
+
/// | neither | empty (panics) |
|
|
55
|
+
#[derive(Clone)]
|
|
56
|
+
pub struct Executor(Arc<dyn rt::Executor<BoxSendFuture> + Send + Sync>);
|
|
57
|
+
|
|
58
|
+
// ===== impl Executor =====
|
|
59
|
+
|
|
60
|
+
impl Executor {
|
|
61
|
+
/// Creates an [`Executor`] backed by a custom implementation.
|
|
62
|
+
///
|
|
63
|
+
/// The value is wrapped in an [`Arc`] and type-erased, so the resulting
|
|
64
|
+
/// handle is cheap to clone and safe to share across threads.
|
|
65
|
+
#[inline]
|
|
66
|
+
pub fn new<E>(exec: E) -> Self
|
|
67
|
+
where
|
|
68
|
+
E: rt::Executor<BoxSendFuture> + Send + Sync + 'static,
|
|
69
|
+
{
|
|
70
|
+
Executor(Arc::new(exec))
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
impl<Fut> rt::Executor<Fut> for Executor
|
|
75
|
+
where
|
|
76
|
+
Fut: Future<Output = ()> + Send + 'static,
|
|
77
|
+
{
|
|
78
|
+
/// Spawns `fut` on the underlying executor.
|
|
79
|
+
///
|
|
80
|
+
/// The future is boxed and pinned internally, so any `F` satisfying the
|
|
81
|
+
/// bounds can be passed without the caller needing to allocate first.
|
|
82
|
+
#[track_caller]
|
|
83
|
+
#[inline(always)]
|
|
84
|
+
fn execute(&self, fut: Fut) {
|
|
85
|
+
self.0.execute(Box::pin(fut))
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
impl Default for Executor {
|
|
90
|
+
/// Returns the runtime-appropriate default executor.
|
|
91
|
+
///
|
|
92
|
+
/// See the [type-level documentation][Executor] for the feature-flag
|
|
93
|
+
/// selection table.
|
|
94
|
+
#[inline]
|
|
95
|
+
fn default() -> Self {
|
|
96
|
+
if_tokio_rt!(block: {
|
|
97
|
+
return Executor(Arc::new(wreq_rt::rt::tokio::TokioExecutor::new()))
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
if_compio_rt!(block: {
|
|
101
|
+
return Executor(Arc::new(wreq_rt::rt::compio::CompioExecutor::new()))
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if_all_rt!(block: {
|
|
105
|
+
return Executor(Arc::new(wreq_rt::rt::tokio::TokioExecutor::new()))
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
if_no_rt!(block:{
|
|
109
|
+
panic!(
|
|
110
|
+
"no async runtime feature enabled; at least one of `tokio-rt` or `compio-rt` must be active"
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ===== Timer =====
|
|
117
|
+
|
|
118
|
+
/// A handle to an async timer.
|
|
119
|
+
///
|
|
120
|
+
/// `Timer` is used by the HTTP client to drive request and connection timeouts,
|
|
121
|
+
/// as well as the connection pool's idle-expiry loop. It wraps an
|
|
122
|
+
/// [`rt::Timer`] implementation in a cheap-to-clone, type-erased handle.
|
|
123
|
+
///
|
|
124
|
+
/// # Default behavior
|
|
125
|
+
///
|
|
126
|
+
/// [`Timer::default`] picks the runtime-appropriate implementation based on
|
|
127
|
+
/// the active feature flags:
|
|
128
|
+
///
|
|
129
|
+
/// | Feature flags active | Timer |
|
|
130
|
+
/// |-----------------------------------|-----------------|
|
|
131
|
+
/// | `tokio-rt` only | `TokioTimer` |
|
|
132
|
+
/// | `compio-rt` only | `CompioTimer` |
|
|
133
|
+
/// | both `tokio-rt` and `compio-rt` | `TokioTimer` |
|
|
134
|
+
/// | neither | empty (panics) |
|
|
135
|
+
#[derive(Clone)]
|
|
136
|
+
pub struct Timer(Time);
|
|
137
|
+
|
|
138
|
+
// ===== impl Timer =====
|
|
139
|
+
|
|
140
|
+
impl Timer {
|
|
141
|
+
/// Creates a [`Timer`] backed by a custom implementation.
|
|
142
|
+
#[inline]
|
|
143
|
+
pub fn new<M>(timer: M) -> Self
|
|
144
|
+
where
|
|
145
|
+
M: rt::Timer + Send + Sync + 'static,
|
|
146
|
+
{
|
|
147
|
+
Timer(Time::Timer(Arc::new(timer)))
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
#[cfg(test)]
|
|
151
|
+
#[doc(hidden)]
|
|
152
|
+
pub fn empty() -> Self {
|
|
153
|
+
Timer(Time::Empty)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/// Returns `true` if no timer implementation has been configured.
|
|
157
|
+
#[inline]
|
|
158
|
+
pub fn is_empty(&self) -> bool {
|
|
159
|
+
matches!(self.0, Time::Empty)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
impl Default for Timer {
|
|
164
|
+
#[inline]
|
|
165
|
+
fn default() -> Self {
|
|
166
|
+
if_tokio_rt!(block: {
|
|
167
|
+
return Timer(rt::Time::Timer(Arc::new(wreq_rt::rt::tokio::TokioTimer::new())))
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
if_compio_rt!(block: {
|
|
171
|
+
return Timer(rt::Time::Timer(Arc::new(wreq_rt::rt::compio::CompioTimer::new())))
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
if_all_rt!(block: {
|
|
175
|
+
return Timer(rt::Time::Timer(Arc::new(wreq_rt::rt::tokio::TokioTimer::new())))
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
if_no_rt!(block: {
|
|
179
|
+
Timer(Time::Empty)
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
impl rt::Timer for Timer {
|
|
185
|
+
/// Returns a future that resolves after `duration`.
|
|
186
|
+
#[inline]
|
|
187
|
+
fn sleep(&self, duration: Duration) -> Pin<Box<dyn Sleep>> {
|
|
188
|
+
self.0.sleep(duration)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/// Returns the current time according to the underlying runtime.
|
|
192
|
+
#[inline]
|
|
193
|
+
fn now(&self) -> Instant {
|
|
194
|
+
self.0.now()
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/// Returns a future that resolves at `deadline`.
|
|
198
|
+
#[inline]
|
|
199
|
+
fn sleep_until(&self, deadline: Instant) -> Pin<Box<dyn Sleep>> {
|
|
200
|
+
self.0.sleep_until(deadline)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/// Resets an in-flight sleep future to fire at `new_deadline` instead.
|
|
204
|
+
#[inline]
|
|
205
|
+
fn reset(&self, sleep: &mut Pin<Box<dyn Sleep>>, new_deadline: Instant) {
|
|
206
|
+
self.0.reset(sleep, new_deadline)
|
|
207
|
+
}
|
|
208
|
+
}
|
data/vendor/wreq/src/sync.rs
CHANGED
|
@@ -5,125 +5,124 @@
|
|
|
5
5
|
//!
|
|
6
6
|
//! This is useful in high-availability systems where panic recovery is done externally,
|
|
7
7
|
//! or poisoning is not meaningful in context.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
8
|
+
//!
|
|
9
|
+
//! ## Implementation
|
|
10
|
+
//! - When the `parking_lot` feature is enabled, it uses [`parking_lot::Mutex`] and
|
|
11
|
+
//! [`parking_lot::RwLock`].
|
|
12
|
+
//! - Otherwise, it wraps [`std::sync::Mutex`] and [`std::sync::RwLock`], using `.unwrap_or_else(|e|
|
|
13
|
+
//! e.into_inner())` to silently recover from poisoning.
|
|
14
|
+
|
|
15
|
+
#[cfg(feature = "parking_lot")]
|
|
16
|
+
pub use parking_lot::*;
|
|
17
|
+
|
|
18
|
+
#[cfg(not(feature = "parking_lot"))]
|
|
19
|
+
pub use self::std::*;
|
|
20
|
+
|
|
21
|
+
#[cfg(not(feature = "parking_lot"))]
|
|
22
|
+
mod std {
|
|
23
|
+
use std::{
|
|
24
|
+
ops::{Deref, DerefMut},
|
|
25
|
+
sync,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/// A [`Mutex`] that never poisons and has the same interface as [`std::sync::Mutex`].
|
|
29
|
+
///
|
|
30
|
+
/// See [`crate::sync`] for more details.
|
|
31
|
+
#[derive(Debug)]
|
|
32
|
+
pub struct Mutex<T: ?Sized>(sync::Mutex<T>);
|
|
33
|
+
|
|
34
|
+
impl<T> Mutex<T> {
|
|
35
|
+
/// Like [`std::sync::Mutex::new`].
|
|
36
|
+
#[inline]
|
|
37
|
+
pub fn new(t: T) -> Mutex<T> {
|
|
38
|
+
Mutex(sync::Mutex::new(t))
|
|
39
|
+
}
|
|
30
40
|
}
|
|
31
|
-
}
|
|
32
41
|
|
|
33
|
-
impl<T>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Mutex::new(T::default())
|
|
42
|
+
impl<T: ?Sized> Mutex<T> {
|
|
43
|
+
/// Like [`std::sync::Mutex::lock`].
|
|
44
|
+
#[inline]
|
|
45
|
+
pub fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
|
|
46
|
+
MutexGuard(self.0.lock().unwrap_or_else(|e| e.into_inner()))
|
|
47
|
+
}
|
|
40
48
|
}
|
|
41
|
-
}
|
|
42
49
|
|
|
43
|
-
/// Like [`std::sync::MutexGuard`].
|
|
44
|
-
#[must_use]
|
|
45
|
-
pub struct MutexGuard<'a, T: ?Sized + 'a>(sync::MutexGuard<'a, T>);
|
|
50
|
+
/// Like [`std::sync::MutexGuard`].
|
|
51
|
+
#[must_use]
|
|
52
|
+
pub struct MutexGuard<'a, T: ?Sized + 'a>(sync::MutexGuard<'a, T>);
|
|
46
53
|
|
|
47
|
-
impl<T: ?Sized> Deref for MutexGuard<'
|
|
48
|
-
|
|
54
|
+
impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
|
|
55
|
+
type Target = T;
|
|
49
56
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
#[inline]
|
|
58
|
+
fn deref(&self) -> &T {
|
|
59
|
+
self.0.deref()
|
|
60
|
+
}
|
|
53
61
|
}
|
|
54
|
-
}
|
|
55
62
|
|
|
56
|
-
impl<T: ?Sized> DerefMut for MutexGuard<'
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
|
|
64
|
+
#[inline]
|
|
65
|
+
fn deref_mut(&mut self) -> &mut T {
|
|
66
|
+
self.0.deref_mut()
|
|
67
|
+
}
|
|
60
68
|
}
|
|
61
|
-
}
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
/// Like [`std::sync::RwLock::new`].
|
|
68
|
-
#[inline]
|
|
69
|
-
pub fn new(t: T) -> RwLock<T> {
|
|
70
|
-
RwLock(sync::RwLock::new(t))
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
impl<T: ?Sized> RwLock<T> {
|
|
75
|
-
/// Like [`std::sync::RwLock::read`].
|
|
76
|
-
#[inline]
|
|
77
|
-
pub fn read(&self) -> RwLockReadGuard<'_, T> {
|
|
78
|
-
RwLockReadGuard(self.0.read().unwrap_or_else(|e| e.into_inner()))
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/// Like [`std::sync::RwLock::write`].
|
|
82
|
-
#[inline]
|
|
83
|
-
pub fn write(&self) -> RwLockWriteGuard<'_, T> {
|
|
84
|
-
RwLockWriteGuard(self.0.write().unwrap_or_else(|e| e.into_inner()))
|
|
70
|
+
impl<T: Default> Default for Mutex<T> {
|
|
71
|
+
fn default() -> Self {
|
|
72
|
+
Mutex(Default::default())
|
|
73
|
+
}
|
|
85
74
|
}
|
|
86
|
-
}
|
|
87
75
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
76
|
+
/// A [`RwLock`] that never poisons and has the same interface as [`std::sync::RwLock`].
|
|
77
|
+
///
|
|
78
|
+
/// See [`crate::sync`] for more details.
|
|
79
|
+
#[derive(Debug, Default)]
|
|
80
|
+
pub struct RwLock<T: ?Sized>(sync::RwLock<T>);
|
|
81
|
+
|
|
82
|
+
impl<T: ?Sized> RwLock<T> {
|
|
83
|
+
/// Like [`std::sync::RwLock::read`].
|
|
84
|
+
#[inline]
|
|
85
|
+
pub fn read<'a>(&'a self) -> RwLockReadGuard<'a, T> {
|
|
86
|
+
RwLockReadGuard(self.0.read().unwrap_or_else(|e| e.into_inner()))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// Like [`std::sync::RwLock::write`].
|
|
90
|
+
#[inline]
|
|
91
|
+
pub fn write<'a>(&'a self) -> RwLockWriteGuard<'a, T> {
|
|
92
|
+
RwLockWriteGuard(self.0.write().unwrap_or_else(|e| e.into_inner()))
|
|
93
|
+
}
|
|
95
94
|
}
|
|
96
|
-
}
|
|
97
95
|
|
|
98
|
-
/// Like [`std::sync::RwLockReadGuard`].
|
|
99
|
-
#[must_use]
|
|
100
|
-
pub struct RwLockReadGuard<'a, T: ?Sized + 'a>(sync::RwLockReadGuard<'a, T>);
|
|
96
|
+
/// Like [`std::sync::RwLockReadGuard`].
|
|
97
|
+
#[must_use]
|
|
98
|
+
pub struct RwLockReadGuard<'a, T: ?Sized + 'a>(sync::RwLockReadGuard<'a, T>);
|
|
101
99
|
|
|
102
|
-
impl<T: ?Sized> Deref for RwLockReadGuard<'
|
|
103
|
-
|
|
100
|
+
impl<'a, T: ?Sized> Deref for RwLockReadGuard<'a, T> {
|
|
101
|
+
type Target = T;
|
|
104
102
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
#[inline]
|
|
104
|
+
fn deref(&self) -> &T {
|
|
105
|
+
self.0.deref()
|
|
106
|
+
}
|
|
108
107
|
}
|
|
109
|
-
}
|
|
110
108
|
|
|
111
|
-
/// Like [`std::sync::RwLockWriteGuard`].
|
|
112
|
-
#[must_use]
|
|
113
|
-
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a>(sync::RwLockWriteGuard<'a, T>);
|
|
109
|
+
/// Like [`std::sync::RwLockWriteGuard`].
|
|
110
|
+
#[must_use]
|
|
111
|
+
pub struct RwLockWriteGuard<'a, T: ?Sized + 'a>(sync::RwLockWriteGuard<'a, T>);
|
|
114
112
|
|
|
115
|
-
impl<T: ?Sized> Deref for RwLockWriteGuard<'
|
|
116
|
-
|
|
113
|
+
impl<'a, T: ?Sized> Deref for RwLockWriteGuard<'a, T> {
|
|
114
|
+
type Target = T;
|
|
117
115
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
#[inline]
|
|
117
|
+
fn deref(&self) -> &T {
|
|
118
|
+
self.0.deref()
|
|
119
|
+
}
|
|
121
120
|
}
|
|
122
|
-
}
|
|
123
121
|
|
|
124
|
-
impl<T: ?Sized> DerefMut for RwLockWriteGuard<'
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
122
|
+
impl<'a, T: ?Sized> DerefMut for RwLockWriteGuard<'a, T> {
|
|
123
|
+
#[inline]
|
|
124
|
+
fn deref_mut(&mut self) -> &mut T {
|
|
125
|
+
self.0.deref_mut()
|
|
126
|
+
}
|
|
128
127
|
}
|
|
129
128
|
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
//! TLS certificate compression [RFC 8879](https://datatracker.ietf.org/doc/html/rfc8879).
|
|
2
|
+
//!
|
|
3
|
+
//! Reduces handshake latency by compressing certificate chains.
|
|
4
|
+
//! Supports Zlib, Brotli, and Zstd algorithms to minimize bytes-on-wire
|
|
5
|
+
//! and fit within the initial congestion window.
|
|
6
|
+
|
|
7
|
+
use std::{fmt::Debug, io};
|
|
8
|
+
|
|
9
|
+
use btls::{
|
|
10
|
+
error::ErrorStack,
|
|
11
|
+
ssl::{self, SslConnectorBuilder},
|
|
12
|
+
};
|
|
13
|
+
use btls_sys as ffi;
|
|
14
|
+
// Re-export the `CertificateCompressionAlgorithm` enum for users of this module.
|
|
15
|
+
pub use ssl::CertificateCompressionAlgorithm;
|
|
16
|
+
|
|
17
|
+
/// Certificate compression or decompression.
|
|
18
|
+
///
|
|
19
|
+
/// Wraps a function pointer or closure that processes certificate data.
|
|
20
|
+
#[allow(clippy::type_complexity)]
|
|
21
|
+
pub enum Codec {
|
|
22
|
+
/// Function pointer.
|
|
23
|
+
Pointer(fn(&[u8], &mut dyn io::Write) -> io::Result<()>),
|
|
24
|
+
/// Closure or function object.
|
|
25
|
+
Dynamic(Box<dyn Fn(&[u8], &mut dyn io::Write) -> io::Result<()> + Send + Sync>),
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// Trait for TLS certificate compression implementations.
|
|
29
|
+
///
|
|
30
|
+
/// Provides methods for compressing and decompressing certificate data,
|
|
31
|
+
/// as well as identifying the algorithm in use.
|
|
32
|
+
///
|
|
33
|
+
/// See [RFC 8879, §3](https://www.rfc-editor.org/rfc/rfc8879.html#name-compression-algorithms)
|
|
34
|
+
/// for the list of IANA-assigned compression algorithm identifiers.
|
|
35
|
+
pub trait CertificateCompressor: Debug + Sync + Send + 'static {
|
|
36
|
+
/// Returns the [`Codec`] used to compress certificate chains for this algorithm.
|
|
37
|
+
fn compress(&self) -> Codec;
|
|
38
|
+
|
|
39
|
+
/// Returns the [`Codec`] used to decompress certificate chains for this algorithm.
|
|
40
|
+
fn decompress(&self) -> Codec;
|
|
41
|
+
|
|
42
|
+
/// Returns the IANA-assigned identifier of the compression algorithm.
|
|
43
|
+
fn algorithm(&self) -> CertificateCompressionAlgorithm;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
struct Compressor<const ALGORITHM: i32> {
|
|
47
|
+
compress: Codec,
|
|
48
|
+
decompress: Codec,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ===== impl Codec =====
|
|
52
|
+
|
|
53
|
+
impl Codec {
|
|
54
|
+
#[inline]
|
|
55
|
+
fn call(&self, input: &[u8], output: &mut dyn io::Write) -> io::Result<()> {
|
|
56
|
+
match self {
|
|
57
|
+
Codec::Pointer(func) => func(input, output),
|
|
58
|
+
Codec::Dynamic(closure) => closure(input, output),
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ===== impl Compressor =====
|
|
64
|
+
|
|
65
|
+
impl<const ALGORITHM: i32> ssl::CertificateCompressor for Compressor<ALGORITHM> {
|
|
66
|
+
const ALGORITHM: CertificateCompressionAlgorithm = match ALGORITHM {
|
|
67
|
+
ffi::TLSEXT_cert_compression_zlib => CertificateCompressionAlgorithm::ZLIB,
|
|
68
|
+
ffi::TLSEXT_cert_compression_brotli => CertificateCompressionAlgorithm::BROTLI,
|
|
69
|
+
ffi::TLSEXT_cert_compression_zstd => CertificateCompressionAlgorithm::ZSTD,
|
|
70
|
+
_ => unreachable!(),
|
|
71
|
+
};
|
|
72
|
+
const CAN_COMPRESS: bool = true;
|
|
73
|
+
const CAN_DECOMPRESS: bool = true;
|
|
74
|
+
|
|
75
|
+
#[inline]
|
|
76
|
+
fn compress<W>(&self, input: &[u8], output: &mut W) -> io::Result<()>
|
|
77
|
+
where
|
|
78
|
+
W: io::Write,
|
|
79
|
+
{
|
|
80
|
+
self.compress.call(input, output)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#[inline]
|
|
84
|
+
fn decompress<W>(&self, input: &[u8], output: &mut W) -> io::Result<()>
|
|
85
|
+
where
|
|
86
|
+
W: io::Write,
|
|
87
|
+
{
|
|
88
|
+
self.decompress.call(input, output)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// Register a certificate compressor with the given [`SslConnectorBuilder`].
|
|
93
|
+
pub(super) fn register(
|
|
94
|
+
compressor: &dyn CertificateCompressor,
|
|
95
|
+
builder: &mut SslConnectorBuilder,
|
|
96
|
+
) -> Result<(), ErrorStack> {
|
|
97
|
+
match compressor.algorithm() {
|
|
98
|
+
CertificateCompressionAlgorithm::ZLIB => {
|
|
99
|
+
builder.add_certificate_compression_algorithm(Compressor::<
|
|
100
|
+
{ ffi::TLSEXT_cert_compression_zlib },
|
|
101
|
+
> {
|
|
102
|
+
compress: compressor.compress(),
|
|
103
|
+
decompress: compressor.decompress(),
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
CertificateCompressionAlgorithm::BROTLI => {
|
|
107
|
+
builder.add_certificate_compression_algorithm(Compressor::<
|
|
108
|
+
{ ffi::TLSEXT_cert_compression_brotli },
|
|
109
|
+
> {
|
|
110
|
+
compress: compressor.compress(),
|
|
111
|
+
decompress: compressor.decompress(),
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
CertificateCompressionAlgorithm::ZSTD => {
|
|
115
|
+
builder.add_certificate_compression_algorithm(Compressor::<
|
|
116
|
+
{ ffi::TLSEXT_cert_compression_zstd },
|
|
117
|
+
> {
|
|
118
|
+
compress: compressor.compress(),
|
|
119
|
+
decompress: compressor.decompress(),
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
_ => unreachable!(),
|
|
123
|
+
}
|
|
124
|
+
}
|