in quic/s2n-quic-rustls/src/session.rs [232:336]
fn poll_impl<C: tls::Context<Self>>(
&mut self,
context: &mut C,
) -> Poll<Result<(), transport::Error>> {
// Tracks if we have attempted to receive data at least once
let mut has_tried_receive = false;
loop {
let crypto_data = match self.rx_phase {
HandshakePhase::Initial => context.receive_initial(None),
HandshakePhase::Handshake => context.receive_handshake(None),
HandshakePhase::Application => context.receive_application(None),
};
// receive anything in the incoming buffer
if let Some(crypto_data) = crypto_data {
self.receive(&crypto_data)?;
} else if has_tried_receive {
return self.poll_complete_handshake(context);
// If there's nothing to receive then we're done for now
}
if let Poll::Ready(()) = self.poll_complete_handshake(context)? {
return Poll::Ready(Ok(()));
}
// mark that we tried to receive some data so we know next time we loop
// to bail if nothing changed
has_tried_receive = true;
// try to pull out the early secrets, if any
if let Some(keys) = self.zero_rtt_keys() {
let (key, header_key) = PacketKey::new(
keys,
s2n_quic_core::crypto::tls::CipherSuite::TLS_AES_128_GCM_SHA256,
);
context.on_zero_rtt_keys(key, header_key, self.application_parameters()?)?;
}
loop {
// make sure we can send data before pulling it out of rustls
let can_send = match self.tx_phase {
HandshakePhase::Initial => context.can_send_initial(),
HandshakePhase::Handshake => context.can_send_handshake(),
HandshakePhase::Application => context.can_send_application(),
};
if !can_send {
break;
}
let mut transmission_buffer = vec![];
let key_change = self.connection.write_hs(&mut transmission_buffer);
// if we didn't upgrade the key or transmit anything then we're waiting for
// more reads
if key_change.is_none() && transmission_buffer.is_empty() {
break;
}
// fill the correct buffer according to the handshake phase
match self.tx_phase {
HandshakePhase::Initial => context.send_initial(transmission_buffer.into()),
HandshakePhase::Handshake => context.send_handshake(transmission_buffer.into()),
HandshakePhase::Application => {
context.send_application(transmission_buffer.into())
}
}
if let Some(key_change) = key_change {
let cipher_suite = self
.connection
.negotiated_cipher_suite()
.expect("cipher_suite should be negotiated")
.suite();
match key_change {
quic::KeyChange::Handshake { keys } => {
let (key, header_key) = PacketKeys::new(keys, cipher_suite);
context.on_handshake_keys(key, header_key)?;
// Transition both phases to Handshake
self.tx_phase.transition();
self.rx_phase.transition();
}
quic::KeyChange::OneRtt { keys, next } => {
let (key, header_key) = OneRttKey::new(keys, next, cipher_suite);
// at this point we should have both SNI and ALPN values
self.emit_events(context)?;
let application_parameters = self.application_parameters()?;
context.on_one_rtt_keys(key, header_key, application_parameters)?;
// Transition the tx_phase to Application
// Note: the rx_phase is transitioned when the handshake is complete
self.tx_phase.transition();
}
}
}
}
}
}