1 //! Starts the facade services that allow us to test the Bluetooth stack
2
3 #[macro_use]
4 extern crate clap;
5 use clap::{App, Arg};
6
7 #[macro_use]
8 extern crate lazy_static;
9
10 use bluetooth_with_facades::RootFacadeService;
11 use futures::channel::mpsc;
12 use futures::executor::block_on;
13 use futures::stream::StreamExt;
14 use grpcio::*;
15 use log::debug;
16 use nix::sys::signal;
17 use std::sync::{Arc, Mutex};
18 use tokio::runtime::Runtime;
19
main()20 fn main() {
21 let sigint = install_sigint();
22 bt_common::init_logging();
23 let rt = Arc::new(Runtime::new().unwrap());
24 rt.block_on(async_main(Arc::clone(&rt), sigint));
25 }
26
async_main(rt: Arc<Runtime>, mut sigint: mpsc::UnboundedReceiver<()>)27 async fn async_main(rt: Arc<Runtime>, mut sigint: mpsc::UnboundedReceiver<()>) {
28 let matches = App::new("bluetooth_with_facades")
29 .about("The bluetooth stack, with testing facades enabled and exposed via gRPC.")
30 .arg(
31 Arg::with_name("root-server-port")
32 .long("root-server-port")
33 .default_value("8897")
34 .takes_value(true),
35 )
36 .arg(Arg::with_name("grpc-port").long("grpc-port").default_value("8899").takes_value(true))
37 .arg(
38 Arg::with_name("signal-port")
39 .long("signal-port")
40 .default_value("8895")
41 .takes_value(true),
42 )
43 .arg(Arg::with_name("rootcanal-port").long("rootcanal-port").takes_value(true))
44 .arg(Arg::with_name("btsnoop").long("btsnoop").takes_value(true))
45 .arg(Arg::with_name("btsnooz").long("btsnooz").takes_value(true))
46 .arg(Arg::with_name("btconfig").long("btconfig").takes_value(true))
47 .get_matches();
48
49 let root_server_port = value_t!(matches, "root-server-port", u16).unwrap();
50 let grpc_port = value_t!(matches, "grpc-port", u16).unwrap();
51 let rootcanal_port = value_t!(matches, "rootcanal-port", u16).ok();
52 let env = Arc::new(Environment::new(2));
53 let mut server = ServerBuilder::new(env)
54 .register_service(RootFacadeService::create(
55 rt,
56 grpc_port,
57 rootcanal_port,
58 matches.value_of("btsnoop").map(String::from),
59 ))
60 .bind("0.0.0.0", root_server_port)
61 .build()
62 .unwrap();
63 server.start();
64
65 sigint.next().await;
66 block_on(server.shutdown()).unwrap();
67 }
68
69 // TODO: remove as this is a temporary nix-based hack to catch SIGINT
install_sigint() -> mpsc::UnboundedReceiver<()>70 fn install_sigint() -> mpsc::UnboundedReceiver<()> {
71 let (tx, rx) = mpsc::unbounded();
72 *SIGINT_TX.lock().unwrap() = Some(tx);
73
74 let sig_action = signal::SigAction::new(
75 signal::SigHandler::Handler(handle_sigint),
76 signal::SaFlags::empty(),
77 signal::SigSet::empty(),
78 );
79 unsafe {
80 signal::sigaction(signal::SIGINT, &sig_action).unwrap();
81 }
82
83 rx
84 }
85
86 lazy_static! {
87 static ref SIGINT_TX: Mutex<Option<mpsc::UnboundedSender<()>>> = Mutex::new(None);
88 }
89
handle_sigint(_: i32)90 extern "C" fn handle_sigint(_: i32) {
91 let mut sigint_tx = SIGINT_TX.lock().unwrap();
92 if let Some(tx) = &*sigint_tx {
93 debug!("Stopping gRPC root server due to SIGINT");
94 tx.unbounded_send(()).unwrap();
95 }
96 *sigint_tx = None;
97 }
98