Skip to content

Commit 7da8ff9

Browse files
committed
arc_castable!, box_castable!, ref_castable! macros
Throughout the project we follow a pattern of: 1. Creating a `snake_case_named` opaque struct[0]. 2. Implementing `Castable` for the struct: a. specifying a `RustType` (some native Rust type). b. specifying an `Ownership` (`OwnershipBox`, `OwnershipArc`, `OwnershipRef`). In the case of `OwnershipRef` we may also need to add a `PhantomData` field referencing a lifetime to the opaque struct. To reduce the boilerplate of doing all of the above over and over this commit adds three new macros that accomplish the task with less ceremony: `arc_castable!`, `box_castable!`, and `ref_castable!`. Existing instances of the pattern are updated to use these macros with one exception: the `rustls_client_hello` type implements `Castable` with `OwnershipRef` for `rustls_client_hello<'a>`, but it isn't the same opaque struct pattern as used elsewhere and so is best implemented by hand. [0]: https://github.com/rustls/rustls-ffi/blob/main/CONTRIBUTING.md#opaque-struct-pattern
1 parent 7cbc457 commit 7da8ff9

File tree

6 files changed

+239
-224
lines changed

6 files changed

+239
-224
lines changed

src/acceptor.rs

Lines changed: 36 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -12,53 +12,43 @@ use crate::io::{
1212
use crate::rslice::{rustls_slice_bytes, rustls_str};
1313
use crate::server::rustls_server_config;
1414
use crate::{
15-
ffi_panic_boundary, free_box, rustls_result, set_boxed_mut_ptr, to_box, to_boxed_mut_ptr,
16-
try_callback, try_clone_arc, try_mut_from_ptr, try_mut_from_ptr_ptr, try_ref_from_ptr,
17-
try_take, Castable, OwnershipBox,
15+
box_castable, ffi_panic_boundary, free_box, rustls_result, set_boxed_mut_ptr, to_box,
16+
to_boxed_mut_ptr, try_callback, try_clone_arc, try_mut_from_ptr, try_mut_from_ptr_ptr,
17+
try_ref_from_ptr, try_take,
1818
};
1919

20-
/// A buffer and parser for ClientHello bytes. This allows reading ClientHello
21-
/// before choosing a rustls_server_config. It's useful when the server
22-
/// config will be based on parameters in the ClientHello: server name
23-
/// indication (SNI), ALPN protocols, signature schemes, and cipher suites. In
24-
/// particular, if a server wants to do some potentially expensive work to load a
25-
/// certificate for a given hostname, rustls_acceptor allows doing that asynchronously,
26-
/// as opposed to rustls_server_config_builder_set_hello_callback(), which doesn't
27-
/// work well for asynchronous I/O.
28-
///
29-
/// The general flow is:
30-
/// - rustls_acceptor_new()
31-
/// - Loop:
32-
/// - Read bytes from the network it with rustls_acceptor_read_tls().
33-
/// - If successful, parse those bytes with rustls_acceptor_accept().
34-
/// - If that returns RUSTLS_RESULT_ACCEPTOR_NOT_READY, continue.
35-
/// - Otherwise, break.
36-
/// - If rustls_acceptor_accept() returned RUSTLS_RESULT_OK:
37-
/// - Examine the resulting rustls_accepted.
38-
/// - Create or select a rustls_server_config.
39-
/// - Call rustls_accepted_into_connection().
40-
/// - Otherwise, there was a problem with the ClientHello data and the
41-
/// connection should be rejected.
42-
pub struct rustls_acceptor {
43-
_private: [u8; 0],
20+
box_castable! {
21+
/// A buffer and parser for ClientHello bytes. This allows reading ClientHello
22+
/// before choosing a rustls_server_config. It's useful when the server
23+
/// config will be based on parameters in the ClientHello: server name
24+
/// indication (SNI), ALPN protocols, signature schemes, and cipher suites. In
25+
/// particular, if a server wants to do some potentially expensive work to load a
26+
/// certificate for a given hostname, rustls_acceptor allows doing that asynchronously,
27+
/// as opposed to rustls_server_config_builder_set_hello_callback(), which doesn't
28+
/// work well for asynchronous I/O.
29+
///
30+
/// The general flow is:
31+
/// - rustls_acceptor_new()
32+
/// - Loop:
33+
/// - Read bytes from the network it with rustls_acceptor_read_tls().
34+
/// - If successful, parse those bytes with rustls_acceptor_accept().
35+
/// - If that returns RUSTLS_RESULT_ACCEPTOR_NOT_READY, continue.
36+
/// - Otherwise, break.
37+
/// - If rustls_acceptor_accept() returned RUSTLS_RESULT_OK:
38+
/// - Examine the resulting rustls_accepted.
39+
/// - Create or select a rustls_server_config.
40+
/// - Call rustls_accepted_into_connection().
41+
/// - Otherwise, there was a problem with the ClientHello data and the
42+
/// connection should be rejected.
43+
pub struct rustls_acceptor(Acceptor);
4444
}
4545

46-
impl Castable for rustls_acceptor {
47-
type Ownership = OwnershipBox;
48-
type RustType = Acceptor;
49-
}
50-
51-
/// A parsed ClientHello produced by a rustls_acceptor. It is used to check
52-
/// server name indication (SNI), ALPN protocols, signature schemes, and
53-
/// cipher suites. It can be combined with a rustls_server_config to build a
54-
/// rustls_connection.
55-
pub struct rustls_accepted {
56-
_private: [u8; 0],
57-
}
58-
59-
impl Castable for rustls_accepted {
60-
type Ownership = OwnershipBox;
61-
type RustType = Option<Accepted>;
46+
box_castable! {
47+
/// A parsed ClientHello produced by a rustls_acceptor. It is used to check
48+
/// server name indication (SNI), ALPN protocols, signature schemes, and
49+
/// cipher suites. It can be combined with a rustls_server_config to build a
50+
/// rustls_connection.
51+
pub struct rustls_accepted(Option<Accepted>);
6252
}
6353

6454
impl rustls_acceptor {
@@ -452,14 +442,9 @@ impl rustls_accepted {
452442
}
453443
}
454444

455-
/// Represents a TLS alert resulting from accepting a client.
456-
pub struct rustls_accepted_alert {
457-
_private: [u8; 0],
458-
}
459-
460-
impl Castable for rustls_accepted_alert {
461-
type Ownership = OwnershipBox;
462-
type RustType = AcceptedAlert;
445+
box_castable! {
446+
/// Represents a TLS alert resulting from accepting a client.
447+
pub struct rustls_accepted_alert(AcceptedAlert);
463448
}
464449

465450
impl rustls_accepted_alert {

src/cipher.rs

Lines changed: 68 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,18 @@ use webpki::{RevocationCheckDepth, UnknownStatusPolicy};
2121
use crate::error::{self, rustls_result};
2222
use crate::rslice::{rustls_slice_bytes, rustls_str};
2323
use crate::{
24-
ffi_panic_boundary, free_arc, free_box, set_arc_mut_ptr, set_boxed_mut_ptr, to_arc_const_ptr,
25-
to_boxed_mut_ptr, try_clone_arc, try_mut_from_ptr, try_mut_from_ptr_ptr, try_ref_from_ptr,
26-
try_ref_from_ptr_ptr, try_slice, try_take, Castable, OwnershipArc, OwnershipBox, OwnershipRef,
24+
arc_castable, box_castable, ffi_panic_boundary, free_arc, free_box, ref_castable,
25+
set_arc_mut_ptr, set_boxed_mut_ptr, to_arc_const_ptr, to_boxed_mut_ptr, try_clone_arc,
26+
try_mut_from_ptr, try_mut_from_ptr_ptr, try_ref_from_ptr, try_ref_from_ptr_ptr, try_slice,
27+
try_take,
2728
};
2829
use rustls_result::{AlreadyUsed, NullParameter};
2930

30-
/// An X.509 certificate, as used in rustls.
31-
/// Corresponds to `CertificateDer` in the Rust pki-types API.
32-
/// <https://docs.rs/rustls-pki-types/latest/rustls_pki_types/struct.CertificateDer.html>
33-
pub struct rustls_certificate<'a> {
34-
_private: [u8; 0],
35-
_marker: PhantomData<&'a ()>,
36-
}
37-
38-
impl<'a> Castable for rustls_certificate<'a> {
39-
type Ownership = OwnershipRef;
40-
type RustType = CertificateDer<'a>;
31+
ref_castable! {
32+
/// An X.509 certificate, as used in rustls.
33+
/// Corresponds to `CertificateDer` in the Rust pki-types API.
34+
/// <https://docs.rs/rustls-pki-types/latest/rustls_pki_types/struct.CertificateDer.html>
35+
pub struct rustls_certificate(CertificateDer<'a>);
4136
}
4237

4338
/// Get the DER data of the certificate itself.
@@ -62,14 +57,9 @@ pub extern "C" fn rustls_certificate_get_der(
6257
}
6358
}
6459

65-
/// A cipher suite supported by rustls.
66-
pub struct rustls_supported_ciphersuite {
67-
_private: [u8; 0],
68-
}
69-
70-
impl Castable for rustls_supported_ciphersuite {
71-
type Ownership = OwnershipRef;
72-
type RustType = SupportedCipherSuite;
60+
ref_castable! {
61+
/// A cipher suite supported by rustls.
62+
pub struct rustls_supported_ciphersuite(SupportedCipherSuite);
7363
}
7464

7565
impl rustls_supported_ciphersuite {
@@ -207,17 +197,12 @@ pub static mut RUSTLS_DEFAULT_CIPHER_SUITES: [*const rustls_supported_ciphersuit
207197
#[no_mangle]
208198
pub static RUSTLS_DEFAULT_CIPHER_SUITES_LEN: usize = unsafe { RUSTLS_DEFAULT_CIPHER_SUITES.len() };
209199

210-
/// The complete chain of certificates to send during a TLS handshake,
211-
/// plus a private key that matches the end-entity (leaf) certificate.
212-
/// Corresponds to `CertifiedKey` in the Rust API.
213-
/// <https://docs.rs/rustls/latest/rustls/sign/struct.CertifiedKey.html>
214-
pub struct rustls_certified_key {
215-
_private: [u8; 0],
216-
}
217-
218-
impl Castable for rustls_certified_key {
219-
type Ownership = OwnershipArc;
220-
type RustType = CertifiedKey;
200+
arc_castable! {
201+
/// The complete chain of certificates to send during a TLS handshake,
202+
/// plus a private key that matches the end-entity (leaf) certificate.
203+
/// Corresponds to `CertifiedKey` in the Rust API.
204+
/// <https://docs.rs/rustls/latest/rustls/sign/struct.CertifiedKey.html>
205+
pub struct rustls_certified_key(CertifiedKey);
221206
}
222207

223208
impl rustls_certified_key {
@@ -385,25 +370,20 @@ impl rustls_certified_key {
385370
}
386371
}
387372

388-
/// A `rustls_root_cert_store` being constructed.
389-
///
390-
/// A builder can be modified by adding trust anchor root certificates with
391-
/// `rustls_root_cert_store_builder_add_pem`. Once you're done adding root certificates,
392-
/// call `rustls_root_cert_store_builder_build` to turn it into a `rustls_root_cert_store`.
393-
/// This object is not safe for concurrent mutation.
394-
pub struct rustls_root_cert_store_builder {
395-
_private: [u8; 0],
373+
box_castable! {
374+
/// A `rustls_root_cert_store` being constructed.
375+
///
376+
/// A builder can be modified by adding trust anchor root certificates with
377+
/// `rustls_root_cert_store_builder_add_pem`. Once you're done adding root certificates,
378+
/// call `rustls_root_cert_store_builder_build` to turn it into a `rustls_root_cert_store`.
379+
/// This object is not safe for concurrent mutation.
380+
pub struct rustls_root_cert_store_builder(Option<RootCertStoreBuilder>);
396381
}
397382

398383
pub(crate) struct RootCertStoreBuilder {
399384
roots: RootCertStore,
400385
}
401386

402-
impl Castable for rustls_root_cert_store_builder {
403-
type Ownership = OwnershipBox;
404-
type RustType = Option<RootCertStoreBuilder>;
405-
}
406-
407387
impl rustls_root_cert_store_builder {
408388
/// Create a `rustls_root_cert_store_builder`.
409389
///
@@ -562,15 +542,10 @@ impl rustls_root_cert_store_builder {
562542
}
563543
}
564544

565-
/// A root certificate store.
566-
/// <https://docs.rs/rustls/latest/rustls/struct.RootCertStore.html>
567-
pub struct rustls_root_cert_store {
568-
_private: [u8; 0],
569-
}
570-
571-
impl Castable for rustls_root_cert_store {
572-
type Ownership = OwnershipArc;
573-
type RustType = RootCertStore;
545+
arc_castable! {
546+
/// A root certificate store.
547+
/// <https://docs.rs/rustls/latest/rustls/struct.RootCertStore.html>
548+
pub struct rustls_root_cert_store(RootCertStore);
574549
}
575550

576551
impl rustls_root_cert_store {
@@ -584,19 +559,15 @@ impl rustls_root_cert_store {
584559
}
585560
}
586561

587-
/// A built client certificate verifier that can be provided to a `rustls_server_config_builder`
588-
/// with `rustls_server_config_builder_set_client_verifier`.
589-
pub struct rustls_client_cert_verifier {
590-
_private: [u8; 0],
591-
}
592-
593-
/// Rustls' ConfigBuilder requires an `Arc<dyn ClientCertVerifier>` here, meaning we
594-
/// must follow the pattern described in CONTRIBUTING.md[0] for handling dynamically sized
595-
/// types (DSTs) across the FFI boundary.
596-
/// [0] <https://github.com/rustls/rustls-ffi/blob/main/CONTRIBUTING.md#dynamically-sized-types>
597-
impl Castable for rustls_client_cert_verifier {
598-
type Ownership = OwnershipBox;
599-
type RustType = Arc<dyn ClientCertVerifier>;
562+
box_castable! {
563+
/// A built client certificate verifier that can be provided to a `rustls_server_config_builder`
564+
/// with `rustls_server_config_builder_set_client_verifier`.
565+
//
566+
// Rustls' ConfigBuilder requires an `Arc<dyn ClientCertVerifier>` here, meaning we
567+
// must follow the pattern described in CONTRIBUTING.md[^0] for handling dynamically sized
568+
// types (DSTs) across the FFI boundary.
569+
// [^0]: <https://github.com/rustls/rustls-ffi/blob/main/CONTRIBUTING.md#dynamically-sized-types>
570+
pub struct rustls_client_cert_verifier(Arc<dyn ClientCertVerifier>);
600571
}
601572

602573
impl rustls_client_cert_verifier {
@@ -611,18 +582,6 @@ impl rustls_client_cert_verifier {
611582
}
612583
}
613584

614-
/// A client certificate verifier being constructed. A builder can be modified by,
615-
/// e.g. `rustls_web_pki_client_cert_verifier_builder_add_crl`. Once you're
616-
/// done configuring settings, call `rustls_web_pki_client_cert_verifier_builder_build`
617-
/// to turn it into a `rustls_client_cert_verifier`. This object is not safe
618-
/// for concurrent mutation.
619-
///
620-
/// See <https://docs.rs/rustls/latest/rustls/server/struct.ClientCertVerifierBuilder.html>
621-
/// for more information.
622-
pub struct rustls_web_pki_client_cert_verifier_builder {
623-
_private: [u8; 0],
624-
}
625-
626585
pub(crate) struct ClientCertVerifierBuilder {
627586
roots: Arc<RootCertStore>,
628587
root_hint_subjects: Vec<DistinguishedName>,
@@ -632,9 +591,16 @@ pub(crate) struct ClientCertVerifierBuilder {
632591
allow_unauthenticated: bool,
633592
}
634593

635-
impl Castable for rustls_web_pki_client_cert_verifier_builder {
636-
type Ownership = OwnershipBox;
637-
type RustType = Option<ClientCertVerifierBuilder>;
594+
box_castable! {
595+
/// A client certificate verifier being constructed. A builder can be modified by,
596+
/// e.g. `rustls_web_pki_client_cert_verifier_builder_add_crl`. Once you're
597+
/// done configuring settings, call `rustls_web_pki_client_cert_verifier_builder_build`
598+
/// to turn it into a `rustls_client_cert_verifier`. This object is not safe
599+
/// for concurrent mutation.
600+
///
601+
/// See <https://docs.rs/rustls/latest/rustls/server/struct.ClientCertVerifierBuilder.html>
602+
/// for more information.
603+
pub struct rustls_web_pki_client_cert_verifier_builder(Option<ClientCertVerifierBuilder>);
638604
}
639605

640606
impl rustls_web_pki_client_cert_verifier_builder {
@@ -893,16 +859,16 @@ impl rustls_web_pki_client_cert_verifier_builder {
893859
}
894860
}
895861

896-
/// A server certificate verifier being constructed. A builder can be modified by,
897-
/// e.g. `rustls_web_pki_server_cert_verifier_builder_add_crl`. Once you're
898-
/// done configuring settings, call `rustls_web_pki_server_cert_verifier_builder_build`
899-
/// to turn it into a `rustls_server_cert_verifier`. This object is not safe
900-
/// for concurrent mutation.
901-
///
902-
/// See <https://docs.rs/rustls/latest/rustls/client/struct.ServerCertVerifierBuilder.html>
903-
/// for more information.
904-
pub struct rustls_web_pki_server_cert_verifier_builder {
905-
_private: [u8; 0],
862+
box_castable! {
863+
/// A server certificate verifier being constructed. A builder can be modified by,
864+
/// e.g. `rustls_web_pki_server_cert_verifier_builder_add_crl`. Once you're
865+
/// done configuring settings, call `rustls_web_pki_server_cert_verifier_builder_build`
866+
/// to turn it into a `rustls_server_cert_verifier`. This object is not safe
867+
/// for concurrent mutation.
868+
///
869+
/// See <https://docs.rs/rustls/latest/rustls/client/struct.ServerCertVerifierBuilder.html>
870+
/// for more information.
871+
pub struct rustls_web_pki_server_cert_verifier_builder(Option<ServerCertVerifierBuilder>);
906872
}
907873

908874
pub(crate) struct ServerCertVerifierBuilder {
@@ -912,11 +878,6 @@ pub(crate) struct ServerCertVerifierBuilder {
912878
revocation_policy: UnknownStatusPolicy,
913879
}
914880

915-
impl Castable for rustls_web_pki_server_cert_verifier_builder {
916-
type Ownership = OwnershipBox;
917-
type RustType = Option<ServerCertVerifierBuilder>;
918-
}
919-
920881
impl ServerCertVerifierBuilder {
921882
/// Create a `rustls_web_pki_server_cert_verifier_builder`. Caller owns the memory and may
922883
/// free it with `rustls_web_pki_server_cert_verifier_builder_free`, regardless of whether
@@ -1095,19 +1056,15 @@ impl ServerCertVerifierBuilder {
10951056
}
10961057
}
10971058

1098-
/// A built server certificate verifier that can be provided to a `rustls_client_config_builder`
1099-
/// with `rustls_client_config_builder_set_server_verifier`.
1100-
pub struct rustls_server_cert_verifier {
1101-
_private: [u8; 0],
1102-
}
1103-
1104-
/// Rustls' ConfigBuilder requires an `Arc<dyn ServerCertVerifier>` here, meaning we
1105-
/// must follow the pattern described in CONTRIBUTING.md[0] for handling dynamically sized
1106-
/// types (DSTs) across the FFI boundary.
1107-
/// [0] <https://github.com/rustls/rustls-ffi/blob/main/CONTRIBUTING.md#dynamically-sized-types>
1108-
impl Castable for rustls_server_cert_verifier {
1109-
type Ownership = OwnershipBox;
1110-
type RustType = Arc<dyn ServerCertVerifier>;
1059+
box_castable! {
1060+
/// A built server certificate verifier that can be provided to a `rustls_client_config_builder`
1061+
/// with `rustls_client_config_builder_set_server_verifier`.
1062+
//
1063+
// Rustls' ConfigBuilder requires an `Arc<dyn ServerCertVerifier>` here, meaning we
1064+
// must follow the pattern described in CONTRIBUTING.md[^0] for handling dynamically sized
1065+
// types (DSTs) across the FFI boundary.
1066+
// [^0]: <https://github.com/rustls/rustls-ffi/blob/main/CONTRIBUTING.md#dynamically-sized-types>
1067+
pub struct rustls_server_cert_verifier(Arc<dyn ServerCertVerifier>);
11111068
}
11121069

11131070
impl rustls_server_cert_verifier {

0 commit comments

Comments
 (0)