use alloc::boxed::Box;
use alloc::vec::Vec;
use core::{fmt, mem};
use super::{
Connection, NeedsInput, SideCommonOutput, SideData, StateMachine, VerifySidePeerIdentity,
};
use crate::client::{ClientSide, ClientState};
use crate::common_state::{Protocol, maybe_send_fatal_alert};
use crate::crypto::VerifiedIdentity;
use crate::error::Error;
use crate::msgs::ServerExtensionsInput;
use crate::quic::{FromConn, Quic, QuicEvent, QuicOutput};
use crate::server::{
ChooseConfig, ClientHello, ServerConfig, ServerHandshake, ServerSide, ServerState,
};
use crate::sync::Arc;
use crate::tracing::trace;
pub(crate) enum ServerNext<T: Transport> {
NeedsInput(Connection<ServerSide, T>),
ChooseConfig(Accepted<T>),
VerifyClientIdentity(VerifyPeerIdentity<ServerSide, T>),
Complete(Connection<ServerSide, T>),
}
impl<T: Transport> TryFrom<Connection<ServerSide, T>> for ServerNext<T> {
type Error = Error;
fn try_from(mut conn: Connection<ServerSide, T>) -> Result<Self, Error> {
const MISUSED: Error = Error::Unreachable("forgot to restore state");
Ok(match mem::replace(&mut conn.state, Err(MISUSED))? {
ServerState::ChooseConfig(choose_config) => Self::ChooseConfig(Accepted {
conn,
choose_config,
}),
ServerState::VerifyClientIdentity(verify_identity) => {
Self::VerifyClientIdentity(VerifyPeerIdentity {
conn,
verify_identity,
})
}
state if state.is_traffic() => {
conn.state = Ok(state);
Self::Complete(conn)
}
state => {
conn.state = Ok(state);
Self::NeedsInput(conn)
}
})
}
}
pub(crate) enum ClientNext<T: Transport> {
NeedsInput(Connection<ClientSide, T>),
VerifyServerIdentity(VerifyPeerIdentity<ClientSide, T>),
Complete(Connection<ClientSide, T>),
}
impl<T: Transport> TryFrom<Connection<ClientSide, T>> for ClientNext<T> {
type Error = Error;
fn try_from(mut conn: Connection<ClientSide, T>) -> Result<Self, Error> {
const MISUSED: Error = Error::Unreachable("forgot to restore state");
Ok(match mem::replace(&mut conn.state, Err(MISUSED))? {
ClientState::VerifyServerIdentity(verify_identity) => {
Self::VerifyServerIdentity(VerifyPeerIdentity {
conn,
verify_identity,
})
}
state if state.is_traffic() => {
conn.state = Ok(state);
Self::Complete(conn)
}
state => {
conn.state = Ok(state);
Self::NeedsInput(conn)
}
})
}
}
pub struct Accepted<T: Transport> {
pub(crate) conn: Connection<ServerSide, T>,
choose_config: Box<ChooseConfig>,
}
impl<T: Transport> Accepted<T> {
pub fn client_hello(&self) -> ClientHello<'_> {
let ch = self.choose_config.client_hello();
trace!("Accepted::client_hello(): {ch:#?}");
ch
}
pub(crate) fn partial_choose_config(
self,
config: Arc<ServerConfig>,
exts: ServerExtensionsInput,
tls: &mut Vec<u8>,
) -> Result<Connection<ServerSide, T>, Error> {
let Self {
mut conn,
choose_config,
} = self;
let result = conn.accepted(choose_config, exts, config, tls);
let send_path = &mut conn.common.send;
if let Err(err) = &result {
maybe_send_fatal_alert(send_path, err, tls)?;
}
result?;
Ok(conn)
}
}
impl Accepted<Tcp> {
pub fn choose_config(
self,
config: Arc<ServerConfig>,
tls: &mut Vec<u8>,
) -> Result<ServerHandshake, Error> {
Ok(ServerHandshake::NeedsInput(NeedsInput(
self.partial_choose_config(config, ServerExtensionsInput::default(), tls)?,
)))
}
}
impl<T: Transport> fmt::Debug for Accepted<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Accepted")
.finish_non_exhaustive()
}
}
pub struct VerifyPeerIdentity<Side: SideData, T: Transport> {
conn: Connection<Side, T>,
verify_identity: Box<dyn VerifySidePeerIdentity<Side>>,
}
impl<Side: SideData, T: Transport> VerifyPeerIdentity<Side, T> {
pub fn presented_identity(&self) -> Result<Side::PeerIdentity<'_>, Error> {
self.verify_identity
.presented_identity()
}
}
impl<Side: SideData> VerifyPeerIdentity<Side, Tcp> {
pub fn with_config(self, tls: &mut Vec<u8>) -> Result<Side::Handshake, Error> {
let result = self
.verify_identity
.verify_with_config();
self.continue_with(result, tls)
}
pub fn continue_with(
self,
verification_result: Result<VerifiedIdentity<'static>, Error>,
tls: &mut Vec<u8>,
) -> Result<Side::Handshake, Error> {
self.partial_continue_with(verification_result, tls)?
.into_handshake()
}
}
impl<Side: SideData> VerifyPeerIdentity<Side, Quic> {
pub fn with_config(self, output: &mut Vec<QuicEvent>) -> Result<Side::QuicHandshake, Error> {
let result = self
.verify_identity
.verify_with_config();
self.continue_with(result, output)
}
pub fn continue_with(
self,
verification_result: Result<VerifiedIdentity<'static>, Error>,
output: &mut Vec<QuicEvent>,
) -> Result<Side::QuicHandshake, Error> {
Side::QuicHandshake::from_conn(
self.partial_continue_with(verification_result, &mut Vec::new())?,
output,
)
}
}
impl<Side: SideData, T: Transport> VerifyPeerIdentity<Side, T> {
fn partial_continue_with(
self,
verification_result: Result<VerifiedIdentity<'static>, Error>,
tls: &mut Vec<u8>,
) -> Result<Connection<Side, T>, Error> {
let Self {
mut conn,
verify_identity,
} = self;
let result = verification_result.and_then(|verified| {
verify_identity.continue_with(
verified,
&mut SideCommonOutput {
side: &mut conn.side,
quic: T::quic(&mut conn.transport),
common: &mut conn.common,
tls,
},
)
});
if let Err(err) = &result {
maybe_send_fatal_alert(&mut conn.common.send, err, tls)?;
}
conn.state = result;
Ok(conn)
}
}
impl<Side: SideData, T: Transport> fmt::Debug for VerifyPeerIdentity<Side, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("VerifyPeerIdentity")
.finish_non_exhaustive()
}
}
#[expect(private_bounds)]
pub trait Transport: Sized + sealed::Transport {}
pub(crate) mod sealed {
use super::QuicOutput;
use crate::Protocol;
pub(crate) trait Transport {
fn protocol(&self) -> Protocol;
fn quic(&mut self) -> Option<&mut dyn QuicOutput>;
}
}
#[expect(clippy::exhaustive_structs)]
pub struct Tcp;
impl Transport for Tcp {}
impl sealed::Transport for Tcp {
fn protocol(&self) -> Protocol {
Protocol::Tcp
}
fn quic(&mut self) -> Option<&mut dyn QuicOutput> {
None
}
}