xref: /aosp_15_r20/tools/netsim/rust/daemon/src/grpc_server/backend.rs (revision cf78ab8cffb8fc9207af348f23af247fb04370a6)
1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use crate::devices::chip;
16 use crate::devices::device::AddChipResult;
17 use crate::devices::devices_handler;
18 use crate::transport::grpc::RustGrpcTransport;
19 use crate::wireless;
20 use crate::wireless::packet::{register_transport, unregister_transport};
21 use anyhow::{anyhow, Context};
22 use bytes::Bytes;
23 use futures_util::{FutureExt as _, TryFutureExt as _, TryStreamExt as _};
24 use log::{info, warn};
25 use netsim_proto::common::ChipKind as ProtoChipKind;
26 use netsim_proto::hci_packet::hcipacket::PacketType;
27 use netsim_proto::packet_streamer::{PacketRequest, PacketResponse};
28 use netsim_proto::packet_streamer_grpc::PacketStreamer;
29 use netsim_proto::startup::ChipInfo;
30 use protobuf::Enum;
31 
add_chip(initial_info: &ChipInfo, device_guid: &str) -> anyhow::Result<AddChipResult>32 fn add_chip(initial_info: &ChipInfo, device_guid: &str) -> anyhow::Result<AddChipResult> {
33     let chip_kind =
34         initial_info.chip.kind.enum_value().map_err(|v| anyhow!("unknown chip kind {v}"))?;
35     let chip = &initial_info.chip;
36     // TODO(b/323899010): Avoid having cfg(test) in mainline code
37     #[cfg(not(test))]
38     let wireless_create_param = match &chip_kind {
39         ProtoChipKind::BLUETOOTH => {
40             wireless::CreateParam::Bluetooth(wireless::bluetooth::CreateParams {
41                 address: chip.address.clone(),
42                 bt_properties: Some(chip.bt_properties.clone()),
43             })
44         }
45         ProtoChipKind::WIFI => wireless::CreateParam::Wifi(wireless::wifi::CreateParams {}),
46         ProtoChipKind::UWB => wireless::CreateParam::Uwb(wireless::uwb::CreateParams {
47             address: chip.address.clone(),
48         }),
49         _ => return Err(anyhow!("The provided chip kind is unsupported: {:?}", chip.kind)),
50     };
51     #[cfg(test)]
52     let wireless_create_param =
53         wireless::CreateParam::Mock(wireless::mocked::CreateParams { chip_kind });
54 
55     let chip_create_params = chip::CreateParams {
56         kind: chip_kind,
57         address: chip.address.clone(),
58         name: Some(chip.id.clone()),
59         manufacturer: chip.manufacturer.clone(),
60         product_name: chip.product_name.clone(),
61     };
62 
63     devices_handler::add_chip(
64         device_guid,
65         &initial_info.name,
66         &chip_create_params,
67         &wireless_create_param,
68         initial_info.device_info.clone().unwrap_or_default(),
69     )
70     .map_err(|err| anyhow!(err))
71 }
72 
73 #[derive(Clone)]
74 pub struct PacketStreamerService;
75 impl PacketStreamer for PacketStreamerService {
stream_packets( &mut self, ctx: ::grpcio::RpcContext, mut packet_request: ::grpcio::RequestStream<PacketRequest>, sink: ::grpcio::DuplexSink<PacketResponse>, )76     fn stream_packets(
77         &mut self,
78         ctx: ::grpcio::RpcContext,
79         mut packet_request: ::grpcio::RequestStream<PacketRequest>,
80         sink: ::grpcio::DuplexSink<PacketResponse>,
81     ) {
82         let peer = ctx.peer().clone();
83         let f = async move {
84             info!("grpc_server new packet_stream for peer {}", &peer);
85 
86             let request = packet_request.try_next().await?.context("initial info")?;
87             let initial_info: &ChipInfo = request.initial_info();
88 
89             let result = add_chip(initial_info, &peer)?;
90 
91             register_transport(result.chip_id, Box::new(RustGrpcTransport { sink }));
92 
93             while let Some(request) = packet_request.try_next().await? {
94                 let chip_kind = &initial_info.chip.kind.unwrap();
95                 match chip_kind {
96                     ProtoChipKind::WIFI | ProtoChipKind::UWB => {
97                         if !request.has_packet() {
98                             warn!("unknown packet type from chip_id: {}", result.chip_id);
99                             continue;
100                         }
101                         let packet: Bytes = request.packet().to_vec().into();
102                         wireless::handle_request(
103                             result.chip_id,
104                             &packet,
105                             PacketType::HCI_PACKET_UNSPECIFIED.value() as u8,
106                         );
107                     }
108                     ProtoChipKind::BLUETOOTH => {
109                         if !request.has_hci_packet() {
110                             warn!("unknown packet type from chip_id: {}", result.chip_id);
111                             continue;
112                         }
113                         let packet: Bytes = request.hci_packet().packet.to_vec().into();
114                         wireless::handle_request(
115                             result.chip_id,
116                             &packet,
117                             request.hci_packet().packet_type.unwrap().value() as u8,
118                         );
119                     }
120                     _ => {
121                         warn!("unknown control packet chip_kind: {:?}", chip_kind);
122                         break;
123                     }
124                 };
125             }
126             unregister_transport(result.chip_id);
127             if let Err(e) = devices_handler::remove_chip(result.device_id, result.chip_id) {
128                 warn!("failed to remove chip: {}", e);
129             }
130             Ok(())
131         }
132         .map_err(|e: anyhow::Error| warn!("failed to stream packets: {:?}", e))
133         .map(|_| ());
134         ctx.spawn(f)
135     }
136 }
137