libp2p_quic/connection/
connecting.rs1use std::{
24 pin::Pin,
25 task::{Context, Poll},
26 time::Duration,
27};
28
29use futures::{
30 future::{select, Either, FutureExt, Select},
31 prelude::*,
32};
33use futures_timer::Delay;
34use libp2p_identity::PeerId;
35use quinn::rustls::pki_types::CertificateDer;
36
37use crate::{Connection, ConnectionError, Error};
38
39#[derive(Debug)]
41pub struct Connecting {
42 connecting: Select<quinn::Connecting, Delay>,
43}
44
45impl Connecting {
46 pub(crate) fn new(connection: quinn::Connecting, timeout: Duration) -> Self {
47 Connecting {
48 connecting: select(connection, Delay::new(timeout)),
49 }
50 }
51}
52
53impl Connecting {
54 fn remote_peer_id(connection: &quinn::Connection) -> PeerId {
57 let identity = connection
58 .peer_identity()
59 .expect("connection got identity because it passed TLS handshake; qed");
60 let certificates: Box<Vec<CertificateDer>> =
61 identity.downcast().expect("we rely on rustls feature; qed");
62 let end_entity = certificates
63 .first()
64 .expect("there should be exactly one certificate; qed");
65 let p2p_cert = libp2p_tls::certificate::parse(end_entity)
66 .expect("the certificate was validated during TLS handshake; qed");
67 p2p_cert.peer_id()
68 }
69}
70
71impl Future for Connecting {
72 type Output = Result<(PeerId, Connection), Error>;
73
74 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
75 let connection = match futures::ready!(self.connecting.poll_unpin(cx)) {
76 Either::Right(_) => return Poll::Ready(Err(Error::HandshakeTimedOut)),
77 Either::Left((connection, _)) => connection.map_err(ConnectionError)?,
78 };
79
80 let peer_id = Self::remote_peer_id(&connection);
81 let muxer = Connection::new(connection);
82 Poll::Ready(Ok((peer_id, muxer)))
83 }
84}