xref: /aosp_15_r20/tools/netsim/rust/daemon/src/transport/socket.rs (revision cf78ab8cffb8fc9207af348f23af247fb04370a6)
1 // Copyright 2023 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 super::h4::PacketError;
16 use crate::devices::chip::{self, ChipIdentifier};
17 use crate::devices::devices_handler::{add_chip, remove_chip};
18 use crate::transport::h4;
19 use crate::wireless;
20 use crate::wireless::packet::{register_transport, unregister_transport, Response};
21 use bytes::Bytes;
22 use log::{error, info, warn};
23 use netsim_proto::common::ChipKind;
24 use netsim_proto::startup::DeviceInfo as ProtoDeviceInfo;
25 use std::io::{ErrorKind, Write};
26 use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, TcpListener, TcpStream};
27 use std::thread;
28 
29 // The HCI server implements the Bluetooth UART transport protocol
30 // (a.k.a. H4) over TCP. Each new connection on the HCI port spawns a
31 // new virtual controller associated with a new device.
32 
33 /// Start the socket-based transport.
34 ///
35 /// The socket transport reads/writes host-controller messages
36 /// for bluetooth (h4 hci) over a [TcpStream] transport.
37 ///
38 
39 struct SocketTransport {
40     stream: TcpStream,
41 }
42 
43 impl Response for SocketTransport {
response(&mut self, packet: Bytes, packet_type: u8)44     fn response(&mut self, packet: Bytes, packet_type: u8) {
45         let mut buffer = Vec::new();
46         buffer.push(packet_type);
47         buffer.extend(packet);
48         if let Err(e) = self.stream.write_all(&buffer[..]) {
49             error!("error writing {}", e);
50         };
51     }
52 }
53 
run_socket_transport(hci_port: u16)54 pub fn run_socket_transport(hci_port: u16) {
55     thread::Builder::new()
56         .name("hci_transport".to_string())
57         .spawn(move || {
58             accept_incoming(hci_port)
59                 .unwrap_or_else(|e| error!("Failed to accept incoming stream: {:?}", e));
60         })
61         .unwrap();
62 }
63 
accept_incoming(hci_port: u16) -> std::io::Result<()>64 fn accept_incoming(hci_port: u16) -> std::io::Result<()> {
65     let listener = TcpListener::bind(SocketAddr::from((Ipv4Addr::LOCALHOST, hci_port))).or_else(|e| {
66             warn!("Failed to bind to 127.0.0.1:{hci_port} in netsimd socket server, Trying [::1]:{hci_port}. {e:?}");
67             TcpListener::bind(SocketAddr::from((Ipv6Addr::LOCALHOST, hci_port)))
68         }
69     )?;
70     info!("Hci socket server is listening on: {}", hci_port);
71 
72     for stream in listener.incoming() {
73         let stream = stream?;
74         // the socket address of the remote peer of this TCP connection
75         info!("Hci client address: {}", stream.peer_addr().unwrap());
76         thread::Builder::new()
77             .name("hci_transport client".to_string())
78             .spawn(move || {
79                 handle_hci_client(stream);
80             })
81             .unwrap();
82     }
83     Ok(())
84 }
85 
handle_hci_client(stream: TcpStream)86 fn handle_hci_client(stream: TcpStream) {
87     // ...
88     let chip_create_params = chip::CreateParams {
89         kind: ChipKind::BLUETOOTH,
90         address: String::new(),
91         name: Some(format!("socket-{}", stream.peer_addr().unwrap())),
92         manufacturer: "Google".to_string(),
93         product_name: "Google".to_string(),
94     };
95     #[cfg(not(test))]
96     let wireless_create_params =
97         wireless::CreateParam::Bluetooth(wireless::bluetooth::CreateParams {
98             address: String::new(),
99             bt_properties: None,
100         });
101     #[cfg(test)]
102     let wireless_create_params = wireless::CreateParam::Mock(wireless::mocked::CreateParams {
103         chip_kind: ChipKind::BLUETOOTH,
104     });
105     let device_info = ProtoDeviceInfo { kind: "HCI_SOCKET".to_string(), ..Default::default() };
106     let result = match add_chip(
107         &stream.peer_addr().unwrap().port().to_string(),
108         &format!("socket-{}", stream.peer_addr().unwrap()),
109         &chip_create_params,
110         &wireless_create_params,
111         device_info,
112     ) {
113         Ok(chip_result) => chip_result,
114         Err(err) => {
115             warn!("{err}");
116             return;
117         }
118     };
119     let tcp_rx = stream.try_clone().unwrap();
120     register_transport(result.chip_id, Box::new(SocketTransport { stream }));
121 
122     let _ = reader(tcp_rx, ChipKind::BLUETOOTH, result.chip_id);
123 
124     // unregister before remove_chip because facade may re-use facade_id
125     // on an intertwining create_chip and the unregister here might remove
126     // the recently added chip creating a disconnected transport.
127     unregister_transport(result.chip_id);
128 
129     if let Err(err) = remove_chip(result.device_id, result.chip_id) {
130         warn!("{err}");
131     };
132     info!("Removed chip: device_id: {} chip_id: {}.", result.device_id, result.chip_id);
133 }
134 
135 /// read from the socket and pass to the packet hub.
136 ///
reader(mut tcp_rx: TcpStream, kind: ChipKind, chip_id: ChipIdentifier) -> std::io::Result<()>137 fn reader(mut tcp_rx: TcpStream, kind: ChipKind, chip_id: ChipIdentifier) -> std::io::Result<()> {
138     loop {
139         if let ChipKind::BLUETOOTH = kind {
140             match h4::read_h4_packet(&mut tcp_rx) {
141                 Ok(packet) => {
142                     wireless::handle_request(chip_id, &packet.payload, packet.h4_type);
143                 }
144                 Err(PacketError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
145                     info!("End socket reader connection with {}.", &tcp_rx.peer_addr().unwrap());
146                     return Ok(());
147                 }
148                 Err(e) => {
149                     error!("End socket reader connection with {}. Failed to reading hci control packet: {:?}",  &tcp_rx.peer_addr().unwrap(), e);
150                     return Ok(());
151                 }
152             }
153         }
154     }
155 }
156