1 //! Bluetooth testing root facade service 2 3 use bt_facade_proto::rootservice::*; 4 use bt_facade_proto::rootservice_grpc::{create_root_facade, RootFacade}; 5 use bt_hal::facade::HciHalFacadeService; 6 use bt_hci::controller_facade::ControllerFacadeService; 7 use bt_hci::facade::HciFacadeService; 8 use bt_main::Stack; 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 => { 84 services.push(stack.get_grpc::<HciFacadeService>().await); 85 } 86 BluetoothModule::HCI_INTERFACES => { 87 services.push(stack.get_grpc::<HciFacadeService>().await); 88 services.push(stack.get_grpc::<ControllerFacadeService>().await); 89 } 90 _ => unimplemented!(), 91 } 92 93 let env = Arc::new(Environment::new(2)); 94 let mut builder = ServerBuilder::new(env).bind("0.0.0.0", grpc_port); 95 for service in services { 96 builder = builder.register_service(service); 97 } 98 99 let mut server = builder.build().unwrap(); 100 server.start(); 101 102 Self { server, stack } 103 } 104 stop(&mut self)105 async fn stop(&mut self) { 106 self.server.shutdown().await.unwrap(); 107 self.stack.stop().await; 108 } 109 } 110 111 /// Result type 112 type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>; 113 114 impl FacadeServiceManager { create( rt: Arc<Runtime>, grpc_port: u16, rootcanal_port: Option<u16>, snoop_path: Option<String>, ) -> Self115 fn create( 116 rt: Arc<Runtime>, 117 grpc_port: u16, 118 rootcanal_port: Option<u16>, 119 snoop_path: Option<String>, 120 ) -> Self { 121 let (tx, mut rx) = channel::<LifecycleCommand>(1); 122 let local_rt = rt.clone(); 123 rt.spawn(async move { 124 let mut server: Option<FacadeServer> = None; 125 while let Some(cmd) = rx.recv().await { 126 match cmd { 127 LifecycleCommand::Start { req, done } => { 128 let stack = Stack::new(local_rt.clone()).await; 129 stack.set_rootcanal_port(rootcanal_port).await; 130 stack.configure_snoop(snoop_path.clone()).await; 131 server = Some(FacadeServer::start(stack, req, grpc_port).await); 132 done.send(()).unwrap(); 133 } 134 LifecycleCommand::Stop { done } => { 135 if let Some(s) = &mut server { 136 block_on(s.stop()); 137 server = None; 138 } 139 done.send(()).unwrap(); 140 } 141 } 142 } 143 }); 144 145 Self { lifecycle_tx: tx } 146 } 147 start(&self, req: StartStackRequest) -> Result<()>148 async fn start(&self, req: StartStackRequest) -> Result<()> { 149 let (tx, rx) = oneshot::channel(); 150 self.lifecycle_tx.send(LifecycleCommand::Start { req, done: tx }).await?; 151 rx.await?; 152 Ok(()) 153 } 154 stop(&self) -> Result<()>155 async fn stop(&self) -> Result<()> { 156 let (tx, rx) = oneshot::channel(); 157 self.lifecycle_tx.send(LifecycleCommand::Stop { done: tx }).await?; 158 rx.await?; 159 Ok(()) 160 } 161 } 162