Skip to content

Commit ae28651

Browse files
committed
Update base.rs.
We now have four types that map nicely to Rust types: - rustls_str -> &str or &String - rustls_slice_bytes -> &[u8] or &Vec<u8> - rustls_vec_str -> &[&str] or &Vec<&str> - rustls_vec_slice_bytes -> &[&[u8]] or &Vec<Vec<u8>> I also added lifetime parameters for these types, along with PhantomData to refer to those lifetime parameters. This lets us take slightly more advantage of Rust's safety tools by ensuring we don't allow any of these types to outlive the things they refer to.
1 parent 3b636b0 commit ae28651

File tree

3 files changed

+117
-77
lines changed

3 files changed

+117
-77
lines changed

src/base.rs

Lines changed: 75 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,108 @@
1-
use libc::size_t;
2-
use std::os::raw::{c_char, c_ushort};
1+
use libc::{c_char, size_t};
2+
use std::{marker::PhantomData, os::raw::{c_ushort}};
33

4-
/// A read-only view on a Rust utf-8 string or byte array.
4+
/// A read-only view on a Rust byte slice.
5+
///
56
/// This is used to pass data from crustls to callback functions provided
6-
/// by the user of the API. The `data` is not NUL-terminated.
7+
/// by the user of the API.
78
/// `len` indicates the number of bytes than can be safely read.
8-
/// A `len` of 0 is used to represent a missing value.
9+
/// A `len` of 0 is used to represent a missing value OR an empty slice.
910
///
10-
/// The memmory exposed is available for the duration of the call (e.g.
11+
/// The memory exposed is available for the duration of the call (e.g.
1112
/// when passed to a callback) and must be copied if the values are
1213
/// needed for longer.
13-
///
1414
#[allow(non_camel_case_types)]
1515
#[repr(C)]
16-
pub struct rustls_string {
17-
data: *const c_char,
16+
pub struct rustls_slice_bytes<'a> {
17+
data: *const u8,
1818
len: size_t,
19+
phantom: PhantomData<&'a [u8]>,
1920
}
2021

