Skip to content

Commit

Permalink
rework CastPtr, CastConstPtr, BoxCastPtr, ArcCastPtr
Browse files Browse the repository at this point in the history
This commit reworks the existing `CastPtr`, `CastConstPtr`,
`BoxCastPtr`, and `ArcCastPtr` traits into a new `Castable` trait with
an associated `CastType`, constrained to be a type implementing the new
`CastTypeMarker` trait. Two implementations of this `CastTypeMarker`
trait are offered: `BoxCastTypeMarker` and `ArcCastTypeMarker`.

The net result is that the type system is now able to enforce our
invariant that a single type can't be cast as both an immutable `Arc`
over the underlying Rust type and a mutable `Box` over the underlying
Rust type.

Along the way crate-internal documentation for the traits and associated
free-standing helper `fs`s were reworked for clarity/consistency.
  • Loading branch information
cpu committed Oct 13, 2023
1 parent 9cee787 commit 318c54b
Show file tree
Hide file tree
Showing 6 changed files with 350 additions and 223 deletions.
24 changes: 11 additions & 13 deletions src/acceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use crate::io::{rustls_read_callback, CallbackReader, ReadCallback};
use crate::rslice::{rustls_slice_bytes, rustls_str};
use crate::server::rustls_server_config;
use crate::{
ffi_panic_boundary, rustls_result, try_arc_from_ptr, try_callback, try_mut_from_ptr,
try_ref_from_ptr, BoxCastPtr, CastPtr,
ffi_panic_boundary, free_box, rustls_result, set_boxed_mut_ptr, to_box, to_boxed_mut_ptr,
try_arc_from_ptr, try_callback, try_mut_from_ptr, try_ref_from_ptr, Castable, OwnershipBox,
};
use rustls_result::NullParameter;

Expand Down Expand Up @@ -42,12 +42,11 @@ pub struct rustls_acceptor {
_private: [u8; 0],
}

