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