Skip to content

Commit dd01a1c

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 3a39676 commit dd01a1c

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 {
@@ -257,17 +247,12 @@ mod tests {
257247
}
258248
}
259249

260-
/// The complete chain of certificates to send during a TLS handshake,
261-
/// plus a private key that matches the end-entity (leaf) certificate.
262-
/// Corresponds to `CertifiedKey` in the Rust API.
263-
/// <https://docs.rs/rustls/latest/rustls/sign/struct.CertifiedKey.html>
264-
pub struct rustls_certified_key {
265-
_private: [u8; 0],
266-
}
267-
268-
impl Castable for rustls_certified_key {
269-
type Ownership = OwnershipArc;
270-
type RustType = CertifiedKey;
250+
arc_castable! {
251+
/// The complete chain of certificates to send during a TLS handshake,
252+
/// plus a private key that matches the end-entity (leaf) certificate.
253+
/// Corresponds to `CertifiedKey` in the Rust API.
254+
/// <https://docs.rs/rustls/latest/rustls/sign/struct.CertifiedKey.html>
255+
pub struct rustls_certified_key(CertifiedKey);
271256
}
272257

273258
impl rustls_certified_key {
@@ -435,25 +420,20 @@ impl rustls_certified_key {
435420
}
436421
}
437422

438-
/// A `rustls_root_cert_store` being constructed.
439-
///
440-
/// A builder can be modified by adding trust anchor root certificates with
441-
/// `rustls_root_cert_store_builder_add_pem`. Once you're done adding root certificates,
442-
/// call `rustls_root_cert_store_builder_build` to turn it into a `rustls_root_cert_store`.
443-
/// This object is not safe for concurrent mutation.
444-
pub struct rustls_root_cert_store_builder {
445-
_private: [u8; 0],
423+
box_castable! {
424+
/// A `rustls_root_cert_store` being constructed.
425+
///
426+
/// A builder can be modified by adding trust anchor root certificates with
427+
/// `rustls_root_cert_store_builder_add_pem`. Once you're done adding root certificates,
428+
/// call `rustls_root_cert_store_builder_build` to turn it into a `rustls_root_cert_store`.
429+
/// This object is not safe for concurrent mutation.
430+
pub struct rustls_root_cert_store_builder(Option<RootCertStoreBuilder>);
446431
}
447432

448433
pub(crate) struct RootCertStoreBuilder {
449434
roots: RootCertStore,
450435
}
451436

452-
impl Castable for rustls_root_cert_store_builder {
453-
type Ownership = OwnershipBox;
454-
type RustType = Option<RootCertStoreBuilder>;
455-
}
456-
457437
impl rustls_root_cert_store_builder {
458438
/// Create a `rustls_root_cert_store_builder`.
459439
///
@@ -612,15 +592,10 @@ impl rustls_root_cert_store_builder {
612592
}
613593
}
614594

615-
/// A root certificate store.
616-
/// <https://docs.rs/rustls/latest/rustls/struct.RootCertStore.html>
617-
pub struct rustls_root_cert_store {
618-
_private: [u8; 0],
619-
}
620-
621-
impl Castable for rustls_root_cert_store {
622-
type Ownership = OwnershipArc;
623-
type RustType = RootCertStore;
595+
arc_castable! {
596+
/// A root certificate store.
597+
/// <https://docs.rs/rustls/latest/rustls/struct.RootCertStore.html>
598+
pub struct rustls_root_cert_store(RootCertStore);
624599
}
625600

626601
impl rustls_root_cert_store {
@@ -634,19 +609,15 @@ impl rustls_root_cert_store {
634609
}
635610
}
636611

637-
/// A built client certificate verifier that can be provided to a `rustls_server_config_builder`
638-
/// with `rustls_server_config_builder_set_client_verifier`.
639-
pub struct rustls_client_cert_verifier {
640-
_private: [u8; 0],
641-
}
642-
643-
/// Rustls' ConfigBuilder requires an `Arc<dyn ClientCertVerifier>` here, meaning we
644-
/// must follow the pattern described in CONTRIBUTING.md[0] for handling dynamically sized
645-
/// types (DSTs) across the FFI boundary.
646-
/// [0] <https://github.com/rustls/rustls-ffi/blob/main/CONTRIBUTING.md#dynamically-sized-types>
647-
impl Castable for rustls_client_cert_verifier {
648-
type Ownership = OwnershipBox;
649-
type RustType = Arc<dyn ClientCertVerifier>;
612+
box_castable! {
613+
/// A built client certificate verifier that can be provided to a `rustls_server_config_builder`
614+
/// with `rustls_server_config_builder_set_client_verifier`.
615+
//
616+
// Rustls' ConfigBuilder requires an `Arc<dyn ClientCertVerifier>` here, meaning we
617+
// must follow the pattern described in CONTRIBUTING.md[^0] for handling dynamically sized
618+
// types (DSTs) across the FFI boundary.
619+
// [^0]: <https://github.com/rustls/rustls-ffi/blob/main/CONTRIBUTING.md#dynamically-sized-types>
620+
pub struct rustls_client_cert_verifier(Arc<dyn ClientCertVerifier>);
650621
}
651622

652623
impl rustls_client_cert_verifier {
@@ -661,18 +632,6 @@ impl rustls_client_cert_verifier {
661632
}
662633
}
663634

664-
/// A client certificate verifier being constructed. A builder can be modified by,
665-
/// e.g. `rustls_web_pki_client_cert_verifier_builder_add_crl`. Once you're
666-
/// done configuring settings, call `rustls_web_pki_client_cert_verifier_builder_build`
667-
/// to turn it into a `rustls_client_cert_verifier`. This object is not safe
668-
/// for concurrent mutation.
669-
///
670-
/// See <https://docs.rs/rustls/latest/rustls/server/struct.ClientCertVerifierBuilder.html>
671-
/// for more information.
672-
pub struct rustls_web_pki_client_cert_verifier_builder {
673-
_private: [u8; 0],
674-
}
675-
676635
pub(crate) struct ClientCertVerifierBuilder {
677636
roots: Arc<RootCertStore>,
678637
root_hint_subjects: Vec<DistinguishedName>,
@@ -682,9 +641,16 @@ pub(crate) struct ClientCertVerifierBuilder {
682641
allow_unauthenticated: bool,
683642
}
684643

685-
impl Castable for rustls_web_pki_client_cert_verifier_builder {
686-
type Ownership = OwnershipBox;
687-
type RustType = Option<ClientCertVerifierBuilder>;
644+
box_castable! {
645+
/// A client certificate verifier being constructed. A builder can be modified by,
646+
/// e.g. `rustls_web_pki_client_cert_verifier_builder_add_crl`. Once you're
647+
/// done configuring settings, call `rustls_web_pki_client_cert_verifier_builder_build`
648+
/// to turn it into a `rustls_client_cert_verifier`. This object is not safe
649+
/// for concurrent mutation.
650+
///
651+
/// See <https://docs.rs/rustls/latest/rustls/server/struct.ClientCertVerifierBuilder.html>
652+
/// for more information.
653+
pub struct rustls_web_pki_client_cert_verifier_builder(Option<ClientCertVerifierBuilder>);
688654
}
689655

690656
impl rustls_web_pki_client_cert_verifier_builder {
@@ -943,16 +909,16 @@ impl rustls_web_pki_client_cert_verifier_builder {
943909
}
944910
}
945911

946-
/// A server certificate verifier being constructed. A builder can be modified by,
947-
/// e.g. `rustls_web_pki_server_cert_verifier_builder_add_crl`. Once you're
948-
/// done configuring settings, call `rustls_web_pki_server_cert_verifier_builder_build`
949-
/// to turn it into a `rustls_server_cert_verifier`. This object is not safe
950-
/// for concurrent mutation.
951-
///
952-
/// See <https://docs.rs/rustls/latest/rustls/client/struct.ServerCertVerifierBuilder.html>
953-
/// for more information.
954-
pub struct rustls_web_pki_server_cert_verifier_builder {
955-
_private: [u8; 0],
912+
box_castable! {
913+
/// A server certificate verifier being constructed. A builder can be modified by,
914+
/// e.g. `rustls_web_pki_server_cert_verifier_builder_add_crl`. Once you're
915+
/// done configuring settings, call `rustls_web_pki_server_cert_verifier_builder_build`
916+
/// to turn it into a `rustls_server_cert_verifier`. This object is not safe
917+
/// for concurrent mutation.
918+
///
919+
/// See <https://docs.rs/rustls/latest/rustls/client/struct.ServerCertVerifierBuilder.html>
920+
/// for more information.
921+
pub struct rustls_web_pki_server_cert_verifier_builder(Option<ServerCertVerifierBuilder>);
956922
}
957923

958924
pub(crate) struct ServerCertVerifierBuilder {
@@ -962,11 +928,6 @@ pub(crate) struct ServerCertVerifierBuilder {
962928
revocation_policy: UnknownStatusPolicy,
963929
}
964930

965-
impl Castable for rustls_web_pki_server_cert_verifier_builder {
966-
type Ownership = OwnershipBox;
967-
type RustType = Option<ServerCertVerifierBuilder>;
968-
}
969-
970931
impl ServerCertVerifierBuilder {
971932
/// Create a `rustls_web_pki_server_cert_verifier_builder`. Caller owns the memory and may
972933
/// free it with `rustls_web_pki_server_cert_verifier_builder_free`, regardless of whether
@@ -1145,19 +1106,15 @@ impl ServerCertVerifierBuilder {
11451106
}
11461107
}
11471108

1148-
/// A built server certificate verifier that can be provided to a `rustls_client_config_builder`
1149-
/// with `rustls_client_config_builder_set_server_verifier`.
1150-
pub struct rustls_server_cert_verifier {
1151-
_private: [u8; 0],
1152-
}
1153-
1154-
/// Rustls' ConfigBuilder requires an `Arc<dyn ServerCertVerifier>` here, meaning we
1155-
/// must follow the pattern described in CONTRIBUTING.md[0] for handling dynamically sized
1156-
/// types (DSTs) across the FFI boundary.
1157-
/// [0] <https://github.com/rustls/rustls-ffi/blob/main/CONTRIBUTING.md#dynamically-sized-types>
1158-
impl Castable for rustls_server_cert_verifier {
1159-
type Ownership = OwnershipBox;
1160-
type RustType = Arc<dyn ServerCertVerifier>;
1109+
box_castable! {
1110+
/// A built server certificate verifier that can be provided to a `rustls_client_config_builder`
1111+
/// with `rustls_client_config_builder_set_server_verifier`.
1112+
//
1113+
// Rustls' ConfigBuilder requires an `Arc<dyn ServerCertVerifier>` here, meaning we
1114+
// must follow the pattern described in CONTRIBUTING.md[^0] for handling dynamically sized
1115+
// types (DSTs) across the FFI boundary.
1116+
// [^0]: <https://github.com/rustls/rustls-ffi/blob/main/CONTRIBUTING.md#dynamically-sized-types>
1117+
pub struct rustls_server_cert_verifier(Arc<dyn ServerCertVerifier>);
11611118
}
11621119

11631120
impl rustls_server_cert_verifier {

0 commit comments

Comments
 (0)