impl CastPtr for rustls_acceptor {
impl Castable for rustls_acceptor {
type Ownership = OwnershipBox;
type RustType = Acceptor;
}

impl BoxCastPtr for rustls_acceptor {}

/// A parsed ClientHello produced by a rustls_acceptor. It is used to check
/// server name indication (SNI), ALPN protocols, signature schemes, and
/// cipher suites. It can be combined with a rustls_server_config to build a
Expand All @@ -56,12 +55,11 @@ pub struct rustls_accepted {
_private: [u8; 0],
}

impl CastPtr for rustls_accepted {
impl Castable for rustls_accepted {
type Ownership = OwnershipBox;
type RustType = Option<Accepted>;
}

impl BoxCastPtr for rustls_accepted {}

impl rustls_acceptor {
/// Create and return a new rustls_acceptor.
///
Expand All @@ -70,7 +68,7 @@ impl rustls_acceptor {
#[no_mangle]
pub extern "C" fn rustls_acceptor_new() -> *mut rustls_acceptor {
ffi_panic_boundary! {
BoxCastPtr::to_mut_ptr(Acceptor::default())
to_boxed_mut_ptr(Acceptor::default())
}
}

Expand All @@ -84,7 +82,7 @@ impl rustls_acceptor {
#[no_mangle]
pub extern "C" fn rustls_acceptor_free(acceptor: *mut rustls_acceptor) {
ffi_panic_boundary! {
BoxCastPtr::to_box(acceptor);
to_box(acceptor);
}
}

Expand Down Expand Up @@ -185,7 +183,7 @@ impl rustls_acceptor {
Ok(None) => rustls_result::AcceptorNotReady,
Err(e) => map_error(e),
Ok(Some(accepted)) => {
BoxCastPtr::set_mut_ptr(out_accepted, Some(accepted));
set_boxed_mut_ptr(out_accepted, Some(accepted));
rustls_result::Ok
}
}
Expand Down Expand Up @@ -408,7 +406,7 @@ impl rustls_accepted {
match accepted.into_connection(config) {
Ok(built) => {
let wrapped = crate::connection::Connection::from_server(built);
BoxCastPtr::set_mut_ptr(out_conn, wrapped);
set_boxed_mut_ptr(out_conn, wrapped);
rustls_result::Ok
},
Err(e) => map_error(e),
Expand All @@ -426,7 +424,7 @@ impl rustls_accepted {
#[no_mangle]
pub extern "C" fn rustls_accepted_free(accepted: *mut rustls_accepted) {
ffi_panic_boundary! {
BoxCastPtr::to_box(accepted);
free_box(accepted);
}
}
}
Expand Down
59 changes: 28 additions & 31 deletions src/cipher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ use rustls_pemfile::{certs, crls, pkcs8_private_keys, rsa_private_keys};
use crate::error::{map_error, rustls_result};
use crate::rslice::{rustls_slice_bytes, rustls_str};
use crate::{
ffi_panic_boundary, try_box_from_ptr, try_mut_from_ptr, try_ref_from_ptr, try_slice,
ArcCastPtr, BoxCastPtr, CastConstPtr, CastPtr,
ffi_panic_boundary, free_arc, to_arc_const_ptr, to_boxed_mut_ptr, try_box_from_ptr,
try_mut_from_ptr, try_ref_from_ptr, try_slice, Castable, OwnershipArc, OwnershipBox,
OwnershipRef,
};
use rustls_result::{AlreadyUsed, NullParameter};

Expand All @@ -33,7 +34,8 @@ pub struct rustls_certificate {
_private: [u8; 0],
}

impl CastPtr for rustls_certificate {
impl Castable for rustls_certificate {
type Ownership = OwnershipRef;
type RustType = Certificate;
}

Expand Down Expand Up @@ -66,7 +68,8 @@ pub struct rustls_supported_ciphersuite {
_private: [u8; 0],
}

impl CastPtr for rustls_supported_ciphersuite {
impl Castable for rustls_supported_ciphersuite {
type Ownership = OwnershipRef;
type RustType = SupportedCipherSuite;
}

Expand Down Expand Up @@ -262,12 +265,11 @@ pub struct rustls_certified_key {
_private: [u8; 0],
}

impl CastPtr for rustls_certified_key {
impl Castable for rustls_certified_key {
type Ownership = OwnershipArc;
type RustType = CertifiedKey;
}

impl ArcCastPtr for rustls_certified_key {}

impl rustls_certified_key {
/// Build a `rustls_certified_key` from a certificate chain and a private key.
/// `cert_chain` must point to a buffer of `cert_chain_len` bytes, containing
Expand Down Expand Up @@ -366,7 +368,7 @@ impl rustls_certified_key {
} else {
new_key.ocsp = None;
}
*cloned_key_out = ArcCastPtr::to_const_ptr(new_key);
*cloned_key_out = to_arc_const_ptr(new_key);
rustls_result::Ok
}
}
Expand All @@ -380,7 +382,7 @@ impl rustls_certified_key {
#[no_mangle]
pub extern "C" fn rustls_certified_key_free(key: *const rustls_certified_key) {
ffi_panic_boundary! {
rustls_certified_key::free(key);
free_arc(key);
}
}

Expand Down Expand Up @@ -443,12 +445,11 @@ pub struct rustls_root_cert_store {
_private: [u8; 0],
}

impl CastPtr for rustls_root_cert_store {
impl Castable for rustls_root_cert_store {
type Ownership = OwnershipBox;
type RustType = RootCertStore;
}

impl BoxCastPtr for rustls_root_cert_store {}

impl rustls_root_cert_store {
/// Create a rustls_root_cert_store. Caller owns the memory and must
/// eventually call rustls_root_cert_store_free. The store starts out empty.
Expand All @@ -458,7 +459,7 @@ impl rustls_root_cert_store {
pub extern "C" fn rustls_root_cert_store_new() -> *mut rustls_root_cert_store {
ffi_panic_boundary! {
let store = rustls::RootCertStore::empty();
BoxCastPtr::to_mut_ptr(store)
to_boxed_mut_ptr(store)
}
}

Expand Down Expand Up @@ -517,14 +518,13 @@ pub struct rustls_allow_any_authenticated_client_builder {
_private: [u8; 0],
}

impl CastPtr for rustls_allow_any_authenticated_client_builder {
// NOTE: contained value is consumed even on error, so this can contain None. but the caller
impl Castable for rustls_allow_any_authenticated_client_builder {
type Ownership = OwnershipBox;
// NOTE: contained value is consumed even on error, so this can contain None, but the caller
// still needs to free it
type RustType = Option<AllowAnyAuthenticatedClient>;
}

impl BoxCastPtr for rustls_allow_any_authenticated_client_builder {}

impl rustls_allow_any_authenticated_client_builder {
/// Create a new allow any authenticated client certificate verifier builder using the root store.
///
Expand All @@ -542,7 +542,7 @@ impl rustls_allow_any_authenticated_client_builder {
ffi_panic_boundary! {
let store: &RootCertStore = try_ref_from_ptr!(store);
let client_cert_verifier = Some(AllowAnyAuthenticatedClient::new(store.clone()));
BoxCastPtr::to_mut_ptr(client_cert_verifier)
to_boxed_mut_ptr(client_cert_verifier)
}
}

Expand Down Expand Up @@ -604,12 +604,11 @@ pub struct rustls_allow_any_authenticated_client_verifier {
_private: [u8; 0],
}

impl CastConstPtr for rustls_allow_any_authenticated_client_verifier {
impl Castable for rustls_allow_any_authenticated_client_verifier {
type Ownership = OwnershipArc;
type RustType = AllowAnyAuthenticatedClient;
}

impl ArcCastPtr for rustls_allow_any_authenticated_client_verifier {}

impl rustls_allow_any_authenticated_client_verifier {
/// Create a new allow any authenticated client certificate verifier from a builder.
///
Expand Down Expand Up @@ -649,7 +648,7 @@ impl rustls_allow_any_authenticated_client_verifier {
verifier: *const rustls_allow_any_authenticated_client_verifier,
) {
ffi_panic_boundary! {
rustls_allow_any_authenticated_client_verifier::free(verifier);
free_arc(verifier);
}
}
}
Expand All @@ -661,14 +660,13 @@ pub struct rustls_allow_any_anonymous_or_authenticated_client_builder {
_private: [u8; 0],
}

impl CastPtr for rustls_allow_any_anonymous_or_authenticated_client_builder {
// NOTE: contained value is consumed even on error, so this can contain None. but the caller
impl Castable for rustls_allow_any_anonymous_or_authenticated_client_builder {
type Ownership = OwnershipBox;
// NOTE: contained value is consumed even on error, so this can contain None, but the caller
// still needs to free it
type RustType = Option<AllowAnyAnonymousOrAuthenticatedClient>;
}

impl BoxCastPtr for rustls_allow_any_anonymous_or_authenticated_client_builder {}

impl rustls_allow_any_anonymous_or_authenticated_client_builder {
/// Create a new allow any anonymous or authenticated client certificate verifier builder
/// using the root store.
Expand All @@ -688,7 +686,7 @@ impl rustls_allow_any_anonymous_or_authenticated_client_builder {
ffi_panic_boundary! {
let store: &RootCertStore = try_ref_from_ptr!(store);
let client_cert_verifier = Some(AllowAnyAnonymousOrAuthenticatedClient::new(store.clone()));
BoxCastPtr::to_mut_ptr(client_cert_verifier)
to_boxed_mut_ptr(client_cert_verifier)
}
}

Expand Down Expand Up @@ -753,12 +751,11 @@ pub struct rustls_allow_any_anonymous_or_authenticated_client_verifier {
_private: [u8; 0],
}

impl CastConstPtr for rustls_allow_any_anonymous_or_authenticated_client_verifier {
impl Castable for rustls_allow_any_anonymous_or_authenticated_client_verifier {
type Ownership = OwnershipArc;
type RustType = AllowAnyAnonymousOrAuthenticatedClient;
}

impl ArcCastPtr for rustls_allow_any_anonymous_or_authenticated_client_verifier {}

impl rustls_allow_any_anonymous_or_authenticated_client_verifier {
/// Create a new allow any anonymous or authenticated client certificate verifier builder
/// from the builder.
Expand Down Expand Up @@ -799,7 +796,7 @@ impl rustls_allow_any_anonymous_or_authenticated_client_verifier {
verifier: *const rustls_allow_any_anonymous_or_authenticated_client_verifier,
) {
ffi_panic_boundary! {
rustls_allow_any_anonymous_or_authenticated_client_verifier::free(verifier);
free_arc(verifier);
}
}
}
27 changes: 13 additions & 14 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ use crate::error::{self, rustls_result};
use crate::rslice::NulByte;
use crate::rslice::{rustls_slice_bytes, rustls_slice_slice_bytes, rustls_str};
use crate::{
ffi_panic_boundary, try_arc_from_ptr, try_box_from_ptr, try_mut_from_ptr, try_ref_from_ptr,
try_slice, userdata_get, ArcCastPtr, BoxCastPtr, CastConstPtr, CastPtr,
ffi_panic_boundary, free_arc, free_box, set_boxed_mut_ptr, to_arc_const_ptr, to_boxed_mut_ptr,
try_arc_from_ptr, try_box_from_ptr, try_mut_from_ptr, try_ref_from_ptr, try_slice,
userdata_get, Castable, OwnershipArc, OwnershipBox,
};

/// A client config being constructed. A builder can be modified by,
Expand All @@ -47,12 +48,11 @@ pub(crate) struct ClientConfigBuilder {
cert_resolver: Option<Arc<dyn rustls::client::ResolvesClientCert>>,
}

impl CastPtr for rustls_client_config_builder {
impl Castable for rustls_client_config_builder {
type Ownership = OwnershipBox;
type RustType = ClientConfigBuilder;
}

impl BoxCastPtr for rustls_client_config_builder {}

/// A client config that is done being constructed and is now read-only.
/// Under the hood, this object corresponds to an `Arc<ClientConfig>`.
/// <https://docs.rs/rustls/latest/rustls/struct.ClientConfig.html>
Expand All @@ -63,12 +63,11 @@ pub struct rustls_client_config {
_private: [u8; 0],
}

impl CastConstPtr for rustls_client_config {
impl Castable for rustls_client_config {
type Ownership = OwnershipArc;
type RustType = ClientConfig;
}

impl ArcCastPtr for rustls_client_config {}

struct NoneVerifier;

impl ServerCertVerifier for NoneVerifier {
Expand Down Expand Up @@ -106,7 +105,7 @@ impl rustls_client_config_builder {
alpn_protocols: vec![],
enable_sni: true,
};
BoxCastPtr::to_mut_ptr(builder)
to_boxed_mut_ptr(builder)
}
}

Expand Down Expand Up @@ -169,7 +168,7 @@ impl rustls_client_config_builder {
enable_sni: true,
};

BoxCastPtr::set_mut_ptr(builder_out, config_builder);
set_boxed_mut_ptr(builder_out, config_builder);
rustls_result::Ok
}
}
Expand Down Expand Up @@ -492,7 +491,7 @@ impl rustls_client_config_builder {
};
config.alpn_protocols = builder.alpn_protocols;
config.enable_sni = builder.enable_sni;
ArcCastPtr::to_const_ptr(config)
to_arc_const_ptr(config)
}
}

Expand All @@ -504,7 +503,7 @@ impl rustls_client_config_builder {
#[no_mangle]
pub extern "C" fn rustls_client_config_builder_free(config: *mut rustls_client_config_builder) {
ffi_panic_boundary! {
BoxCastPtr::to_box(config);
free_box(config);
}
}
}
Expand All @@ -519,7 +518,7 @@ impl rustls_client_config {
#[no_mangle]
pub extern "C" fn rustls_client_config_free(config: *const rustls_client_config) {
ffi_panic_boundary! {
rustls_client_config::free(config);
free_arc(config);
}
}

Expand Down Expand Up @@ -561,7 +560,7 @@ impl rustls_client_config {
// to the caller. After this point, we must return rustls_result::Ok so the
// caller knows it is responsible for this memory.
let c = Connection::from_client(client);
BoxCastPtr::set_mut_ptr(conn_out, c);
set_boxed_mut_ptr(conn_out, c);
rustls_result::Ok
}
}
Expand Down
Loading

0 comments on commit 318c54b

Please sign in to comment.