21-
impl<'a> From<&'a String> for rustls_string {
22-
fn from(s: &String) -> Self {
23-
rustls_string {
24-
data: s.as_ptr() as *const c_char,
22+
impl<'a> From<&'a [u8]> for rustls_slice_bytes<'a> {
23+
fn from(s: &[u8]) -> Self {
24+
rustls_slice_bytes {
25+
data: s.as_ptr() as *const u8,
2526
len: s.len() as size_t,
27+
phantom: PhantomData,
2628
}
2729
}
2830
}
2931

30-
impl<'a> From<&'a str> for rustls_string {
31-
fn from(s: &str) -> Self {
32-
rustls_string {
33-
data: s.as_ptr() as *const c_char,
34-
len: s.len() as size_t,
35-
}
36-
}
32+
/// A read-only view on a vector of Rust byte slices.
33+
///
34+
/// This is used to pass data from crustls to callback functions provided
35+
/// by the user of the API. The `data` is an array of `rustls_slice_bytes`
36+
/// structures with `len` elements.
37+
///
38+
/// The memory exposed is available for the duration of the call (e.g.
39+
/// when passed to a callback) and must be copied if the values are
40+
/// needed for longer.
41+
#[allow(non_camel_case_types)]
42+
#[repr(C)]
43+
pub struct rustls_vec_slice_bytes<'a> {
44+
data: *const rustls_slice_bytes<'a>,
45+
len: size_t,
3746
}
3847

39-
impl<'a> From<&'a [u8]> for rustls_string {
40-
fn from(s: &[u8]) -> Self {
41-
rustls_string {
42-
data: s.as_ptr() as *const c_char,
43-
len: s.len() as size_t,
48+
impl<'a> From<&'a [&[u8]]> for rustls_vec_slice_bytes<'a> {
49+
fn from(input: &'a [&[u8]]) -> Self {
50+
let mut output: Vec<rustls_slice_bytes> = vec![];
51+
for b in input {
52+
let b: &[u8] = b;
53+
output.push(b.into());
4454
}
45-
}
46-
}
47-
48-
pub(crate) fn rustls_strings<'a>(values: Option<&'a [&'a [u8]]>) -> Vec<rustls_string> {
49-
let mut strings: Vec<rustls_string> = Vec::new();
50-
match values {
51-
Some(values) => {
52-
for entry in values.iter() {
53-
strings.push(rustls_string::from(*entry))
54-
}
55+
rustls_vec_slice_bytes {
56+
data: output.as_ptr(),
57+
len: output.len(),
5558
}
56-
None => (),
57-
};
58-
strings
59+
}
5960
}
6061

61-
/// A read-only view on a list of Rust utf-8 strings or byte arrays.
62+
/// A read-only view on a Rust utf-8 string slice.
6263
/// This is used to pass data from crustls to callback functions provided
63-
/// by the user of the API. The `data` is an array of `rustls_string`
64-
/// structures with `len` elements.
64+
/// by the user of the API. The `data` is not NUL-terminated.
65+
/// `len` indicates the number of bytes than can be safely read.
66+
/// A `len` of 0 is used to represent a missing value OR an empty string.
6567
///
66-
/// The memmory exposed is available for the duration of the call (e.g.
68+
/// The memory exposed is available for the duration of the call (e.g.
6769
/// when passed to a callback) and must be copied if the values are
6870
/// needed for longer.
69-
///
7071
#[allow(non_camel_case_types)]
7172
#[repr(C)]
72-
pub struct rustls_vec_string {
73-
data: *const rustls_string,
73+
pub struct rustls_str<'a> {
74+
data: *const c_char,
7475
len: size_t,
76+
phantom: PhantomData<&'a str>,
7577
}
7678

77-
impl<'a> From<&'a Vec<rustls_string>> for rustls_vec_string {
78-
fn from(values: &Vec<rustls_string>) -> Self {
79-
rustls_vec_string {
80-
data: values.as_ptr(),
81-
len: values.len(),
79+
impl<'a> From<&'a str> for rustls_str<'a> {
80+
fn from(s: &str) -> Self {
81+
rustls_str {
82+
data: s.as_ptr() as *const c_char,
83+
len: s.len() as size_t,
84+
phantom: PhantomData,
85+
}
86+
}
87+
}
88+
89+
#[allow(non_camel_case_types)]
90+
#[repr(C)]
91+
pub struct rustls_vec_str<'a> {
92+
data: *const rustls_str<'a>,
93+
len: size_t,
94+
}
95+
96+
impl<'a> From<&'a [String]> for rustls_vec_str<'a> {
97+
fn from(input: &'a [String]) -> Self {
98+
let mut output: Vec<rustls_str> = vec![];
99+
for b in input {
100+
let b: &str = b;
101+
output.push(b.into());
102+
}
103+
rustls_vec_str {
104+
data: output.as_ptr(),
105+
len: output.len(),
82106
}
83107
}
84108
}
@@ -87,10 +111,9 @@ impl<'a> From<&'a Vec<rustls_string>> for rustls_vec_string {
87111
/// This is used to pass data from crustls to callback functions provided
88112
/// by the user of the API. The `data` is an array of `len` 16 bit values.
89113
///
90-
/// The memmory exposed is available for the duration of the call (e.g.
114+
/// The memory exposed is available for the duration of the call (e.g.
91115
/// when passed to a callback) and must be copied if the values are
92116
/// needed for longer.
93-
///
94117
#[allow(non_camel_case_types)]
95118
#[repr(C)]
96119
pub struct rustls_vec_ushort {

src/crustls.h

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -135,52 +135,67 @@ typedef struct rustls_server_session rustls_server_session;
135135
typedef void *rustls_client_hello_userdata;
136136

137137
/**
138-
* A read-only view on a Rust utf-8 string or byte array.
138+
* A read-only view on a Rust utf-8 string slice.
139139
* This is used to pass data from crustls to callback functions provided
140140
* by the user of the API. The `data` is not NUL-terminated.
141141
* `len` indicates the number of bytes than can be safely read.
142-
* A `len` of 0 is used to represent a missing value.
142+
* A `len` of 0 is used to represent a missing value OR an empty string.
143143
*
144-
* The memmory exposed is available for the duration of the call (e.g.
144+
* The memory exposed is available for the duration of the call (e.g.
145145
* when passed to a callback) and must be copied if the values are
146146
* needed for longer.
147-
*
148147
*/
149-
typedef struct rustls_string {
148+
typedef struct rustls_str {
150149
const char *data;
151150
size_t len;
152-
} rustls_string;
151+
} rustls_str;
153152

154153
/**
155154
* A read-only view on a list of Rust owned unsigned short values.
156155
* This is used to pass data from crustls to callback functions provided
157156
* by the user of the API. The `data` is an array of `len` 16 bit values.
158157
*
159-
* The memmory exposed is available for the duration of the call (e.g.
158+
* The memory exposed is available for the duration of the call (e.g.
160159
* when passed to a callback) and must be copied if the values are
161160
* needed for longer.
162-
*
163161
*/
164162
typedef struct rustls_vec_ushort {
165163
const unsigned short *data;
166164
size_t len;
167165
} rustls_vec_ushort;
168166

169167
/**
170-
* A read-only view on a list of Rust utf-8 strings or byte arrays.
168+
* A read-only view on a Rust byte slice.
169+
*
171170
* This is used to pass data from crustls to callback functions provided
172-
* by the user of the API. The `data` is an array of `rustls_string`
173-
* structures with `len` elements.
171+
* by the user of the API.
172+
* `len` indicates the number of bytes than can be safely read.
173+
* A `len` of 0 is used to represent a missing value OR an empty slice.
174174
*
175-
* The memmory exposed is available for the duration of the call (e.g.
175+
* The memory exposed is available for the duration of the call (e.g.
176176
* when passed to a callback) and must be copied if the values are
177177
* needed for longer.
178+
*/
179+
typedef struct rustls_slice_bytes {
180+
const uint8_t *data;
181+
size_t len;
182+
} rustls_slice_bytes;
183+
184+
/**
185+
* A read-only view on a vector of Rust byte slices.
178186
*
187+
* This is used to pass data from crustls to callback functions provided
188+
* by the user of the API. The `data` is an array of `rustls_slice_bytes`
189+
* structures with `len` elements.
190+
*
191+
* The memory exposed is available for the duration of the call (e.g.
192+
* when passed to a callback) and must be copied if the values are
193+
* needed for longer.
179194
*/
180-
typedef struct rustls_vec_string {
181-
const struct rustls_string *data;
195+
typedef struct rustls_vec_slice_bytes {
196+
const struct rustls_slice_bytes *data;
182197
size_t len;
183-
} rustls_vec_string;
198+
} rustls_vec_slice_bytes;
184199

185200
/**
186201
* The TLS Client Hello information provided to a ClientHelloCallback function.
@@ -201,9 +216,9 @@ typedef struct rustls_vec_string {
201216
* the rustls library is re-evaluating their current approach to client hello handling.
202217
*/
203218
typedef struct rustls_client_hello {
204-
struct rustls_string sni_name;
219+
struct rustls_str sni_name;
205220
struct rustls_vec_ushort signature_schemes;
206-
struct rustls_vec_string alpn;
221+
struct rustls_vec_slice_bytes alpn;
207222
} rustls_client_hello;
208223

209224
/**

src/server.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustls::{
1010
};
1111
use rustls_pemfile::{certs, pkcs8_private_keys, rsa_private_keys};
1212

13-
use crate::arc_with_incref_from_raw;
14-
use crate::base::{rustls_string, rustls_strings, rustls_vec_string, rustls_vec_ushort};
13+
use crate::{arc_with_incref_from_raw, base::rustls_vec_slice_bytes};
14+
use crate::base::{rustls_str, rustls_vec_ushort};
1515
use crate::cipher::rustls_cipher_map_signature_schemes;
1616
use crate::error::{map_error, rustls_result};
1717
use crate::{
@@ -495,10 +495,10 @@ pub extern "C" fn rustls_server_session_get_sni_hostname(
495495
/// the rustls library is re-evaluating their current approach to client hello handling.
496496
#[allow(non_camel_case_types)]
497497
#[repr(C)]
498-
pub struct rustls_client_hello {
499-
sni_name: rustls_string,
498+
pub struct rustls_client_hello<'a> {
499+
sni_name: rustls_str<'a>,
500500
signature_schemes: rustls_vec_ushort,
501-
alpn: rustls_vec_string,
501+
alpn: rustls_vec_slice_bytes<'a>,
502502
}
503503

504504
/// Any context information the callback will receive when invoked.
@@ -546,11 +546,13 @@ impl rustls::ResolvesServerCert for ClientHelloResolver {
546546
}
547547
};
548548
let mapped_sigs: Vec<u16> = rustls_cipher_map_signature_schemes(client_hello.sigschemes());
549-
let alpn: Vec<rustls_string> = rustls_strings(client_hello.alpn());
549+
// Unwrap the Option. None becomes an empty slice.
550+
let alpn: &[&[u8]] = client_hello.alpn().unwrap_or(&[]);
551+
let alpn: rustls_vec_slice_bytes = alpn.into();
550552
let hello = rustls_client_hello {
551-
sni_name: rustls_string::from(sni_name),
553+
sni_name: rustls_str::from(sni_name),
552554
signature_schemes: rustls_vec_ushort::from(&mapped_sigs),
553-
alpn: rustls_vec_string::from(&alpn),
555+
alpn,
554556
};
555557
let cb = self.callback;
556558
unsafe { cb(self.userdata, &hello) };

0 commit comments

Comments
 (0)