1 // Copyright (C) 2019, Cloudflare, Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright notice,
9 //       this list of conditions and the following disclaimer.
10 //
11 //     * Redistributions in binary form must reproduce the above copyright
12 //       notice, this list of conditions and the following disclaimer in the
13 //       documentation and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #[cfg(feature = "sfv")]
28 use std::convert::TryFrom;
29 
30 use std::ptr;
31 use std::slice;
32 
33 use libc::c_int;
34 use libc::c_void;
35 use libc::size_t;
36 use libc::ssize_t;
37 
38 use crate::*;
39 
40 use crate::h3::NameValue;
41 use crate::h3::Priority;
42 
43 #[no_mangle]
quiche_h3_config_new() -> *mut h3::Config44 pub extern fn quiche_h3_config_new() -> *mut h3::Config {
45     match h3::Config::new() {
46         Ok(c) => Box::into_raw(Box::new(c)),
47 
48         Err(_) => ptr::null_mut(),
49     }
50 }
51 
52 #[no_mangle]
quiche_h3_config_set_max_field_section_size( config: &mut h3::Config, v: u64, )53 pub extern fn quiche_h3_config_set_max_field_section_size(
54     config: &mut h3::Config, v: u64,
55 ) {
56     config.set_max_field_section_size(v);
57 }
58 
59 #[no_mangle]
quiche_h3_config_set_qpack_max_table_capacity( config: &mut h3::Config, v: u64, )60 pub extern fn quiche_h3_config_set_qpack_max_table_capacity(
61     config: &mut h3::Config, v: u64,
62 ) {
63     config.set_qpack_max_table_capacity(v);
64 }
65 
66 #[no_mangle]
quiche_h3_config_set_qpack_blocked_streams( config: &mut h3::Config, v: u64, )67 pub extern fn quiche_h3_config_set_qpack_blocked_streams(
68     config: &mut h3::Config, v: u64,
69 ) {
70     config.set_qpack_blocked_streams(v);
71 }
72 
73 #[no_mangle]
quiche_h3_config_enable_extended_connect( config: &mut h3::Config, enabled: bool, )74 pub extern fn quiche_h3_config_enable_extended_connect(
75     config: &mut h3::Config, enabled: bool,
76 ) {
77     config.enable_extended_connect(enabled);
78 }
79 
80 #[no_mangle]
quiche_h3_config_free(config: *mut h3::Config)81 pub extern fn quiche_h3_config_free(config: *mut h3::Config) {
82     unsafe { Box::from_raw(config) };
83 }
84 
85 #[no_mangle]
quiche_h3_conn_new_with_transport( quic_conn: &mut Connection, config: &mut h3::Config, ) -> *mut h3::Connection86 pub extern fn quiche_h3_conn_new_with_transport(
87     quic_conn: &mut Connection, config: &mut h3::Config,
88 ) -> *mut h3::Connection {
89     match h3::Connection::with_transport(quic_conn, config) {
90         Ok(c) => Box::into_raw(Box::new(c)),
91 
92         Err(_) => ptr::null_mut(),
93     }
94 }
95 
96 #[no_mangle]
quiche_h3_for_each_setting( conn: &h3::Connection, cb: extern fn(identifier: u64, value: u64, argp: *mut c_void) -> c_int, argp: *mut c_void, ) -> c_int97 pub extern fn quiche_h3_for_each_setting(
98     conn: &h3::Connection,
99     cb: extern fn(identifier: u64, value: u64, argp: *mut c_void) -> c_int,
100     argp: *mut c_void,
101 ) -> c_int {
102     match conn.peer_settings_raw() {
103         Some(raw) => {
104             for setting in raw {
105                 let rc = cb(setting.0, setting.1, argp);
106 
107                 if rc != 0 {
108                     return rc;
109                 }
110             }
111 
112             0
113         },
114 
115         None => -1,
116     }
117 }
118 
119 #[no_mangle]
quiche_h3_conn_poll( conn: &mut h3::Connection, quic_conn: &mut Connection, ev: *mut *const h3::Event, ) -> i64120 pub extern fn quiche_h3_conn_poll(
121     conn: &mut h3::Connection, quic_conn: &mut Connection,
122     ev: *mut *const h3::Event,
123 ) -> i64 {
124     match conn.poll(quic_conn) {
125         Ok((id, v)) => {
126             unsafe {
127                 *ev = Box::into_raw(Box::new(v));
128             }
129 
130             id as i64
131         },
132 
133         Err(e) => e.to_c() as i64,
134     }
135 }
136 
137 #[no_mangle]
quiche_h3_event_type(ev: &h3::Event) -> u32138 pub extern fn quiche_h3_event_type(ev: &h3::Event) -> u32 {
139     match ev {
140         h3::Event::Headers { .. } => 0,
141 
142         h3::Event::Data { .. } => 1,
143 
144         h3::Event::Finished { .. } => 2,
145 
146         h3::Event::Datagram { .. } => 3,
147 
148         h3::Event::GoAway { .. } => 4,
149 
150         h3::Event::Reset { .. } => 5,
151 
152         h3::Event::PriorityUpdate { .. } => 6,
153     }
154 }
155 
156 #[no_mangle]
quiche_h3_event_for_each_header( ev: &h3::Event, cb: extern fn( name: *const u8, name_len: size_t, value: *const u8, value_len: size_t, argp: *mut c_void, ) -> c_int, argp: *mut c_void, ) -> c_int157 pub extern fn quiche_h3_event_for_each_header(
158     ev: &h3::Event,
159     cb: extern fn(
160         name: *const u8,
161         name_len: size_t,
162 
163         value: *const u8,
164         value_len: size_t,
165 
166         argp: *mut c_void,
167     ) -> c_int,
168     argp: *mut c_void,
169 ) -> c_int {
170     match ev {
171         h3::Event::Headers { list, .. } =>
172             for h in list {
173                 let rc = cb(
174                     h.name().as_ptr(),
175                     h.name().len(),
176                     h.value().as_ptr(),
177                     h.value().len(),
178                     argp,
179                 );
180 
181                 if rc != 0 {
182                     return rc;
183                 }
184             },
185 
186         _ => unreachable!(),
187     }
188 
189     0
190 }
191 
192 #[no_mangle]
quiche_h3_event_headers_has_body(ev: &h3::Event) -> bool193 pub extern fn quiche_h3_event_headers_has_body(ev: &h3::Event) -> bool {
194     match ev {
195         h3::Event::Headers { has_body, .. } => *has_body,
196 
197         _ => unreachable!(),
198     }
199 }
200 
201 #[no_mangle]
quiche_h3_extended_connect_enabled_by_peer( conn: &h3::Connection, ) -> bool202 pub extern fn quiche_h3_extended_connect_enabled_by_peer(
203     conn: &h3::Connection,
204 ) -> bool {
205     conn.extended_connect_enabled_by_peer()
206 }
207 
208 #[no_mangle]
quiche_h3_event_free(ev: *mut h3::Event)209 pub extern fn quiche_h3_event_free(ev: *mut h3::Event) {
210     unsafe { Box::from_raw(ev) };
211 }
212 
213 #[repr(C)]
214 pub struct Header {
215     name: *mut u8,
216     name_len: usize,
217 
218     value: *mut u8,
219     value_len: usize,
220 }
221 
222 #[no_mangle]
quiche_h3_send_request( conn: &mut h3::Connection, quic_conn: &mut Connection, headers: *const Header, headers_len: size_t, fin: bool, ) -> i64223 pub extern fn quiche_h3_send_request(
224     conn: &mut h3::Connection, quic_conn: &mut Connection,
225     headers: *const Header, headers_len: size_t, fin: bool,
226 ) -> i64 {
227     let req_headers = headers_from_ptr(headers, headers_len);
228 
229     match conn.send_request(quic_conn, &req_headers, fin) {
230         Ok(v) => v as i64,
231 
232         Err(e) => e.to_c() as i64,
233     }
234 }
235 
236 #[no_mangle]
quiche_h3_send_response( conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64, headers: *const Header, headers_len: size_t, fin: bool, ) -> c_int237 pub extern fn quiche_h3_send_response(
238     conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
239     headers: *const Header, headers_len: size_t, fin: bool,
240 ) -> c_int {
241     let resp_headers = headers_from_ptr(headers, headers_len);
242 
243     match conn.send_response(quic_conn, stream_id, &resp_headers, fin) {
244         Ok(_) => 0,
245 
246         Err(e) => e.to_c() as c_int,
247     }
248 }
249 
250 #[no_mangle]
quiche_h3_send_response_with_priority( conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64, headers: *const Header, headers_len: size_t, priority: &Priority, fin: bool, ) -> c_int251 pub extern fn quiche_h3_send_response_with_priority(
252     conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
253     headers: *const Header, headers_len: size_t, priority: &Priority, fin: bool,
254 ) -> c_int {
255     let resp_headers = headers_from_ptr(headers, headers_len);
256 
257     match conn.send_response_with_priority(
258         quic_conn,
259         stream_id,
260         &resp_headers,
261         priority,
262         fin,
263     ) {
264         Ok(_) => 0,
265 
266         Err(e) => e.to_c() as c_int,
267     }
268 }
269 
270 #[no_mangle]
quiche_h3_send_body( conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64, body: *const u8, body_len: size_t, fin: bool, ) -> ssize_t271 pub extern fn quiche_h3_send_body(
272     conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
273     body: *const u8, body_len: size_t, fin: bool,
274 ) -> ssize_t {
275     if body_len > <ssize_t>::max_value() as usize {
276         panic!("The provided buffer is too large");
277     }
278 
279     let body = unsafe { slice::from_raw_parts(body, body_len) };
280 
281     match conn.send_body(quic_conn, stream_id, body, fin) {
282         Ok(v) => v as ssize_t,
283 
284         Err(e) => e.to_c(),
285     }
286 }
287 
288 #[no_mangle]
quiche_h3_recv_body( conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64, out: *mut u8, out_len: size_t, ) -> ssize_t289 pub extern fn quiche_h3_recv_body(
290     conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
291     out: *mut u8, out_len: size_t,
292 ) -> ssize_t {
293     if out_len > <ssize_t>::max_value() as usize {
294         panic!("The provided buffer is too large");
295     }
296 
297     let out = unsafe { slice::from_raw_parts_mut(out, out_len) };
298 
299     match conn.recv_body(quic_conn, stream_id, out) {
300         Ok(v) => v as ssize_t,
301 
302         Err(e) => e.to_c(),
303     }
304 }
305 
306 #[no_mangle]
307 #[cfg(feature = "sfv")]
quiche_h3_parse_extensible_priority( priority: *const u8, priority_len: size_t, parsed: &mut Priority, ) -> c_int308 pub extern fn quiche_h3_parse_extensible_priority(
309     priority: *const u8, priority_len: size_t, parsed: &mut Priority,
310 ) -> c_int {
311     let priority = unsafe { slice::from_raw_parts(priority, priority_len) };
312 
313     match h3::Priority::try_from(priority) {
314         Ok(v) => {
315             parsed.urgency = v.urgency;
316             parsed.incremental = v.incremental;
317             0
318         },
319 
320         Err(e) => e.to_c() as c_int,
321     }
322 }
323 
324 #[no_mangle]
quiche_h3_send_priority_update_for_request( conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64, priority: &Priority, ) -> c_int325 pub extern fn quiche_h3_send_priority_update_for_request(
326     conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
327     priority: &Priority,
328 ) -> c_int {
329     match conn.send_priority_update_for_request(quic_conn, stream_id, priority) {
330         Ok(()) => 0,
331 
332         Err(e) => e.to_c() as c_int,
333     }
334 }
335 
336 #[no_mangle]
quiche_h3_take_last_priority_update( conn: &mut h3::Connection, prioritized_element_id: u64, cb: extern fn( priority_field_value: *const u8, priority_field_value_len: size_t, argp: *mut c_void, ) -> c_int, argp: *mut c_void, ) -> c_int337 pub extern fn quiche_h3_take_last_priority_update(
338     conn: &mut h3::Connection, prioritized_element_id: u64,
339     cb: extern fn(
340         priority_field_value: *const u8,
341         priority_field_value_len: size_t,
342         argp: *mut c_void,
343     ) -> c_int,
344     argp: *mut c_void,
345 ) -> c_int {
346     match conn.take_last_priority_update(prioritized_element_id) {
347         Ok(priority) => {
348             let rc = cb(priority.as_ptr(), priority.len(), argp);
349 
350             if rc != 0 {
351                 return rc;
352             }
353 
354             0
355         },
356 
357         Err(e) => e.to_c() as c_int,
358     }
359 }
360 
361 #[no_mangle]
quiche_h3_dgram_enabled_by_peer( conn: &h3::Connection, quic_conn: &Connection, ) -> bool362 pub extern fn quiche_h3_dgram_enabled_by_peer(
363     conn: &h3::Connection, quic_conn: &Connection,
364 ) -> bool {
365     conn.dgram_enabled_by_peer(quic_conn)
366 }
367 
368 #[no_mangle]
quiche_h3_send_dgram( conn: &mut h3::Connection, quic_conn: &mut Connection, flow_id: u64, data: *const u8, data_len: size_t, ) -> c_int369 pub extern fn quiche_h3_send_dgram(
370     conn: &mut h3::Connection, quic_conn: &mut Connection, flow_id: u64,
371     data: *const u8, data_len: size_t,
372 ) -> c_int {
373     if data_len > <ssize_t>::max_value() as usize {
374         panic!("The provided buffer is too large");
375     }
376 
377     let data = unsafe { slice::from_raw_parts(data, data_len) };
378 
379     match conn.send_dgram(quic_conn, flow_id, data) {
380         Ok(_) => 0,
381 
382         Err(e) => e.to_c() as c_int,
383     }
384 }
385 
386 #[no_mangle]
quiche_h3_recv_dgram( conn: &mut h3::Connection, quic_conn: &mut Connection, flow_id: *mut u64, flow_id_len: *mut usize, out: *mut u8, out_len: size_t, ) -> ssize_t387 pub extern fn quiche_h3_recv_dgram(
388     conn: &mut h3::Connection, quic_conn: &mut Connection, flow_id: *mut u64,
389     flow_id_len: *mut usize, out: *mut u8, out_len: size_t,
390 ) -> ssize_t {
391     if out_len > <ssize_t>::max_value() as usize {
392         panic!("The provided buffer is too large");
393     }
394 
395     let out = unsafe { slice::from_raw_parts_mut(out, out_len) };
396 
397     match conn.recv_dgram(quic_conn, out) {
398         Ok((len, id, id_len)) => {
399             unsafe { *flow_id = id };
400             unsafe { *flow_id_len = id_len };
401             len as ssize_t
402         },
403 
404         Err(e) => e.to_c(),
405     }
406 }
407 
408 #[no_mangle]
quiche_h3_conn_free(conn: *mut h3::Connection)409 pub extern fn quiche_h3_conn_free(conn: *mut h3::Connection) {
410     unsafe { Box::from_raw(conn) };
411 }
412 
headers_from_ptr<'a>( ptr: *const Header, len: size_t, ) -> Vec<h3::HeaderRef<'a>>413 fn headers_from_ptr<'a>(
414     ptr: *const Header, len: size_t,
415 ) -> Vec<h3::HeaderRef<'a>> {
416     let headers = unsafe { slice::from_raw_parts(ptr, len) };
417 
418     let mut out = Vec::new();
419 
420     for h in headers {
421         out.push({
422             let name = unsafe { slice::from_raw_parts(h.name, h.name_len) };
423             let value = unsafe { slice::from_raw_parts(h.value, h.value_len) };
424 
425             h3::HeaderRef::new(name, value)
426         });
427     }
428 
429     out
430 }
431