Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit db7d1795 authored by Zach Johnson's avatar Zach Johnson
Browse files

rusty-gd: move hci facade client contents to root server

Bug: 171749953
Tag: #gd-refactor
Test: gd/cert/run --rhost
Change-Id: I97ef3f26cb4a8458ebb7a9eda1df0b4391459a1c
parent 7796be10
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@ rust_library {
    srcs: ["src/lib.rs"],
    edition: "2018",
    rustlibs: [
      "libbt_hal",
      "libbt_hci",
      "libbt_facade_rootservice_proto",
      "libbt_facade_common_proto",
      "libfutures",
+117 −9
Original line number Diff line number Diff line
@@ -11,17 +11,26 @@ pub mod empty {
pub use bt_facade_common_proto::common;
pub use bt_facade_rootservice_proto::rootservice;

use bt_hal::rootcanal_hal::{RootcanalConfig, RootcanalHal};
use bt_hci::facade::hci_facade_server::HciLayerFacadeService;
use bt_hci::Hci;

use tokio::runtime::Runtime;
use tokio::sync::mpsc::{channel, Sender};
use tokio::sync::oneshot;

use grpcio::*;

use std::sync::Arc;

use futures::executor::block_on;

/// Bluetooth testing root facade service
#[derive(Clone)]
pub struct RootFacadeService {
    /// Tokio runtime
    pub rt: Arc<Runtime>,
    rt: Arc<Runtime>,
    manager: FacadeServiceManager,
}

use bt_facade_rootservice_proto::rootservice::*;
@@ -30,8 +39,15 @@ use rootservice_grpc::RootFacade;

impl RootFacadeService {
    /// Create a new instance of the root facade service
    pub fn create(rt: Arc<Runtime>) -> grpcio::Service {
        create_root_facade(Self { rt })
    pub fn create(
        rt: Arc<Runtime>,
        grpc_port: u16,
        rootcanal_port: Option<u16>,
    ) -> grpcio::Service {
        create_root_facade(Self {
            rt: rt.clone(),
            manager: FacadeServiceManager::create(rt, grpc_port, rootcanal_port),
        })
    }
}

@@ -39,18 +55,110 @@ impl RootFacade for RootFacadeService {
    fn start_stack(
        &mut self,
        _ctx: RpcContext<'_>,
        mut _cmd: StartStackRequest,
        _sink: UnarySink<StartStackResponse>,
        req: StartStackRequest,
        sink: UnarySink<StartStackResponse>,
    ) {
        unimplemented!()
        self.rt.block_on(self.manager.start(req)).unwrap();
        sink.success(StartStackResponse::default());
    }

    fn stop_stack(
        &mut self,
        _ctx: RpcContext<'_>,
        mut _cmd: StopStackRequest,
        _sink: UnarySink<StopStackResponse>,
        _req: StopStackRequest,
        sink: UnarySink<StopStackResponse>,
    ) {
        unimplemented!()
        self.rt.block_on(self.manager.stop()).unwrap();
        sink.success(StopStackResponse::default());
    }
}

#[derive(Debug)]
enum LifecycleCommand {
    Start {
        req: StartStackRequest,
        done: oneshot::Sender<()>,
    },
    Stop {
        done: oneshot::Sender<()>,
    },
}

#[derive(Clone)]
struct FacadeServiceManager {
    lifecycle_tx: Sender<LifecycleCommand>,
}

/// Result type
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;

impl FacadeServiceManager {
    fn create(rt: Arc<Runtime>, grpc_port: u16, rootcanal_port: Option<u16>) -> Self {
        let (tx, mut rx) = channel::<LifecycleCommand>(1);
        let local_rt = rt.clone();
        local_rt.spawn(async move {
            let mut server: Option<Server> = None;
            while let Some(cmd) = rx.recv().await {
                match cmd {
                    LifecycleCommand::Start { req, done } => {
                        server =
                            Some(Self::start_internal(&rt, req, grpc_port, rootcanal_port).await);
                        done.send(()).unwrap();
                    }
                    LifecycleCommand::Stop { done } => {
                        if let Some(s) = &mut server {
                            block_on(s.shutdown()).unwrap();
                            server = None;
                        }
                        done.send(()).unwrap();
                    }
                }
            }
        });

        Self { lifecycle_tx: tx }
    }

    async fn start(&self, req: StartStackRequest) -> Result<()> {
        let (tx, rx) = oneshot::channel();
        self.lifecycle_tx
            .send(LifecycleCommand::Start { req, done: tx })
            .await?;
        rx.await?;
        Ok(())
    }

    async fn stop(&self) -> Result<()> {
        let (tx, rx) = oneshot::channel();
        self.lifecycle_tx
            .send(LifecycleCommand::Stop { done: tx })
            .await?;
        rx.await?;
        Ok(())
    }

    // TODO this is messy and needs to be overhauled to support bringing up the stack to partial
    // layers. Will be cleaned up soon.
    async fn start_internal(
        rt: &Arc<Runtime>,
        _req: StartStackRequest,
        grpc_port: u16,
        rootcanal_port: Option<u16>,
    ) -> Server {
        let env = Arc::new(Environment::new(2));
        let hal_exports = RootcanalHal::start(
            RootcanalConfig::new(rootcanal_port.unwrap(), "127.0.0.1"),
            Arc::clone(&rt),
        )
        .await
        .unwrap();
        let hci_exports = Hci::start(hal_exports, Arc::clone(&rt));
        let mut server = ServerBuilder::new(env)
            .register_service(HciLayerFacadeService::create(hci_exports, Arc::clone(&rt)))
            .bind("0.0.0.0", grpc_port)
            .build()
            .unwrap();
        server.start();
        server
    }
}
+2 −6
Original line number Diff line number Diff line
@@ -72,15 +72,11 @@ async fn async_main(rt: Arc<Runtime>, mut sigint: mpsc::UnboundedReceiver<()>) {
    let root_server_port = value_t!(matches, "root-server-port", u16).unwrap();
    let grpc_port = value_t!(matches, "grpc-port", u16).unwrap();
    let signal_port = value_t!(matches, "signal-port", u16).unwrap();

    println!(
        "root server port: {}, grpc port: {}, signal port {}",
        root_server_port, grpc_port, signal_port
    );
    let rootcanal_port = value_t!(matches, "rootcanal-port", u16).ok();

    let env = Arc::new(Environment::new(2));
    let mut server = ServerBuilder::new(env)
        .register_service(RootFacadeService::create(rt))
        .register_service(RootFacadeService::create(rt, grpc_port, rootcanal_port))
        .bind("0.0.0.0", root_server_port)
        .build()
        .unwrap();
+0 −34
Original line number Diff line number Diff line
@@ -20,37 +20,3 @@ rust_library {
    ],
    host_supported: true,
}

rust_binary {
    name: "hci_facade_client",
    crate_name: "hci_facade_client",
    srcs: ["src/facade/hci_facade_client.rs"],
    edition: "2018",
    rustlibs: [
        "libbt_hal",
        "libbt_hci",
        "libbytes",
        "libfutures",
        "libgrpcio",
        "libprotobuf",
        "libtokio",
    ],
    host_supported: true,
}

rust_binary {
    name: "hci_facade_main",
    crate_name: "hci_facade_main",
    srcs: ["src/facade/hci_facade_main.rs"],
    edition: "2018",
    rustlibs: [
        "libbt_hal",
        "libbt_hci",
        "libbytes",
        "libfutures",
        "libgrpcio",
        "libprotobuf",
        "libtokio",
    ],
    host_supported: true,
}
+0 −80
Original line number Diff line number Diff line
//! A client that connects to HciLayerFacadeService

// TODO(qasimj): This client is temporary and is used for testing only.
// It will be removed later.

use grpcio::*;

use std::sync::Arc;

use futures::TryStreamExt;

use bt_hci as hci;
use hci::facade::protos::empty::Empty;
use hci::facade::protos::facade::{CommandMsg, EventCodeMsg};
use hci::facade::protos::hci_layer_facade_grpc::HciLayerFacadeClient;

fn new_event_code(code: u32) -> EventCodeMsg {
    let mut event_code = EventCodeMsg::default();
    event_code.set_code(code);
    event_code
}

fn new_command(bytes: Vec<u8>) -> CommandMsg {
    let mut cmd = CommandMsg::default();
    cmd.set_command(bytes);
    cmd
}

async fn register_event_handler(
    client: &HciLayerFacadeClient,
    event_code: &EventCodeMsg,
) -> Result<()> {
    let register_event_handler = client.register_event_handler_async(event_code)?;
    register_event_handler.await?;

    Ok(())
}

async fn enqueue_command_with_complete(
    client: &HciLayerFacadeClient,
    cmd: &CommandMsg,
) -> Result<()> {
    let enqueue = client.enqueue_command_with_complete_async(cmd)?;
    enqueue.await?;
    Ok(())
}

async fn fetch_events(client: &HciLayerFacadeClient) -> Result<()> {
    let mut fetch_events = client.fetch_events(&Empty::new())?;
    while let Some(event) = fetch_events.try_next().await? {
        println!("Received Event: {:?}", event);
    }
    Ok(())
}

async fn async_main() -> Result<()> {
    let env = Arc::new(Environment::new(2));
    let channel = ChannelBuilder::new(env).connect("pop-os:8999");
    let client = HciLayerFacadeClient::new(channel);

    println!("Registering event handler!");
    register_event_handler(&client, &new_event_code(0x0eu32)).await?;

    let handle = fetch_events(&client);
    let cmd = &new_command(vec![0x0du8, 0x08, 0x04, 0x07, 0x00, 0x06, 0x00]);

    println!("Enqueue commands");
    enqueue_command_with_complete(&client, cmd).await.unwrap();

    enqueue_command_with_complete(&client, cmd).await.unwrap();

    println!("Waiting for events...");
    handle.await.unwrap();

    Ok(())
}

fn main() {
    futures::executor::block_on(async_main()).unwrap();
}
Loading