1 //! Starts the facade services that allow us to test the Bluetooth stack
2 
3 use bt_topshim::btif;
4 
5 use clap::{value_parser, Arg, Command};
6 use futures::channel::mpsc;
7 use futures::executor::block_on;
8 use futures::stream::StreamExt;
9 use grpcio::*;
10 use lazy_static::lazy_static;
11 use log::debug;
12 use nix::sys::signal;
13 use std::sync::{Arc, Mutex};
14 use tokio::runtime::Runtime;
15 
16 mod adapter_service;
17 mod gatt_service;
18 mod hf_client_service;
19 mod hfp_service;
20 mod media_service;
21 mod security_service;
22 mod utils;
23 
24 // This is needed for linking, libbt_shim_bridge needs symbols defined by
25 // bt_shim, however bt_shim depends on rust crates (future, tokio) that
26 // we use too, if we build and link them separately we ends with duplicate
27 // symbols. To solve that we build bt_shim with bt_topshim_facade so the rust
28 // compiler share the transitive dependencies.
29 //
30 // The `::*` is here to circuvent the single_component_path_imports from
31 // clippy that is denied on the rust command line so we can't just allow it.
32 // This is fine for now since bt_shim doesn't export anything
33 #[allow(unused)]
34 use bluetooth_core_rs_for_facade::*;
35 #[allow(unused)]
36 use bt_shim::*;
37 
main()38 fn main() {
39     // SAFETY: There is no signal handler installed before this.
40     let sigint = unsafe { install_sigint() };
41     bt_common::init_logging();
42     let rt = Arc::new(Runtime::new().unwrap());
43     rt.block_on(async_main(Arc::clone(&rt), sigint));
44 }
45 
clap_command() -> Command46 fn clap_command() -> Command {
47     Command::new("bluetooth_topshim_facade")
48         .about("The bluetooth topshim stack, with testing facades enabled and exposed via gRPC.")
49         .arg(
50             Arg::new("grpc-port")
51                 .long("grpc-port")
52                 .value_parser(value_parser!(u16))
53                 .default_value("8899"),
54         )
55         .arg(
56             Arg::new("root-server-port")
57                 .long("root-server-port")
58                 .value_parser(value_parser!(u16))
59                 .default_value("8897"),
60         )
61         .arg(
62             Arg::new("signal-port")
63                 .long("signal-port")
64                 .value_parser(value_parser!(u16))
65                 .default_value("8895"),
66         )
67         .arg(Arg::new("rootcanal-port").long("rootcanal-port").value_parser(value_parser!(u16)))
68         .arg(Arg::new("btsnoop").long("btsnoop"))
69         .arg(Arg::new("btsnooz").long("btsnooz"))
70         .arg(Arg::new("btconfig").long("btconfig"))
71         .arg(
72             Arg::new("start-stack-now")
73                 .long("start-stack-now")
74                 .value_parser(value_parser!(bool))
75                 .default_value("true"),
76         )
77 }
78 
async_main(rt: Arc<Runtime>, mut sigint: mpsc::UnboundedReceiver<()>)79 async fn async_main(rt: Arc<Runtime>, mut sigint: mpsc::UnboundedReceiver<()>) {
80     let matches = clap_command().get_matches();
81 
82     let grpc_port = *matches.get_one::<u16>("grpc-port").unwrap();
83     let _rootcanal_port = matches.get_one::<u16>("rootcanal-port").cloned();
84     let env = Arc::new(Environment::new(2));
85 
86     let btif_intf = Arc::new(Mutex::new(btif::get_btinterface().unwrap()));
87 
88     // AdapterServiceImpl::create initializes the stack; not the best practice because the side effect is hidden
89     let adapter_service_impl =
90         adapter_service::AdapterServiceImpl::create(rt.clone(), btif_intf.clone());
91 
92     let security_service_impl =
93         security_service::SecurityServiceImpl::create(rt.clone(), btif_intf.clone());
94 
95     let gatt_service_impl = gatt_service::GattServiceImpl::create(rt.clone(), btif_intf.clone());
96 
97     let hf_client_service_impl =
98         hf_client_service::HfClientServiceImpl::create(rt.clone(), btif_intf.clone());
99 
100     let hfp_service_impl = hfp_service::HfpServiceImpl::create(rt.clone(), btif_intf.clone());
101 
102     let media_service_impl = media_service::MediaServiceImpl::create(rt.clone(), btif_intf.clone());
103 
104     let start_stack_now = *matches.get_one::<bool>("start-stack-now").unwrap();
105 
106     if start_stack_now {
107         btif_intf.clone().lock().unwrap().enable();
108     }
109 
110     let mut server = ServerBuilder::new(env)
111         .register_service(adapter_service_impl)
112         .register_service(security_service_impl)
113         .register_service(gatt_service_impl)
114         .register_service(hf_client_service_impl)
115         .register_service(hfp_service_impl)
116         .register_service(media_service_impl)
117         .build()
118         .unwrap();
119     let addr = format!("0.0.0.0:{}", grpc_port);
120     let creds = ServerCredentials::insecure();
121     server.add_listening_port(addr, creds).unwrap();
122     server.start();
123 
124     sigint.next().await;
125     block_on(server.shutdown()).unwrap();
126 }
127 
128 // TODO: remove as this is a temporary nix-based hack to catch SIGINT
129 /// # Safety
130 ///
131 /// The old signal handler, if any, must be installed correctly.
install_sigint() -> mpsc::UnboundedReceiver<()>132 unsafe fn install_sigint() -> mpsc::UnboundedReceiver<()> {
133     let (tx, rx) = mpsc::unbounded();
134     *SIGINT_TX.lock().unwrap() = Some(tx);
135 
136     let sig_action = signal::SigAction::new(
137         signal::SigHandler::Handler(handle_sigint),
138         signal::SaFlags::empty(),
139         signal::SigSet::empty(),
140     );
141     // SAFETY: The caller guarantees that the old signal handler was installed correctly.
142     // TODO(b/292218119): Make sure `handle_sigint` only makes system calls that are safe for signal
143     // handlers, and only accesses global state through atomics. In particular, it must not take any
144     // shared locks.
145     unsafe {
146         signal::sigaction(signal::SIGINT, &sig_action).unwrap();
147     }
148 
149     rx
150 }
151 
152 lazy_static! {
153     static ref SIGINT_TX: Mutex<Option<mpsc::UnboundedSender<()>>> = Mutex::new(None);
154 }
155 
handle_sigint(_: i32)156 extern "C" fn handle_sigint(_: i32) {
157     let mut sigint_tx = SIGINT_TX.lock().unwrap();
158     if let Some(tx) = &*sigint_tx {
159         debug!("Stopping gRPC root server due to SIGINT");
160         tx.unbounded_send(()).unwrap();
161     }
162     *sigint_tx = None;
163 }
164 
165 #[cfg(test)]
166 mod tests {
167     use super::*;
168 
169     #[test]
verify_comand()170     fn verify_comand() {
171         clap_command().debug_assert();
172     }
173 }
174