web_transport_quinn/
client.rsuse thiserror::Error;
use tokio::net::lookup_host;
use url::Url;
use crate::{Connect, ConnectError, Session, Settings, SettingsError};
#[derive(Error, Debug, Clone)]
pub enum ClientError {
#[error("unexpected end of stream")]
UnexpectedEnd,
#[error("connection error: {0}")]
Connection(#[from] quinn::ConnectionError),
#[error("failed to write: {0}")]
WriteError(#[from] quinn::WriteError),
#[error("failed to read: {0}")]
ReadError(#[from] quinn::ReadError),
#[error("failed to exchange h3 settings: {0}")]
SettingsError(#[from] SettingsError),
#[error("failed to exchange h3 connect: {0}")]
ConnectError(#[from] ConnectError),
#[error("quic error: {0}")]
QuicError(#[from] quinn::ConnectError),
#[error("invalid DNS name: {0}")]
InvalidDnsName(String),
}
pub async fn connect(client: &quinn::Endpoint, url: &Url) -> Result<Session, ClientError> {
let host = url
.host()
.ok_or_else(|| ClientError::InvalidDnsName("".to_string()))?
.to_string();
let port = url.port().unwrap_or(443);
let mut remotes = match lookup_host((host.clone(), port)).await {
Ok(remotes) => remotes,
Err(_) => return Err(ClientError::InvalidDnsName(host)),
};
let remote = match remotes.next() {
Some(remote) => remote,
None => return Err(ClientError::InvalidDnsName(host)),
};
let conn = client.connect(remote, &host)?;
let conn = conn.await?;
connect_with(conn, url).await
}
pub async fn connect_with(conn: quinn::Connection, url: &Url) -> Result<Session, ClientError> {
let settings = Settings::connect(&conn).await?;
let connect = Connect::open(&conn, url).await?;
let session = Session::new(conn, settings, connect);
Ok(session)
}