wreq-rb 0.3.0

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 (167) hide show
  1. checksums.yaml +7 -0
  2. data/Cargo.lock +2688 -0
  3. data/Cargo.toml +6 -0
  4. data/README.md +179 -0
  5. data/ext/wreq_rb/Cargo.toml +39 -0
  6. data/ext/wreq_rb/extconf.rb +22 -0
  7. data/ext/wreq_rb/src/client.rs +565 -0
  8. data/ext/wreq_rb/src/error.rs +25 -0
  9. data/ext/wreq_rb/src/lib.rs +20 -0
  10. data/ext/wreq_rb/src/response.rs +132 -0
  11. data/lib/wreq-rb/version.rb +5 -0
  12. data/lib/wreq-rb.rb +17 -0
  13. data/patches/0001-add-transfer-size-tracking.patch +292 -0
  14. data/vendor/wreq/Cargo.toml +306 -0
  15. data/vendor/wreq/LICENSE +202 -0
  16. data/vendor/wreq/README.md +122 -0
  17. data/vendor/wreq/examples/cert_store.rs +77 -0
  18. data/vendor/wreq/examples/connect_via_lower_priority_tokio_runtime.rs +258 -0
  19. data/vendor/wreq/examples/emulation.rs +118 -0
  20. data/vendor/wreq/examples/form.rs +14 -0
  21. data/vendor/wreq/examples/http1_websocket.rs +37 -0
  22. data/vendor/wreq/examples/http2_websocket.rs +45 -0
  23. data/vendor/wreq/examples/json_dynamic.rs +41 -0
  24. data/vendor/wreq/examples/json_typed.rs +47 -0
  25. data/vendor/wreq/examples/keylog.rs +16 -0
  26. data/vendor/wreq/examples/request_with_emulation.rs +115 -0
  27. data/vendor/wreq/examples/request_with_interface.rs +37 -0
  28. data/vendor/wreq/examples/request_with_local_address.rs +16 -0
  29. data/vendor/wreq/examples/request_with_proxy.rs +13 -0
  30. data/vendor/wreq/examples/request_with_redirect.rs +22 -0
  31. data/vendor/wreq/examples/request_with_version.rs +15 -0
  32. data/vendor/wreq/examples/tor_socks.rs +24 -0
  33. data/vendor/wreq/examples/unix_socket.rs +33 -0
  34. data/vendor/wreq/src/client/body.rs +304 -0
  35. data/vendor/wreq/src/client/conn/conn.rs +231 -0
  36. data/vendor/wreq/src/client/conn/connector.rs +549 -0
  37. data/vendor/wreq/src/client/conn/http.rs +1023 -0
  38. data/vendor/wreq/src/client/conn/proxy/socks.rs +233 -0
  39. data/vendor/wreq/src/client/conn/proxy/tunnel.rs +260 -0
  40. data/vendor/wreq/src/client/conn/proxy.rs +39 -0
  41. data/vendor/wreq/src/client/conn/tls_info.rs +98 -0
  42. data/vendor/wreq/src/client/conn/uds.rs +44 -0
  43. data/vendor/wreq/src/client/conn/verbose.rs +149 -0
  44. data/vendor/wreq/src/client/conn.rs +323 -0
  45. data/vendor/wreq/src/client/core/body/incoming.rs +485 -0
  46. data/vendor/wreq/src/client/core/body/length.rs +118 -0
  47. data/vendor/wreq/src/client/core/body.rs +34 -0
  48. data/vendor/wreq/src/client/core/common/buf.rs +149 -0
  49. data/vendor/wreq/src/client/core/common/rewind.rs +141 -0
  50. data/vendor/wreq/src/client/core/common/watch.rs +76 -0
  51. data/vendor/wreq/src/client/core/common.rs +3 -0
  52. data/vendor/wreq/src/client/core/conn/http1.rs +342 -0
  53. data/vendor/wreq/src/client/core/conn/http2.rs +307 -0
  54. data/vendor/wreq/src/client/core/conn.rs +11 -0
  55. data/vendor/wreq/src/client/core/dispatch.rs +299 -0
  56. data/vendor/wreq/src/client/core/error.rs +435 -0
  57. data/vendor/wreq/src/client/core/ext.rs +201 -0
  58. data/vendor/wreq/src/client/core/http1.rs +178 -0
  59. data/vendor/wreq/src/client/core/http2.rs +483 -0
  60. data/vendor/wreq/src/client/core/proto/h1/conn.rs +988 -0
  61. data/vendor/wreq/src/client/core/proto/h1/decode.rs +1170 -0
  62. data/vendor/wreq/src/client/core/proto/h1/dispatch.rs +684 -0
  63. data/vendor/wreq/src/client/core/proto/h1/encode.rs +580 -0
  64. data/vendor/wreq/src/client/core/proto/h1/io.rs +879 -0
  65. data/vendor/wreq/src/client/core/proto/h1/role.rs +694 -0
  66. data/vendor/wreq/src/client/core/proto/h1.rs +104 -0
  67. data/vendor/wreq/src/client/core/proto/h2/client.rs +650 -0
  68. data/vendor/wreq/src/client/core/proto/h2/ping.rs +539 -0
  69. data/vendor/wreq/src/client/core/proto/h2.rs +379 -0
  70. data/vendor/wreq/src/client/core/proto/headers.rs +138 -0
  71. data/vendor/wreq/src/client/core/proto.rs +58 -0
  72. data/vendor/wreq/src/client/core/rt/bounds.rs +57 -0
  73. data/vendor/wreq/src/client/core/rt/timer.rs +150 -0
  74. data/vendor/wreq/src/client/core/rt/tokio.rs +99 -0
  75. data/vendor/wreq/src/client/core/rt.rs +25 -0
  76. data/vendor/wreq/src/client/core/upgrade.rs +267 -0
  77. data/vendor/wreq/src/client/core.rs +16 -0
  78. data/vendor/wreq/src/client/emulation.rs +161 -0
  79. data/vendor/wreq/src/client/http/client/error.rs +142 -0
  80. data/vendor/wreq/src/client/http/client/exec.rs +29 -0
  81. data/vendor/wreq/src/client/http/client/extra.rs +77 -0
  82. data/vendor/wreq/src/client/http/client/lazy.rs +79 -0
  83. data/vendor/wreq/src/client/http/client/pool.rs +1105 -0
  84. data/vendor/wreq/src/client/http/client/util.rs +104 -0
  85. data/vendor/wreq/src/client/http/client.rs +1003 -0
  86. data/vendor/wreq/src/client/http/future.rs +99 -0
  87. data/vendor/wreq/src/client/http.rs +1629 -0
  88. data/vendor/wreq/src/client/layer/config/options.rs +156 -0
  89. data/vendor/wreq/src/client/layer/config.rs +116 -0
  90. data/vendor/wreq/src/client/layer/cookie.rs +161 -0
  91. data/vendor/wreq/src/client/layer/decoder.rs +139 -0
  92. data/vendor/wreq/src/client/layer/redirect/future.rs +270 -0
  93. data/vendor/wreq/src/client/layer/redirect/policy.rs +63 -0
  94. data/vendor/wreq/src/client/layer/redirect.rs +145 -0
  95. data/vendor/wreq/src/client/layer/retry/classify.rs +105 -0
  96. data/vendor/wreq/src/client/layer/retry/scope.rs +51 -0
  97. data/vendor/wreq/src/client/layer/retry.rs +151 -0
  98. data/vendor/wreq/src/client/layer/timeout/body.rs +233 -0
  99. data/vendor/wreq/src/client/layer/timeout/future.rs +90 -0
  100. data/vendor/wreq/src/client/layer/timeout.rs +177 -0
  101. data/vendor/wreq/src/client/layer.rs +15 -0
  102. data/vendor/wreq/src/client/multipart.rs +717 -0
  103. data/vendor/wreq/src/client/request.rs +818 -0
  104. data/vendor/wreq/src/client/response.rs +534 -0
  105. data/vendor/wreq/src/client/ws/json.rs +99 -0
  106. data/vendor/wreq/src/client/ws/message.rs +453 -0
  107. data/vendor/wreq/src/client/ws.rs +714 -0
  108. data/vendor/wreq/src/client.rs +27 -0
  109. data/vendor/wreq/src/config.rs +140 -0
  110. data/vendor/wreq/src/cookie.rs +579 -0
  111. data/vendor/wreq/src/dns/gai.rs +249 -0
  112. data/vendor/wreq/src/dns/hickory.rs +78 -0
  113. data/vendor/wreq/src/dns/resolve.rs +180 -0
  114. data/vendor/wreq/src/dns.rs +69 -0
  115. data/vendor/wreq/src/error.rs +502 -0
  116. data/vendor/wreq/src/ext.rs +398 -0
  117. data/vendor/wreq/src/hash.rs +143 -0
  118. data/vendor/wreq/src/header.rs +506 -0
  119. data/vendor/wreq/src/into_uri.rs +187 -0
  120. data/vendor/wreq/src/lib.rs +586 -0
  121. data/vendor/wreq/src/proxy/mac.rs +82 -0
  122. data/vendor/wreq/src/proxy/matcher.rs +806 -0
  123. data/vendor/wreq/src/proxy/uds.rs +66 -0
  124. data/vendor/wreq/src/proxy/win.rs +31 -0
  125. data/vendor/wreq/src/proxy.rs +569 -0
  126. data/vendor/wreq/src/redirect.rs +575 -0
  127. data/vendor/wreq/src/retry.rs +198 -0
  128. data/vendor/wreq/src/sync.rs +129 -0
  129. data/vendor/wreq/src/tls/conn/cache.rs +123 -0
  130. data/vendor/wreq/src/tls/conn/cert_compression.rs +125 -0
  131. data/vendor/wreq/src/tls/conn/ext.rs +82 -0
  132. data/vendor/wreq/src/tls/conn/macros.rs +34 -0
  133. data/vendor/wreq/src/tls/conn/service.rs +138 -0
  134. data/vendor/wreq/src/tls/conn.rs +681 -0
  135. data/vendor/wreq/src/tls/keylog/handle.rs +64 -0
  136. data/vendor/wreq/src/tls/keylog.rs +99 -0
  137. data/vendor/wreq/src/tls/options.rs +464 -0
  138. data/vendor/wreq/src/tls/x509/identity.rs +122 -0
  139. data/vendor/wreq/src/tls/x509/parser.rs +71 -0
  140. data/vendor/wreq/src/tls/x509/store.rs +228 -0
  141. data/vendor/wreq/src/tls/x509.rs +68 -0
  142. data/vendor/wreq/src/tls.rs +154 -0
  143. data/vendor/wreq/src/trace.rs +55 -0
  144. data/vendor/wreq/src/util.rs +122 -0
  145. data/vendor/wreq/tests/badssl.rs +228 -0
  146. data/vendor/wreq/tests/brotli.rs +350 -0
  147. data/vendor/wreq/tests/client.rs +1098 -0
  148. data/vendor/wreq/tests/connector_layers.rs +227 -0
  149. data/vendor/wreq/tests/cookie.rs +306 -0
  150. data/vendor/wreq/tests/deflate.rs +347 -0
  151. data/vendor/wreq/tests/emulation.rs +260 -0
  152. data/vendor/wreq/tests/gzip.rs +347 -0
  153. data/vendor/wreq/tests/layers.rs +261 -0
  154. data/vendor/wreq/tests/multipart.rs +165 -0
  155. data/vendor/wreq/tests/proxy.rs +438 -0
  156. data/vendor/wreq/tests/redirect.rs +629 -0
  157. data/vendor/wreq/tests/retry.rs +135 -0
  158. data/vendor/wreq/tests/support/delay_server.rs +117 -0
  159. data/vendor/wreq/tests/support/error.rs +16 -0
  160. data/vendor/wreq/tests/support/layer.rs +183 -0
  161. data/vendor/wreq/tests/support/mod.rs +9 -0
  162. data/vendor/wreq/tests/support/server.rs +232 -0
  163. data/vendor/wreq/tests/timeouts.rs +281 -0
  164. data/vendor/wreq/tests/unix_socket.rs +135 -0
  165. data/vendor/wreq/tests/upgrade.rs +98 -0
  166. data/vendor/wreq/tests/zstd.rs +559 -0
  167. metadata +225 -0
