in bindings/rust/extended/s2n-tls/src/renegotiate.rs [988:1062]
fn scheduled_renegotiate_with_async_callback() -> Result<(), Box<dyn Error>> {
// To test how renegotiate handles blocking on async callbacks,
// we need an async callback that triggers on the client.
// Currently our only option is the async pkey callback.
struct TestAsyncCallback {
count: usize,
op: Option<PrivateKeyOperation>,
}
impl PrivateKeyCallback for TestAsyncCallback {
fn handle_operation(
&self,
_: &mut Connection,
operation: PrivateKeyOperation,
) -> ConnectionFutureResult {
Ok(Some(Box::pin(TestAsyncCallback {
count: self.count,
op: Some(operation),
})))
}
}
impl ConnectionFuture for TestAsyncCallback {
fn poll(
self: Pin<&mut Self>,
conn: &mut Connection,
ctx: &mut core::task::Context,
) -> Poll<Result<(), crate::error::Error>> {
ctx.waker().wake_by_ref();
let this = self.get_mut();
if this.count > 1 {
// Repeatedly block the handshake in order to verify
// that renegotiate can handle Pending callbacks.
this.count -= 1;
Pending
} else {
// Perform the pkey operation with the selected cert / key pair.
let op = this.op.take().unwrap();
let opt_ptr = op.as_ptr();
let chain_ptr = conn.selected_cert().unwrap().as_ptr();
unsafe {
// SAFETY, mut cast: get_private_key does not modify the
// chain, and it is invalid to modify key through `key_ptr`
let key_ptr = s2n_cert_chain_and_key_get_private_key(chain_ptr as *mut _)
.into_result()?
.as_ptr();
s2n_async_pkey_op_perform(opt_ptr, key_ptr).into_result()?;
s2n_async_pkey_op_apply(opt_ptr, conn.as_ptr()).into_result()?;
}
Ready(Ok(()))
}
}
}
let count_per_handshake = 10;
let async_callback = TestAsyncCallback {
count: count_per_handshake,
op: None,
};
let mut builder = config::Builder::new();
builder.set_renegotiate_callback(RenegotiateResponse::Schedule)?;
builder.set_private_key_callback(async_callback)?;
let mut pair = RenegotiateTestPair::from(builder)?;
let (waker, wake_count) = new_count_waker();
pair.client.set_waker(Some(&waker))?;
pair.handshake().expect("Initial handshake");
assert_eq!(wake_count, count_per_handshake);
pair.send_renegotiate_request()
.expect("Server sends request");
pair.assert_renegotiate()?;
assert_eq!(wake_count, count_per_handshake * 2);
Ok(())
}