• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Bluetooth testing root facade service
2 
3 use bluetooth_rs::hal::facade::HciHalFacadeService;
4 use bluetooth_rs::hci::controller_facade::ControllerFacadeService;
5 use bluetooth_rs::hci::facade::HciFacadeService;
6 use bluetooth_rs::Stack;
7 use bt_facade_proto::rootservice::*;
8 use bt_facade_proto::rootservice_grpc::{create_root_facade, RootFacade};
9 use futures::executor::block_on;
10 use grpcio::*;
11 use std::sync::Arc;
12 use tokio::runtime::Runtime;
13 use tokio::sync::mpsc::{channel, Sender};
14 use tokio::sync::oneshot;
15 
16 /// Bluetooth testing root facade service
17 #[derive(Clone)]
18 pub struct RootFacadeService {
19     rt: Arc<Runtime>,
20     manager: FacadeServiceManager,
21 }
22 
23 impl RootFacadeService {
24     /// Create a new instance of the root facade service
create( rt: Arc<Runtime>, grpc_port: u16, rootcanal_port: Option<u16>, snoop_path: Option<String>, ) -> grpcio::Service25     pub fn create(
26         rt: Arc<Runtime>,
27         grpc_port: u16,
28         rootcanal_port: Option<u16>,
29         snoop_path: Option<String>,
30     ) -> grpcio::Service {
31         create_root_facade(Self {
32             rt: rt.clone(),
33             manager: FacadeServiceManager::create(rt, grpc_port, rootcanal_port, snoop_path),
34         })
35     }
36 }
37 
38 impl RootFacade for RootFacadeService {
start_stack( &mut self, _ctx: RpcContext<'_>, req: StartStackRequest, sink: UnarySink<StartStackResponse>, )39     fn start_stack(
40         &mut self,
41         _ctx: RpcContext<'_>,
42         req: StartStackRequest,
43         sink: UnarySink<StartStackResponse>,
44     ) {
45         self.rt.block_on(self.manager.start(req)).unwrap();
46         sink.success(StartStackResponse::default());
47     }
48 
stop_stack( &mut self, _ctx: RpcContext<'_>, _req: StopStackRequest, sink: UnarySink<StopStackResponse>, )49     fn stop_stack(
50         &mut self,
51         _ctx: RpcContext<'_>,
52         _req: StopStackRequest,
53         sink: UnarySink<StopStackResponse>,
54     ) {
55         self.rt.block_on(self.manager.stop()).unwrap();
56         sink.success(StopStackResponse::default());
57     }
58 }
59 
60 #[derive(Debug)]
61 enum LifecycleCommand {
62     Start { req: StartStackRequest, done: oneshot::Sender<()> },
63     Stop { done: oneshot::Sender<()> },
64 }
65 
66 #[derive(Clone)]
67 struct FacadeServiceManager {
68     lifecycle_tx: Sender<LifecycleCommand>,
69 }
70 
71 struct FacadeServer {
72     server: Server,
73     stack: Stack,
74 }
75 
76 impl FacadeServer {
start(stack: Stack, req: StartStackRequest, grpc_port: u16) -> Self77     async fn start(stack: Stack, req: StartStackRequest, grpc_port: u16) -> Self {
78         let mut services = Vec::new();
79         match req.get_module_under_test() {
80             BluetoothModule::HAL => {
81                 services.push(stack.get_grpc::<HciHalFacadeService>().await);
82             }
83             BluetoothModule::HCI | BluetoothModule::HCI_INTERFACES => {
84                 services.push(stack.get_grpc::<HciFacadeService>().await);
85                 services.push(stack.get_grpc::<ControllerFacadeService>().await);
86             }
87             _ => unimplemented!(),
88         }
89 
90         let env = Arc::new(Environment::new(2));
91         let mut builder = ServerBuilder::new(env).bind("0.0.0.0", grpc_port);
92         for service in services {
93             builder = builder.register_service(service);
94         }
95 
96         let mut server = builder.build().unwrap();
97         server.start();
98 
99         Self { server, stack }
100     }
101 
stop(&mut self)102     async fn stop(&mut self) {
103         self.server.shutdown().await.unwrap();
104         self.stack.stop().await;
105     }
106 }
107 
108 /// Result type
109 type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
110 
111 impl FacadeServiceManager {
create( rt: Arc<Runtime>, grpc_port: u16, rootcanal_port: Option<u16>, snoop_path: Option<String>, ) -> Self112     fn create(
113         rt: Arc<Runtime>,
114         grpc_port: u16,
115         rootcanal_port: Option<u16>,
116         snoop_path: Option<String>,
117     ) -> Self {
118         let (tx, mut rx) = channel::<LifecycleCommand>(1);
119         let local_rt = rt.clone();
120         rt.spawn(async move {
121             let mut server: Option<FacadeServer> = None;
122             while let Some(cmd) = rx.recv().await {
123                 match cmd {
124                     LifecycleCommand::Start { req, done } => {
125                         let stack = Stack::new(local_rt.clone()).await;
126                         stack.set_rootcanal_port(rootcanal_port).await;
127                         stack.configure_snoop(snoop_path.clone()).await;
128                         server = Some(FacadeServer::start(stack, req, grpc_port).await);
129                         done.send(()).unwrap();
130                     }
131                     LifecycleCommand::Stop { done } => {
132                         if let Some(s) = &mut server {
133                             block_on(s.stop());
134                             server = None;
135                         }
136                         done.send(()).unwrap();
137                     }
138                 }
139             }
140         });
141 
142         Self { lifecycle_tx: tx }
143     }
144 
start(&self, req: StartStackRequest) -> Result<()>145     async fn start(&self, req: StartStackRequest) -> Result<()> {
146         let (tx, rx) = oneshot::channel();
147         self.lifecycle_tx.send(LifecycleCommand::Start { req, done: tx }).await?;
148         rx.await?;
149         Ok(())
150     }
151 
stop(&self) -> Result<()>152     async fn stop(&self) -> Result<()> {
153         let (tx, rx) = oneshot::channel();
154         self.lifecycle_tx.send(LifecycleCommand::Stop { done: tx }).await?;
155         rx.await?;
156         Ok(())
157     }
158 }
159