1use std::any::TypeId;
43use std::error::Error as StdError;
44use std::fmt;
45use std::future::Future;
46use std::io;
47use std::pin::Pin;
48use std::sync::{Arc, Mutex};
49use std::task::{Context, Poll};
50
51use crate::rt::{Read, ReadBufCursor, Write};
52use bytes::Bytes;
53use tokio::sync::oneshot;
54
55use crate::common::io::Rewind;
56use crate::common::lock::LockResultExt;
57
58pub struct Upgraded {
67 io: Rewind<Box<dyn Io + Send>>,
68}
69
70#[derive(Clone)]
74pub struct OnUpgrade {
75 rx: Option<Arc<Mutex<oneshot::Receiver<crate::Result<Upgraded>>>>>,
76}
77
78#[derive(Debug)]
83#[non_exhaustive]
84pub struct Parts<T> {
85 pub io: T,
87 pub read_buf: Bytes,
96}
97
98pub fn on<T: sealed::CanUpgrade>(msg: T) -> OnUpgrade {
107 msg.on_upgrade()
108}
109
110#[cfg(all(
111 any(feature = "client", feature = "server"),
112 any(feature = "http1", feature = "http2"),
113))]
114pub(super) struct Pending {
115 tx: oneshot::Sender<crate::Result<Upgraded>>,
116}
117
118#[cfg(all(
119 any(feature = "client", feature = "server"),
120 any(feature = "http1", feature = "http2"),
121))]
122pub(super) fn pending() -> (Pending, OnUpgrade) {
123 let (tx, rx) = oneshot::channel();
124 (
125 Pending { tx },
126 OnUpgrade {
127 rx: Some(Arc::new(Mutex::new(rx))),
128 },
129 )
130}
131
132impl Upgraded {
135 #[cfg(all(
136 any(feature = "client", feature = "server"),
137 any(feature = "http1", feature = "http2")
138 ))]
139 pub(super) fn new<T>(io: T, read_buf: Bytes) -> Self
140 where
141 T: Read + Write + Unpin + Send + 'static,
142 {
143 Upgraded {
144 io: Rewind::new_buffered(Box::new(io), read_buf),
145 }
146 }
147
148 pub fn downcast<T: Read + Write + Unpin + 'static>(self) -> Result<Parts<T>, Self> {
155 let (io, buf) = self.io.into_inner();
156 match io.__hyper_downcast() {
157 Ok(t) => Ok(Parts {
158 io: *t,
159 read_buf: buf,
160 }),
161 Err(io) => Err(Upgraded {
162 io: Rewind::new_buffered(io, buf),
163 }),
164 }
165 }
166}
167
168impl Read for Upgraded {
169 fn poll_read(
170 mut self: Pin<&mut Self>,
171 cx: &mut Context<'_>,
172 buf: ReadBufCursor<'_>,
173 ) -> Poll<io::Result<()>> {
174 Pin::new(&mut self.io).poll_read(cx, buf)
175 }
176}
177
178impl Write for Upgraded {
179 fn poll_write(
180 mut self: Pin<&mut Self>,
181 cx: &mut Context<'_>,
182 buf: &[u8],
183 ) -> Poll<io::Result<usize>> {
184 Pin::new(&mut self.io).poll_write(cx, buf)
185 }
186
187 fn poll_write_vectored(
188 mut self: Pin<&mut Self>,
189 cx: &mut Context<'_>,
190 bufs: &[io::IoSlice<'_>],
191 ) -> Poll<io::Result<usize>> {
192 Pin::new(&mut self.io).poll_write_vectored(cx, bufs)
193 }
194
195 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
196 Pin::new(&mut self.io).poll_flush(cx)
197 }
198
199 fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
200 Pin::new(&mut self.io).poll_shutdown(cx)
201 }
202
203 fn is_write_vectored(&self) -> bool {
204 self.io.is_write_vectored()
205 }
206}
207
208impl fmt::Debug for Upgraded {
209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 f.debug_struct("Upgraded").finish()
211 }
212}
213
214impl OnUpgrade {
217 pub(super) fn none() -> Self {
218 OnUpgrade { rx: None }
219 }
220
221 #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
222 pub(super) fn is_none(&self) -> bool {
223 self.rx.is_none()
224 }
225}
226
227impl Future for OnUpgrade {
228 type Output = Result<Upgraded, crate::Error>;
229
230 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
231 match &self.rx {
232 Some(rx) => {
233 Pin::new(&mut *rx.lock().panic_if_poisoned())
234 .poll(cx)
235 .map(|res| match res {
236 Ok(Ok(upgraded)) => Ok(upgraded),
237 Ok(Err(err)) => Err(err),
238 Err(_oneshot_canceled) => {
239 Err(crate::Error::new_canceled().with(UpgradeExpected))
240 }
241 })
242 }
243 None => Poll::Ready(Err(crate::Error::new_user_no_upgrade())),
244 }
245 }
246}
247
248impl fmt::Debug for OnUpgrade {
249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 f.debug_struct("OnUpgrade").finish()
251 }
252}
253
254#[cfg(all(
257 any(feature = "client", feature = "server"),
258 any(feature = "http1", feature = "http2")
259))]
260impl Pending {
261 pub(super) fn fulfill(self, upgraded: Upgraded) {
262 trace!("pending upgrade fulfill");
263 let _ = self.tx.send(Ok(upgraded));
264 }
265
266 #[cfg(feature = "http1")]
267 pub(super) fn manual(self) {
270 #[cfg(any(feature = "http1", feature = "http2"))]
271 trace!("pending upgrade handled manually");
272 let _ = self.tx.send(Err(crate::Error::new_user_manual_upgrade()));
273 }
274}
275
276#[derive(Debug)]
283struct UpgradeExpected;
284
285impl fmt::Display for UpgradeExpected {
286 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
287 f.write_str("upgrade expected but not completed")
288 }
289}
290
291impl StdError for UpgradeExpected {}
292
293pub(super) trait Io: Read + Write + Unpin + 'static {
296 fn __hyper_type_id(&self) -> TypeId {
297 TypeId::of::<Self>()
298 }
299}
300
301impl<T: Read + Write + Unpin + 'static> Io for T {}
302
303impl dyn Io + Send {
304 fn __hyper_is<T: Io>(&self) -> bool {
305 let t = TypeId::of::<T>();
306 self.__hyper_type_id() == t
307 }
308 fn __hyper_downcast<T: Io>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
311 if self.__hyper_is::<T>() {
312 unsafe {
323 let raw: *mut dyn Io = Box::into_raw(self);
324 Ok(Box::from_raw(raw.cast()))
325 }
326 } else {
327 Err(self)
328 }
329 }
330}
331
332mod sealed {
333 use super::OnUpgrade;
334
335 pub trait CanUpgrade {
336 fn on_upgrade(self) -> OnUpgrade;
337 }
338
339 impl<B> CanUpgrade for http::Request<B> {
340 fn on_upgrade(mut self) -> OnUpgrade {
341 self.extensions_mut()
342 .remove::<OnUpgrade>()
343 .unwrap_or_else(OnUpgrade::none)
344 }
345 }
346
347 impl<B> CanUpgrade for &'_ mut http::Request<B> {
348 fn on_upgrade(self) -> OnUpgrade {
349 self.extensions_mut()
350 .remove::<OnUpgrade>()
351 .unwrap_or_else(OnUpgrade::none)
352 }
353 }
354
355 impl<B> CanUpgrade for http::Response<B> {
356 fn on_upgrade(mut self) -> OnUpgrade {
357 self.extensions_mut()
358 .remove::<OnUpgrade>()
359 .unwrap_or_else(OnUpgrade::none)
360 }
361 }
362
363 impl<B> CanUpgrade for &'_ mut http::Response<B> {
364 fn on_upgrade(self) -> OnUpgrade {
365 self.extensions_mut()
366 .remove::<OnUpgrade>()
367 .unwrap_or_else(OnUpgrade::none)
368 }
369 }
370}
371
372#[cfg(all(
373 any(feature = "client", feature = "server"),
374 any(feature = "http1", feature = "http2"),
375))]
376#[cfg(test)]
377mod tests {
378 use super::*;
379
380 #[test]
381 fn upgraded_downcast() {
382 let upgraded = Upgraded::new(Mock, Bytes::new());
383
384 let upgraded = upgraded
385 .downcast::<crate::common::io::Compat<std::io::Cursor<Vec<u8>>>>()
386 .unwrap_err();
387
388 upgraded.downcast::<Mock>().unwrap();
389 }
390
391 struct Mock;
393
394 impl Read for Mock {
395 fn poll_read(
396 self: Pin<&mut Self>,
397 _cx: &mut Context<'_>,
398 _buf: ReadBufCursor<'_>,
399 ) -> Poll<io::Result<()>> {
400 unreachable!("Mock::poll_read")
401 }
402 }
403
404 impl Write for Mock {
405 fn poll_write(
406 self: Pin<&mut Self>,
407 _: &mut Context<'_>,
408 buf: &[u8],
409 ) -> Poll<io::Result<usize>> {
410 Poll::Ready(Ok(buf.len()))
411 }
412
413 fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
414 unreachable!("Mock::poll_flush")
415 }
416
417 fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
418 unreachable!("Mock::poll_shutdown")
419 }
420 }
421}