• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 use std::ffi;
28 use std::ptr;
29 use std::slice;
30 
31 use libc::c_char;
32 use libc::c_int;
33 use libc::c_void;
34 use libc::size_t;
35 use libc::ssize_t;
36 
37 use crate::*;
38 
39 use crate::h3::NameValue;
40 
41 #[no_mangle]
quiche_h3_config_new() -> *mut h3::Config42 pub extern fn quiche_h3_config_new() -> *mut h3::Config {
43     match h3::Config::new() {
44         Ok(c) => Box::into_raw(Box::new(c)),
45 
46         Err(_) => ptr::null_mut(),
47     }
48 }
49 
50 #[no_mangle]
quiche_h3_config_set_max_header_list_size( config: &mut h3::Config, v: u64, )51 pub extern fn quiche_h3_config_set_max_header_list_size(
52     config: &mut h3::Config, v: u64,
53 ) {
54     config.set_max_header_list_size(v);
55 }
56 
57 #[no_mangle]
quiche_h3_config_set_qpack_max_table_capacity( config: &mut h3::Config, v: u64, )58 pub extern fn quiche_h3_config_set_qpack_max_table_capacity(
59     config: &mut h3::Config, v: u64,
60 ) {
61     config.set_qpack_max_table_capacity(v);
62 }
63 
64 #[no_mangle]
quiche_h3_config_set_qpack_blocked_streams( config: &mut h3::Config, v: u64, )65 pub extern fn quiche_h3_config_set_qpack_blocked_streams(
66     config: &mut h3::Config, v: u64,
67 ) {
68     config.set_qpack_blocked_streams(v);
69 }
70 
71 #[no_mangle]
quiche_h3_config_free(config: *mut h3::Config)72 pub extern fn quiche_h3_config_free(config: *mut h3::Config) {
73     unsafe { Box::from_raw(config) };
74 }
75 
76 #[no_mangle]
quiche_h3_conn_new_with_transport( quic_conn: &mut Connection, config: &mut h3::Config, ) -> *mut h3::Connection77 pub extern fn quiche_h3_conn_new_with_transport(
78     quic_conn: &mut Connection, config: &mut h3::Config,
79 ) -> *mut h3::Connection {
80     match h3::Connection::with_transport(quic_conn, config) {
81         Ok(c) => Box::into_raw(Box::new(c)),
82 
83         Err(_) => ptr::null_mut(),
84     }
85 }
86 
87 #[no_mangle]
quiche_h3_conn_poll( conn: &mut h3::Connection, quic_conn: &mut Connection, ev: *mut *const h3::Event, ) -> i6488 pub extern fn quiche_h3_conn_poll(
89     conn: &mut h3::Connection, quic_conn: &mut Connection,
90     ev: *mut *const h3::Event,
91 ) -> i64 {
92     match conn.poll(quic_conn) {
93         Ok((id, v)) => {
94             unsafe {
95                 *ev = Box::into_raw(Box::new(v));
96             }
97 
98             id as i64
99         },
100 
101         Err(e) => e.to_c() as i64,
102     }
103 }
104 
105 #[no_mangle]
quiche_h3_event_type(ev: &h3::Event) -> u32106 pub extern fn quiche_h3_event_type(ev: &h3::Event) -> u32 {
107     match ev {
108         h3::Event::Headers { .. } => 0,
109 
110         h3::Event::Data { .. } => 1,
111 
112         h3::Event::Finished { .. } => 2,
113 
114         h3::Event::Datagram { .. } => 3,
115 
116         h3::Event::GoAway { .. } => 4,
117     }
118 }
119 
120 #[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_int121 pub extern fn quiche_h3_event_for_each_header(
122     ev: &h3::Event,
123     cb: extern fn(
124         name: *const u8,
125         name_len: size_t,
126 
127         value: *const u8,
128         value_len: size_t,
129 
130         argp: *mut c_void,
131     ) -> c_int,
132     argp: *mut c_void,
133 ) -> c_int {
134     match ev {
135         h3::Event::Headers { list, .. } =>
136             for h in list {
137                 let rc = cb(
138                     h.name().as_ptr(),
139                     h.name().len(),
140                     h.value().as_ptr(),
141                     h.value().len(),
142                     argp,
143                 );
144 
145                 if rc != 0 {
146                     return rc;
147                 }
148             },
149 
150         _ => unreachable!(),
151     }
152 
153     0
154 }
155 
156 #[no_mangle]
quiche_h3_event_headers_has_body(ev: &h3::Event) -> bool157 pub extern fn quiche_h3_event_headers_has_body(ev: &h3::Event) -> bool {
158     match ev {
159         h3::Event::Headers { has_body, .. } => *has_body,
160 
161         _ => unreachable!(),
162     }
163 }
164 
165 #[no_mangle]
quiche_h3_event_free(ev: *mut h3::Event)166 pub extern fn quiche_h3_event_free(ev: *mut h3::Event) {
167     unsafe { Box::from_raw(ev) };
168 }
169 
170 #[repr(C)]
171 pub struct Header {
172     name: *mut u8,
173     name_len: usize,
174 
175     value: *mut u8,
176     value_len: usize,
177 }
178 
179 #[no_mangle]
quiche_h3_send_request( conn: &mut h3::Connection, quic_conn: &mut Connection, headers: *const Header, headers_len: size_t, fin: bool, ) -> i64180 pub extern fn quiche_h3_send_request(
181     conn: &mut h3::Connection, quic_conn: &mut Connection,
182     headers: *const Header, headers_len: size_t, fin: bool,
183 ) -> i64 {
184     let req_headers = headers_from_ptr(headers, headers_len);
185 
186     match conn.send_request(quic_conn, &req_headers, fin) {
187         Ok(v) => v as i64,
188 
189         Err(e) => e.to_c() as i64,
190     }
191 }
192 
193 #[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_int194 pub extern fn quiche_h3_send_response(
195     conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
196     headers: *const Header, headers_len: size_t, fin: bool,
197 ) -> c_int {
198     let resp_headers = headers_from_ptr(headers, headers_len);
199 
200     match conn.send_response(quic_conn, stream_id, &resp_headers, fin) {
201         Ok(_) => 0,
202 
203         Err(e) => e.to_c() as c_int,
204     }
205 }
206 
207 #[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: *const c_char, fin: bool, ) -> c_int208 pub extern fn quiche_h3_send_response_with_priority(
209     conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
210     headers: *const Header, headers_len: size_t, priority: *const c_char,
211     fin: bool,
212 ) -> c_int {
213     let resp_headers = headers_from_ptr(headers, headers_len);
214     let priority = unsafe { ffi::CStr::from_ptr(priority).to_str().unwrap() };
215 
216     match conn.send_response_with_priority(
217         quic_conn,
218         stream_id,
219         &resp_headers,
220         &priority,
221         fin,
222     ) {
223         Ok(_) => 0,
224 
225         Err(e) => e.to_c() as c_int,
226     }
227 }
228 
229 #[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_t230 pub extern fn quiche_h3_send_body(
231     conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
232     body: *const u8, body_len: size_t, fin: bool,
233 ) -> ssize_t {
234     if body_len > <ssize_t>::max_value() as usize {
235         panic!("The provided buffer is too large");
236     }
237 
238     let body = unsafe { slice::from_raw_parts(body, body_len) };
239 
240     match conn.send_body(quic_conn, stream_id, body, fin) {
241         Ok(v) => v as ssize_t,
242 
243         Err(e) => e.to_c(),
244     }
245 }
246 
247 #[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_t248 pub extern fn quiche_h3_recv_body(
249     conn: &mut h3::Connection, quic_conn: &mut Connection, stream_id: u64,
250     out: *mut u8, out_len: size_t,
251 ) -> ssize_t {
252     if out_len > <ssize_t>::max_value() as usize {
253         panic!("The provided buffer is too large");
254     }
255 
256     let out = unsafe { slice::from_raw_parts_mut(out, out_len) };
257 
258     match conn.recv_body(quic_conn, stream_id, out) {
259         Ok(v) => v as ssize_t,
260 
261         Err(e) => e.to_c(),
262     }
263 }
264 
265 #[no_mangle]
quiche_h3_dgram_enabled_by_peer( conn: &h3::Connection, quic_conn: &Connection, ) -> bool266 pub extern fn quiche_h3_dgram_enabled_by_peer(
267     conn: &h3::Connection, quic_conn: &Connection,
268 ) -> bool {
269     conn.dgram_enabled_by_peer(quic_conn)
270 }
271 
272 #[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_int273 pub extern fn quiche_h3_send_dgram(
274     conn: &mut h3::Connection, quic_conn: &mut Connection, flow_id: u64,
275     data: *const u8, data_len: size_t,
276 ) -> c_int {
277     if data_len > <ssize_t>::max_value() as usize {
278         panic!("The provided buffer is too large");
279     }
280 
281     let data = unsafe { slice::from_raw_parts(data, data_len) };
282 
283     match conn.send_dgram(quic_conn, flow_id, data) {
284         Ok(_) => 0,
285 
286         Err(e) => e.to_c() as c_int,
287     }
288 }
289 
290 #[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_t291 pub extern fn quiche_h3_recv_dgram(
292     conn: &mut h3::Connection, quic_conn: &mut Connection, flow_id: *mut u64,
293     flow_id_len: *mut usize, out: *mut u8, out_len: size_t,
294 ) -> ssize_t {
295     if out_len > <ssize_t>::max_value() as usize {
296         panic!("The provided buffer is too large");
297     }
298 
299     let out = unsafe { slice::from_raw_parts_mut(out, out_len) };
300 
301     match conn.recv_dgram(quic_conn, out) {
302         Ok((len, id, id_len)) => {
303             unsafe { *flow_id = id };
304             unsafe { *flow_id_len = id_len };
305             len as ssize_t
306         },
307 
308         Err(e) => e.to_c(),
309     }
310 }
311 
312 #[no_mangle]
quiche_h3_conn_free(conn: *mut h3::Connection)313 pub extern fn quiche_h3_conn_free(conn: *mut h3::Connection) {
314     unsafe { Box::from_raw(conn) };
315 }
316 
headers_from_ptr<'a>( ptr: *const Header, len: size_t, ) -> Vec<h3::HeaderRef<'a>>317 fn headers_from_ptr<'a>(
318     ptr: *const Header, len: size_t,
319 ) -> Vec<h3::HeaderRef<'a>> {
320     let headers = unsafe { slice::from_raw_parts(ptr, len) };
321 
322     let mut out = Vec::new();
323 
324     for h in headers {
325         out.push({
326             let name = unsafe { slice::from_raw_parts(h.name, h.name_len) };
327             let value = unsafe { slice::from_raw_parts(h.value, h.value_len) };
328 
329             h3::HeaderRef::new(name, value)
330         });
331     }
332 
333     out
334 }
335