1 /*
2 * Copyright (C) 2021, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 use crate::dns_https_frontend::DohFrontend;
18 use crate::stats::Stats;
19
20 use anyhow::{bail, Result};
21 use libc::c_char;
22 use log::warn;
23 use std::ffi::CStr;
24 use std::net::{IpAddr, SocketAddr};
25 use std::str::FromStr;
26
27 /// Creates a DohFrontend object by the given IP addresss and ports. Returns the pointer of
28 /// the object if the creation succeeds; otherwise, returns a null pointer.
29 ///
30 /// # Safety
31 ///
32 /// The parameters `addr`, `port`, `backend_addr`, and `backend_port` must all point to null
33 /// terminated UTF-8 encoded strings.
34 #[no_mangle]
frontend_new( addr: *const c_char, port: *const c_char, backend_addr: *const c_char, backend_port: *const c_char, ) -> *mut DohFrontend35 pub unsafe extern "C" fn frontend_new(
36 addr: *const c_char,
37 port: *const c_char,
38 backend_addr: *const c_char,
39 backend_port: *const c_char,
40 ) -> *mut DohFrontend {
41 let addr = CStr::from_ptr(addr).to_str().unwrap();
42 let port = CStr::from_ptr(port).to_str().unwrap();
43 let backend_addr = CStr::from_ptr(backend_addr).to_str().unwrap();
44 let backend_port = CStr::from_ptr(backend_port).to_str().unwrap();
45
46 let socket_addr = to_socket_addr(addr, port).or_else(logging_and_return_err);
47 let backend_socket_addr =
48 to_socket_addr(backend_addr, backend_port).or_else(logging_and_return_err);
49 if socket_addr.is_err() || backend_socket_addr.is_err() {
50 return std::ptr::null_mut();
51 }
52
53 match DohFrontend::new(socket_addr.unwrap(), backend_socket_addr.unwrap()) {
54 Ok(c) => Box::into_raw(c),
55 Err(_) => std::ptr::null_mut(),
56 }
57 }
58
59 /// Starts the `DohFrontend` worker thread. Returns true if the worker thread is spawned
60 /// successfully; otherwise, it returns false.
61 #[no_mangle]
frontend_start(doh: &mut DohFrontend) -> bool62 pub extern "C" fn frontend_start(doh: &mut DohFrontend) -> bool {
63 doh.start().or_else(logging_and_return_err).is_ok()
64 }
65
66 /// Stops the `DohFrontend` worker thread.
67 #[no_mangle]
frontend_stop(doh: &mut DohFrontend) -> bool68 pub extern "C" fn frontend_stop(doh: &mut DohFrontend) -> bool {
69 doh.stop().or_else(logging_and_return_err).is_ok()
70 }
71
72 /// Deletes the `DohFrontend` created from `frontend_new`.
73 /// If the caller has called `frontend_start` to start `DohFrontend`, it has to call
74 /// call `frontend_stop` to stop the worker thread before deleting the object.
75 ///
76 /// # Safety
77 ///
78 /// The DohFrontend is not set to null pointer, caller needs to do it on its own.
79 #[no_mangle]
frontend_delete(doh: *mut DohFrontend)80 pub unsafe extern "C" fn frontend_delete(doh: *mut DohFrontend) {
81 if !doh.is_null() {
82 Box::from_raw(doh);
83 }
84 }
85
86 /// Sets server certificate to `DohFrontend`.
87 ///
88 /// # Safety
89 ///
90 /// The given certificate must be a null-terminated UTF-8 encoded string.
91 #[no_mangle]
frontend_set_certificate( doh: &mut DohFrontend, certificate: *const c_char, ) -> bool92 pub unsafe extern "C" fn frontend_set_certificate(
93 doh: &mut DohFrontend,
94 certificate: *const c_char,
95 ) -> bool {
96 if certificate.is_null() {
97 return false;
98 }
99 let certificate = CStr::from_ptr(certificate).to_str().unwrap();
100 doh.set_certificate(certificate).or_else(logging_and_return_err).is_ok()
101 }
102
103 /// Sets server private key to `DohFrontend`.
104 ///
105 /// # Safety
106 ///
107 /// The given private key must be a null-terminated UTF-8 encoded string.
108 #[no_mangle]
frontend_set_private_key( doh: &mut DohFrontend, private_key: *const c_char, ) -> bool109 pub unsafe extern "C" fn frontend_set_private_key(
110 doh: &mut DohFrontend,
111 private_key: *const c_char,
112 ) -> bool {
113 if private_key.is_null() {
114 return false;
115 }
116 let private_key = CStr::from_ptr(private_key).to_str().unwrap();
117 doh.set_private_key(private_key).or_else(logging_and_return_err).is_ok()
118 }
119
120 /// Configures the `DohFrontend` not to process DoH queries until a given number of DoH queries
121 /// are received. This function works even in the middle of the worker thread.
122 #[no_mangle]
frontend_set_delay_queries(doh: &mut DohFrontend, count: i32) -> bool123 pub extern "C" fn frontend_set_delay_queries(doh: &mut DohFrontend, count: i32) -> bool {
124 doh.set_delay_queries(count).or_else(logging_and_return_err).is_ok()
125 }
126
127 /// Configures the `DohFrontend` to use the given value for max_idle_timeout transport parameter.
128 #[no_mangle]
frontend_set_max_idle_timeout(doh: &mut DohFrontend, value: u64) -> bool129 pub extern "C" fn frontend_set_max_idle_timeout(doh: &mut DohFrontend, value: u64) -> bool {
130 doh.set_max_idle_timeout(value).or_else(logging_and_return_err).is_ok()
131 }
132
133 /// Configures the `DohFrontend` to use the given value for these transport parameters.
134 /// - initial_max_data
135 /// - initial_max_stream_data_bidi_local
136 /// - initial_max_stream_data_bidi_remote
137 /// - initial_max_stream_data_uni
138 #[no_mangle]
frontend_set_max_buffer_size(doh: &mut DohFrontend, value: u64) -> bool139 pub extern "C" fn frontend_set_max_buffer_size(doh: &mut DohFrontend, value: u64) -> bool {
140 doh.set_max_buffer_size(value).or_else(logging_and_return_err).is_ok()
141 }
142
143 /// Configures the `DohFrontend` to use the given value for initial_max_streams_bidi transport
144 /// parameter.
145 #[no_mangle]
frontend_set_max_streams_bidi(doh: &mut DohFrontend, value: u64) -> bool146 pub extern "C" fn frontend_set_max_streams_bidi(doh: &mut DohFrontend, value: u64) -> bool {
147 doh.set_max_streams_bidi(value).or_else(logging_and_return_err).is_ok()
148 }
149
150 /// Sets the `DohFrontend` to block or unblock sending any data.
151 #[no_mangle]
frontend_block_sending(doh: &mut DohFrontend, block: bool) -> bool152 pub extern "C" fn frontend_block_sending(doh: &mut DohFrontend, block: bool) -> bool {
153 doh.block_sending(block).or_else(logging_and_return_err).is_ok()
154 }
155
156 /// Gets the statistics of the `DohFrontend` and writes the result to |out|.
157 #[no_mangle]
frontend_stats(doh: &mut DohFrontend, out: &mut Stats) -> bool158 pub extern "C" fn frontend_stats(doh: &mut DohFrontend, out: &mut Stats) -> bool {
159 doh.request_stats()
160 .map(|stats| {
161 out.queries_received = stats.queries_received;
162 out.connections_accepted = stats.connections_accepted;
163 out.alive_connections = stats.alive_connections;
164 out.resumed_connections = stats.resumed_connections;
165 })
166 .or_else(logging_and_return_err)
167 .is_ok()
168 }
169
170 /// Resets `queries_received` field of `Stats` owned by the `DohFrontend`.
171 #[no_mangle]
frontend_stats_clear_queries(doh: &DohFrontend) -> bool172 pub extern "C" fn frontend_stats_clear_queries(doh: &DohFrontend) -> bool {
173 doh.stats_clear_queries().or_else(logging_and_return_err).is_ok()
174 }
175
176 /// Enable Rust debug logging.
177 #[no_mangle]
init_android_logger()178 pub extern "C" fn init_android_logger() {
179 android_logger::init_once(
180 android_logger::Config::default().with_tag("DohFrontend").with_min_level(log::Level::Debug),
181 );
182 }
183
to_socket_addr(addr: &str, port: &str) -> Result<SocketAddr>184 fn to_socket_addr(addr: &str, port: &str) -> Result<SocketAddr> {
185 let socket_addr = SocketAddr::new(IpAddr::from_str(addr)?, port.parse()?);
186 Ok(socket_addr)
187 }
188
logging_and_return_err<T, U: std::fmt::Debug>(e: U) -> Result<T>189 fn logging_and_return_err<T, U: std::fmt::Debug>(e: U) -> Result<T> {
190 warn!("logging_and_return_err: {:?}", e);
191 bail!("{:?}", e)
192 }
193