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