use alloc::boxed::Box;
use core::marker::PhantomData;
use crate::client::ClientConnectionData;
use crate::common_state::Protocol;
use crate::msgs::codec::Codec;
use crate::msgs::handshake::{CertificateChain, NewSessionTicketPayloadTls13};
use crate::quic::Quic;
use crate::{CommonState, ConnectionTrafficSecrets, Error, ProtocolVersion, SupportedCipherSuite};
pub struct KernelConnection<Data> {
state: Box<dyn KernelState>,
peer_certificates: Option<CertificateChain<'static>>,
quic: Quic,
negotiated_version: ProtocolVersion,
protocol: Protocol,
suite: SupportedCipherSuite,
_data: PhantomData<Data>,
}
impl<Data> KernelConnection<Data> {
pub(crate) fn new(state: Box<dyn KernelState>, common: CommonState) -> Result<Self, Error> {
Ok(Self {
state,
peer_certificates: common.peer_certificates,
quic: common.quic,
negotiated_version: common
.negotiated_version
.ok_or(Error::HandshakeNotComplete)?,
protocol: common.protocol,
suite: common
.suite
.ok_or(Error::HandshakeNotComplete)?,
_data: PhantomData,
})
}
pub fn negotiated_cipher_suite(&self) -> SupportedCipherSuite {
self.suite
}
pub fn protocol_version(&self) -> ProtocolVersion {
self.negotiated_version
}
pub fn update_tx_secret(&mut self) -> Result<(u64, ConnectionTrafficSecrets), Error> {
self.state
.update_secrets(Direction::Transmit)
.map(|secret| (0, secret))
}
pub fn update_rx_secret(&mut self) -> Result<(u64, ConnectionTrafficSecrets), Error> {
self.state
.update_secrets(Direction::Receive)
.map(|secret| (0, secret))
}
}
impl KernelConnection<ClientConnectionData> {
pub fn handle_new_session_ticket(&mut self, payload: &[u8]) -> Result<(), Error> {
if self.protocol_version() != ProtocolVersion::TLSv1_3 {
return Err(Error::General(
"TLS 1.2 session tickets may not be sent once the handshake has completed".into(),
));
}
let nst = NewSessionTicketPayloadTls13::read_bytes(payload)?;
let mut cx = KernelContext {
peer_certificates: self.peer_certificates.as_ref(),
protocol: self.protocol,
quic: &self.quic,
};
self.state
.handle_new_session_ticket(&mut cx, &nst)
}
}
pub(crate) trait KernelState: Send + Sync {
fn update_secrets(&mut self, dir: Direction) -> Result<ConnectionTrafficSecrets, Error>;
fn handle_new_session_ticket(
&mut self,
cx: &mut KernelContext<'_>,
message: &NewSessionTicketPayloadTls13,
) -> Result<(), Error>;
}
pub(crate) struct KernelContext<'a> {
pub(crate) peer_certificates: Option<&'a CertificateChain<'static>>,
pub(crate) protocol: Protocol,
pub(crate) quic: &'a Quic,
}
impl KernelContext<'_> {
pub(crate) fn is_quic(&self) -> bool {
self.protocol == Protocol::Quic
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum Direction {
Transmit,
Receive,
}