@@ -0,0 +1,307 @@
1
+ //! HTTP/2 client connections
2
+
3
+ use std::{
4
+ fmt,
5
+ future::Future,
6
+ marker::PhantomData,
7
+ pin::Pin,
8
+ task::{Context, Poll, ready},
9
+ };
10
+
11
+ use http::{Request, Response};
12
+ use http_body::Body;
13
+ use tokio::io::{AsyncRead, AsyncWrite};
14
+
15
+ use crate::{
16
+ client::core::{
17
+ Result,
18
+ body::Incoming as IncomingBody,
19
+ dispatch::{self, TrySendError},
20
+ error::{BoxError, Error},
21
+ proto::{self, h2::ping},
22
+ rt::{ArcTimer, Time, Timer, bounds::Http2ClientConnExec},
23
+ },
24
+ http2::Http2Options,
25
+ };
26
+
27
+ /// The sender side of an established connection.
28
+ pub struct SendRequest<B> {
29
+ dispatch: dispatch::UnboundedSender<Request<B>, Response<IncomingBody>>,
30
+ }
31
+
32
+ impl<B> Clone for SendRequest<B> {
33
+ fn clone(&self) -> SendRequest<B> {
34
+ SendRequest {
35
+ dispatch: self.dispatch.clone(),
36
+ }
37
+ }
38
+ }
39
+
40
+ /// A future that processes all HTTP state for the IO object.
41
+ ///
42
+ /// In most cases, this should just be spawned into an executor, so that it
43
+ /// can process incoming and outgoing messages, notice hangups, and the like.
44
+ #[must_use = "futures do nothing unless polled"]
45
+ pub struct Connection<T, B, E>
46
+ where
47
+ T: AsyncRead + AsyncWrite + Unpin,
48
+ B: Body + 'static,
49
+ E: Http2ClientConnExec<B, T> + Unpin,
50
+ B::Error: Into<BoxError>,
51
+ {
52
+ inner: (PhantomData<T>, proto::h2::ClientTask<B, E, T>),
53
+ }
54
+
55
+ /// A builder to configure an HTTP connection.
56
+ ///
57
+ /// After setting options, the builder is used to create a handshake future.
58
+ ///
59
+ /// **Note**: The default values of options are *not considered stable*. They
60
+ /// are subject to change at any time.
61
+ #[derive(Clone)]
62
+ pub struct Builder<Ex> {
63
+ exec: Ex,
64
+ timer: Time,
65
+ opts: Http2Options,
66
+ }
67
+
68
+ // ===== impl SendRequest
69
+
70
+ impl<B> SendRequest<B> {
71
+ /// Polls to determine whether this sender can be used yet for a request.
72
+ ///
73
+ /// If the associated connection is closed, this returns an Error.
74
+ pub fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<()>> {
75
+ if self.is_closed() {
76
+ Poll::Ready(Err(Error::new_closed()))
77
+ } else {
78
+ Poll::Ready(Ok(()))
79
+ }
80
+ }
81
+
82
+ /// Waits until the dispatcher is ready
83
+ ///
84
+ /// If the associated connection is closed, this returns an Error.
85
+ pub async fn ready(&mut self) -> Result<()> {
86
+ std::future::poll_fn(|cx| self.poll_ready(cx)).await
87
+ }
88
+
89
+ /// Checks if the connection is currently ready to send a request.
90
+ ///
91
+ /// # Note
92
+ ///
93
+ /// This is mostly a hint. Due to inherent latency of networks, it is
94
+ /// possible that even after checking this is ready, sending a request
95
+ /// may still fail because the connection was closed in the meantime.
96
+ pub fn is_ready(&self) -> bool {
97
+ self.dispatch.is_ready()
98
+ }
99
+
100
+ /// Checks if the connection side has been closed.
101
+ pub fn is_closed(&self) -> bool {
102
+ self.dispatch.is_closed()
103
+ }
104
+ }
105
+
106
+ impl<B> SendRequest<B>
107
+ where
108
+ B: Body + 'static,
109
+ {
110
+ /// Sends a `Request` on the associated connection.
111
+ ///
112
+ /// Returns a future that if successful, yields the `Response`.
113
+ ///
114
+ /// # Error
115
+ ///
116
+ /// If there was an error before trying to serialize the request to the
117
+ /// connection, the message will be returned as part of this error.
118
+ pub fn try_send_request(
119
+ &mut self,
120
+ req: Request<B>,
121
+ ) -> impl Future<Output = std::result::Result<Response<IncomingBody>, TrySendError<Request<B>>>>
122
+ {
123
+ let sent = self.dispatch.try_send(req);
124
+ async move {
125
+ match sent {
126
+ Ok(rx) => match rx.await {
127
+ Ok(Ok(res)) => Ok(res),
128
+ Ok(Err(err)) => Err(err),
129
+ // this is definite bug if it happens, but it shouldn't happen!
130
+ Err(_) => panic!("dispatch dropped without returning error"),
131
+ },
132
+ Err(req) => {
133
+ debug!("connection was not ready");
134
+ let error = Error::new_canceled().with("connection was not ready");
135
+ Err(TrySendError {
136
+ error,
137
+ message: Some(req),
138
+ })
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+
145
+ impl<B> fmt::Debug for SendRequest<B> {
146
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147
+ f.debug_struct("SendRequest").finish()
148
+ }
149
+ }
150
+
151
+ // ===== impl Connection
152
+
153
+ impl<T, B, E> fmt::Debug for Connection<T, B, E>
154
+ where
155
+ T: AsyncRead + AsyncWrite + fmt::Debug + 'static + Unpin,
156
+ B: Body + 'static,
157
+ E: Http2ClientConnExec<B, T> + Unpin,
158
+ B::Error: Into<BoxError>,
159
+ {
160
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161
+ f.debug_struct("Connection").finish()
162
+ }
163
+ }
164
+
165
+ impl<T, B, E> Future for Connection<T, B, E>
166
+ where
167
+ T: AsyncRead + AsyncWrite + Unpin + 'static,
168
+ B: Body + 'static + Unpin,
169
+ B::Data: Send,
170
+ E: Unpin,
171
+ B::Error: Into<BoxError>,
172
+ E: Http2ClientConnExec<B, T> + Unpin,
173
+ {
174
+ type Output = Result<()>;
175
+
176
+ fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
177
+ match ready!(Pin::new(&mut self.inner.1).poll(cx))? {
178
+ proto::Dispatched::Shutdown => Poll::Ready(Ok(())),
179
+ proto::Dispatched::Upgrade(_pending) => unreachable!("http2 cannot upgrade"),
180
+ }
181
+ }
182
+ }
183
+
184
+ // ===== impl Builder
185
+
186
+ impl<Ex> Builder<Ex>
187
+ where
188
+ Ex: Clone,
189
+ {
190
+ /// Creates a new connection builder.
191
+ #[inline]
192
+ pub fn new(exec: Ex) -> Builder<Ex> {
193
+ Builder {
194
+ exec,
195
+ timer: Time::Empty,
196
+ opts: Default::default(),
197
+ }
198
+ }
199
+
200
+ /// Provide a timer to execute background HTTP2 tasks.
201
+ #[inline]
202
+ pub fn timer<M>(&mut self, timer: M)
203
+ where
204
+ M: Timer + Send + Sync + 'static,
205
+ {
206
+ self.timer = Time::Timer(ArcTimer::new(timer));
207
+ }
208
+
209
+ /// Provide a options configuration for the HTTP/2 connection.
210
+ #[inline]
211
+ pub fn options(&mut self, opts: Http2Options) {
212
+ self.opts = opts;
213
+ }
214
+
215
+ /// Constructs a connection with the configured options and IO.
216
+ ///
217
+ /// Note, if [`Connection`] is not `await`-ed, [`SendRequest`] will
218
+ /// do nothing.
219
+ pub async fn handshake<T, B>(self, io: T) -> Result<(SendRequest<B>, Connection<T, B, Ex>)>
220
+ where
221
+ T: AsyncRead + AsyncWrite + Unpin,
222
+ B: Body + 'static,
223
+ B::Data: Send,
224
+ B::Error: Into<BoxError>,
225
+ Ex: Http2ClientConnExec<B, T> + Unpin,
226
+ {
227
+ trace!("client handshake HTTP/2");
228
+
229
+ // Crate the HTTP/2 client with the provided options.
230
+ let builder = {
231
+ let mut builder = http2::client::Builder::default();
232
+ builder
233
+ .initial_max_send_streams(self.opts.initial_max_send_streams)
234
+ .initial_window_size(self.opts.initial_window_size)
235
+ .initial_connection_window_size(self.opts.initial_conn_window_size)
236
+ .max_send_buffer_size(self.opts.max_send_buffer_size);
237
+ if let Some(id) = self.opts.initial_stream_id {
238
+ builder.initial_stream_id(id);
239
+ }
240
+ if let Some(max) = self.opts.max_pending_accept_reset_streams {
241
+ builder.max_pending_accept_reset_streams(max);
242
+ }
243
+ if let Some(max) = self.opts.max_concurrent_reset_streams {
244
+ builder.max_concurrent_reset_streams(max);
245
+ }
246
+ if let Some(max) = self.opts.max_concurrent_streams {
247
+ builder.max_concurrent_streams(max);
248
+ }
249
+ if let Some(max) = self.opts.max_header_list_size {
250
+ builder.max_header_list_size(max);
251
+ }
252
+ if let Some(opt) = self.opts.enable_push {
253
+ builder.enable_push(opt);
254
+ }
255
+ if let Some(max) = self.opts.max_frame_size {
256
+ builder.max_frame_size(max);
257
+ }
258
+ if let Some(max) = self.opts.header_table_size {
259
+ builder.header_table_size(max);
260
+ }
261
+ if let Some(v) = self.opts.enable_connect_protocol {
262
+ builder.enable_connect_protocol(v);
263
+ }
264
+ if let Some(v) = self.opts.no_rfc7540_priorities {
265
+ builder.no_rfc7540_priorities(v);
266
+ }
267
+ if let Some(order) = self.opts.settings_order {
268
+ builder.settings_order(order);
269
+ }
270
+ if let Some(experimental_settings) = self.opts.experimental_settings {
271
+ builder.experimental_settings(experimental_settings);
272
+ }
273
+ if let Some(stream_dependency) = self.opts.headers_stream_dependency {
274
+ builder.headers_stream_dependency(stream_dependency);
275
+ }
276
+ if let Some(order) = self.opts.headers_pseudo_order {
277
+ builder.headers_pseudo_order(order);
278
+ }
279
+ if let Some(priority) = self.opts.priorities {
280
+ builder.priorities(priority);
281
+ }
282
+
283
+ builder
284
+ };
285
+
286
+ // Create the ping configuration for the connection.
287
+ let ping_config = ping::Config::new(
288
+ self.opts.adaptive_window,
289
+ self.opts.initial_window_size,
290
+ self.opts.keep_alive_interval,
291
+ self.opts.keep_alive_timeout,
292
+ self.opts.keep_alive_while_idle,
293
+ );
294
+
295
+ let (tx, rx) = dispatch::channel();
296
+ let h2 = proto::h2::client::handshake(io, rx, builder, ping_config, self.exec, self.timer)
297
+ .await?;
298
+ Ok((
299
+ SendRequest {
300
+ dispatch: tx.unbound(),
301
+ },
302
+ Connection {
303
+ inner: (PhantomData, h2),
304
+ },
305
+ ))
306
+ }
307
+ }
@@ -0,0 +1,11 @@
1
+ //! Lower-level client connection API.
2
+ //!
3
+ //! The types in this module are to provide a lower-level API based around a
4
+ //! single connection. Connecting to a host, pooling connections, and the like
5
+ //! are not handled at this level. This module provides the building blocks to
6
+ //! customize those things externally.
7
+
8
+ pub mod http1;
9
+ pub mod http2;
10
+
11
+ pub use super::dispatch::TrySendError;
@@ -0,0 +1,299 @@
1
+ use std::{
2
+ future::Future,
3
+ pin::Pin,
4
+ task::{Context, Poll},
5
+ };
6
+
7
+ use http::{Request, Response};
8
+ use http_body::Body;
9
+ use pin_project_lite::pin_project;
10
+ use tokio::sync::{mpsc, oneshot};
11
+
12
+ use super::{Error, body::Incoming, proto::h2::client::ResponseFutMap};
13
+
14
+ pub(crate) type RetryPromise<T, U> = oneshot::Receiver<Result<U, TrySendError<T>>>;
15
+
16
+ /// An error when calling `try_send_request`.
17
+ ///
18
+ /// There is a possibility of an error occurring on a connection in-between the
19
+ /// time that a request is queued and when it is actually written to the IO
20
+ /// transport. If that happens, it is safe to return the request back to the
21
+ /// caller, as it was never fully sent.
22
+ #[derive(Debug)]
23
+ pub struct TrySendError<T> {
24
+ pub(crate) error: Error,
25
+ pub(crate) message: Option<T>,
26
+ }
27
+
28
+ pub(crate) fn channel<T, U>() -> (Sender<T, U>, Receiver<T, U>) {
29
+ let (tx, rx) = mpsc::unbounded_channel();
30
+ let (giver, taker) = want::new();
31
+ let tx = Sender {
32
+ buffered_once: false,
33
+ giver,
34
+ inner: tx,
35
+ };
36
+ let rx = Receiver { inner: rx, taker };
37
+ (tx, rx)
38
+ }
39
+
40
+ /// A bounded sender of requests and callbacks for when responses are ready.
41
+ ///
42
+ /// While the inner sender is unbounded, the Giver is used to determine
43
+ /// if the Receiver is ready for another request.
44
+ pub(crate) struct Sender<T, U> {
45
+ /// One message is always allowed, even if the Receiver hasn't asked
46
+ /// for it yet. This boolean keeps track of whether we've sent one
47
+ /// without notice.
48
+ buffered_once: bool,
49
+ /// The Giver helps watch that the Receiver side has been polled
50
+ /// when the queue is empty. This helps us know when a request and
51
+ /// response have been fully processed, and a connection is ready
52
+ /// for more.
53
+ giver: want::Giver,
54
+ /// Actually bounded by the Giver, plus `buffered_once`.
55
+ inner: mpsc::UnboundedSender<Envelope<T, U>>,
56
+ }
57
+
58
+ /// An unbounded version.
59
+ ///
60
+ /// Cannot poll the Giver, but can still use it to determine if the Receiver
61
+ /// has been dropped. However, this version can be cloned.
62
+ pub(crate) struct UnboundedSender<T, U> {
63
+ /// Only used for `is_closed`, since mpsc::UnboundedSender cannot be checked.
64
+ giver: want::SharedGiver,
65
+ inner: mpsc::UnboundedSender<Envelope<T, U>>,
66
+ }
67
+
68
+ impl<T, U> Sender<T, U> {
69
+ pub(crate) fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<super::Result<()>> {
70
+ self.giver.poll_want(cx).map_err(|_| Error::new_closed())
71
+ }
72
+
73
+ pub(crate) fn is_ready(&self) -> bool {
74
+ self.giver.is_wanting()
75
+ }
76
+
77
+ fn can_send(&mut self) -> bool {
78
+ if self.giver.give() || !self.buffered_once {
79
+ // If the receiver is ready *now*, then of course we can send.
80
+ //
81
+ // If the receiver isn't ready yet, but we don't have anything
82
+ // in the channel yet, then allow one message.
83
+ self.buffered_once = true;
84
+ true
85
+ } else {
86
+ false
87
+ }
88
+ }
89
+
90
+ pub(crate) fn try_send(&mut self, val: T) -> Result<RetryPromise<T, U>, T> {
91
+ if !self.can_send() {
92
+ return Err(val);
93
+ }
94
+ let (tx, rx) = oneshot::channel();
95
+ self.inner
96
+ .send(Envelope(Some((val, Callback(Some(tx))))))
97
+ .map(move |_| rx)
98
+ .map_err(|mut e| (e.0).0.take().expect("envelope not dropped").0)
99
+ }
100
+
101
+ pub(crate) fn unbound(self) -> UnboundedSender<T, U> {
102
+ UnboundedSender {
103
+ giver: self.giver.shared(),
104
+ inner: self.inner,
105
+ }
106
+ }
107
+ }
108
+
109
+ impl<T, U> UnboundedSender<T, U> {
110
+ pub(crate) fn is_ready(&self) -> bool {
111
+ !self.giver.is_canceled()
112
+ }
113
+
114
+ pub(crate) fn is_closed(&self) -> bool {
115
+ self.giver.is_canceled()
116
+ }
117
+
118
+ pub(crate) fn try_send(&mut self, val: T) -> Result<RetryPromise<T, U>, T> {
119
+ let (tx, rx) = oneshot::channel();
120
+ self.inner
121
+ .send(Envelope(Some((val, Callback(Some(tx))))))
122
+ .map(move |_| rx)
123
+ .map_err(|mut e| (e.0).0.take().expect("envelope not dropped").0)
124
+ }
125
+ }
126
+
127
+ impl<T, U> Clone for UnboundedSender<T, U> {
128
+ fn clone(&self) -> Self {
129
+ UnboundedSender {
130
+ giver: self.giver.clone(),
131
+ inner: self.inner.clone(),
132
+ }
133
+ }
134
+ }
135
+
136
+ pub(crate) struct Receiver<T, U> {
137
+ inner: mpsc::UnboundedReceiver<Envelope<T, U>>,
138
+ taker: want::Taker,
139
+ }
140
+
141
+ impl<T, U> Receiver<T, U> {
142
+ pub(crate) fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Option<(T, Callback<T, U>)>> {
143
+ match self.inner.poll_recv(cx) {
144
+ Poll::Ready(item) => {
145
+ Poll::Ready(item.map(|mut env| env.0.take().expect("envelope not dropped")))
146
+ }
147
+ Poll::Pending => {
148
+ self.taker.want();
149
+ Poll::Pending
150
+ }
151
+ }
152
+ }
153
+
154
+ pub(crate) fn close(&mut self) {
155
+ self.taker.cancel();
156
+ self.inner.close();
157
+ }
158
+
159
+ pub(crate) fn try_recv(&mut self) -> Option<(T, Callback<T, U>)> {
160
+ use futures_util::FutureExt;
161
+ match self.inner.recv().now_or_never() {
162
+ Some(Some(mut env)) => env.0.take(),
163
+ _ => None,
164
+ }
165
+ }
166
+ }
167
+
168
+ impl<T, U> Drop for Receiver<T, U> {
169
+ fn drop(&mut self) {
170
+ // Notify the giver about the closure first, before dropping
171
+ // the mpsc::Receiver.
172
+ self.taker.cancel();
173
+ }
174
+ }
175
+
176
+ struct Envelope<T, U>(Option<(T, Callback<T, U>)>);
177
+
178
+ impl<T, U> Drop for Envelope<T, U> {
179
+ fn drop(&mut self) {
180
+ if let Some((val, cb)) = self.0.take() {
181
+ cb.send(Err(TrySendError {
182
+ error: Error::new_canceled().with("connection closed"),
183
+ message: Some(val),
184
+ }));
185
+ }
186
+ }
187
+ }
188
+
189
+ pub(crate) struct Callback<T, U>(Option<oneshot::Sender<Result<U, TrySendError<T>>>>);
190
+
191
+ impl<T, U> Drop for Callback<T, U> {
192
+ fn drop(&mut self) {
193
+ if let Some(tx) = self.0.take() {
194
+ let _ = tx.send(Err(TrySendError {
195
+ error: dispatch_gone(),
196
+ message: None,
197
+ }));
198
+ }
199
+ }
200
+ }
201
+
202
+ #[cold]
203
+ fn dispatch_gone() -> Error {
204
+ // FIXME(nox): What errors do we want here?
205
+ Error::new_user_dispatch_gone().with(if std::thread::panicking() {
206
+ "user code panicked"
207
+ } else {
208
+ "runtime dropped the dispatch task"
209
+ })
210
+ }
211
+
212
+ impl<T, U> Callback<T, U> {
213
+ pub(crate) fn is_canceled(&self) -> bool {
214
+ if let Some(ref tx) = self.0 {
215
+ return tx.is_closed();
216
+ }
217
+
218
+ unreachable!()
219
+ }
220
+
221
+ pub(crate) fn poll_canceled(&mut self, cx: &mut Context<'_>) -> Poll<()> {
222
+ if let Some(ref mut tx) = self.0 {
223
+ return tx.poll_closed(cx);
224
+ }
225
+
226
+ unreachable!()
227
+ }
228
+
229
+ pub(crate) fn send(mut self, val: Result<U, TrySendError<T>>) {
230
+ let _ = self.0.take().unwrap().send(val);
231
+ }
232
+ }
233
+
234
+ impl<T> TrySendError<T> {
235
+ /// Take the message from this error.
236
+ ///
237
+ /// The message will not always have been recovered. If an error occurs
238
+ /// after the message has been serialized onto the connection, it will not
239
+ /// be available here.
240
+ pub fn take_message(&mut self) -> Option<T> {
241
+ self.message.take()
242
+ }
243
+
244
+ /// Consumes this to return the inner error.
245
+ pub fn into_error(self) -> Error {
246
+ self.error
247
+ }
248
+ }
249
+
250
+ pin_project! {
251
+ pub struct SendWhen<B>
252
+ where
253
+ B: Body,
254
+ B: 'static,
255
+ {
256
+ #[pin]
257
+ pub(crate) when: ResponseFutMap<B>,
258
+ #[pin]
259
+ pub(crate) call_back: Option<Callback<Request<B>, Response<Incoming>>>,
260
+ }
261
+ }
262
+
263
+ impl<B> Future for SendWhen<B>
264
+ where
265
+ B: Body + 'static,
266
+ B::Data: Send,
267
+ {
268
+ type Output = ();
269
+
270
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
271
+ let mut this = self.project();
272
+
273
+ let mut call_back = this.call_back.take().expect("polled after complete");
274
+
275
+ match Pin::new(&mut this.when).poll(cx) {
276
+ Poll::Ready(Ok(res)) => {
277
+ call_back.send(Ok(res));
278
+ Poll::Ready(())
279
+ }
280
+ Poll::Pending => {
281
+ // check if the callback is canceled
282
+ match call_back.poll_canceled(cx) {
283
+ Poll::Ready(v) => v,
284
+ Poll::Pending => {
285
+ // Move call_back back to struct before return
286
+ this.call_back.set(Some(call_back));
287
+ return Poll::Pending;
288
+ }
289
+ };
290
+ trace!("send_when canceled");
291
+ Poll::Ready(())
292
+ }
293
+ Poll::Ready(Err((error, message))) => {
294
+ call_back.send(Err(TrySendError { error, message }));
295
+ Poll::Ready(())
296
+ }
297
+ }
298
+ }
299
+ }