1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "hal/hci_hal_host_rootcanal.h" 18 #include "hal/hci_hal.h" 19 #include "hal/serialize_packet.h" 20 21 #include <fcntl.h> 22 #include <netdb.h> 23 #include <netinet/in.h> 24 #include <netinet/ip.h> 25 #include <sys/socket.h> 26 #include <sys/types.h> 27 #include <unistd.h> 28 #include <cstring> 29 #include <queue> 30 #include <thread> 31 #include <utility> 32 #include <vector> 33 34 #include <gtest/gtest.h> 35 36 #include "os/log.h" 37 #include "os/thread.h" 38 #include "os/utils.h" 39 #include "packet/raw_builder.h" 40 41 using ::bluetooth::os::Thread; 42 43 namespace bluetooth { 44 namespace hal { 45 namespace { 46 47 uint16_t kTestPort = 6537; 48 49 constexpr uint8_t kH4Command = 0x01; 50 constexpr uint8_t kH4Acl = 0x02; 51 constexpr uint8_t kH4Sco = 0x03; 52 constexpr uint8_t kH4Event = 0x04; 53 54 using H4Packet = std::vector<uint8_t>; 55 56 std::queue<std::pair<uint8_t, HciPacket>> incoming_packets_queue_; 57 58 class TestHciHalCallbacks : public HciHalCallbacks { 59 public: 60 void hciEventReceived(HciPacket packet) override { 61 incoming_packets_queue_.emplace(kH4Event, packet); 62 } 63 64 void aclDataReceived(HciPacket packet) override { 65 incoming_packets_queue_.emplace(kH4Acl, packet); 66 } 67 68 void scoDataReceived(HciPacket packet) override { 69 incoming_packets_queue_.emplace(kH4Sco, packet); 70 } 71 }; 72 73 // An implementation of rootcanal desktop HCI server which listens on localhost:kListeningPort 74 class FakeRootcanalDesktopHciServer { 75 public: 76 FakeRootcanalDesktopHciServer() { 77 struct sockaddr_in listen_address; 78 socklen_t sockaddr_in_size = sizeof(struct sockaddr_in); 79 memset(&listen_address, 0, sockaddr_in_size); 80 81 RUN_NO_INTR(listen_fd_ = socket(AF_INET, SOCK_STREAM, 0)); 82 if (listen_fd_ < 0) { 83 LOG_WARN("Error creating socket for test channel."); 84 return; 85 } 86 87 listen_address.sin_family = AF_INET; 88 listen_address.sin_port = htons(HciHalHostRootcanalConfig::Get()->GetPort()); 89 listen_address.sin_addr.s_addr = htonl(INADDR_ANY); 90 91 if (bind(listen_fd_, reinterpret_cast<sockaddr*>(&listen_address), sockaddr_in_size) < 0) { 92 LOG_WARN("Error binding test channel listener socket to address."); 93 close(listen_fd_); 94 return; 95 } 96 97 if (listen(listen_fd_, 1) < 0) { 98 LOG_WARN("Error listening for test channel."); 99 close(listen_fd_); 100 return; 101 } 102 } 103 104 ~FakeRootcanalDesktopHciServer() { 105 close(listen_fd_); 106 } 107 108 int Accept() { 109 int accept_fd; 110 111 RUN_NO_INTR(accept_fd = accept(listen_fd_, nullptr, nullptr)); 112 113 int flags = fcntl(accept_fd, F_GETFL, NULL); 114 int ret = fcntl(accept_fd, F_SETFL, flags | O_NONBLOCK); 115 if (ret == -1) { 116 LOG_ERROR("Can't fcntl"); 117 return -1; 118 } 119 120 if (accept_fd < 0) { 121 LOG_WARN("Error accepting test channel connection errno=%d (%s).", errno, strerror(errno)); 122 123 if (errno != EAGAIN && errno != EWOULDBLOCK) { 124 LOG_ERROR("Closing listen_fd_ (won't try again)."); 125 close(listen_fd_); 126 return -1; 127 } 128 } 129 130 return accept_fd; 131 } 132 133 private: 134 int listen_fd_ = -1; 135 }; 136 137 class HciHalRootcanalTest : public ::testing::Test { 138 protected: 139 void SetUp() override { 140 thread_ = new Thread("test_thread", Thread::Priority::NORMAL); 141 142 HciHalHostRootcanalConfig::Get()->SetPort(kTestPort); 143 fake_server_ = new FakeRootcanalDesktopHciServer; 144 hal_ = fake_registry_.Start<HciHal>(thread_); 145 hal_->registerIncomingPacketCallback(&callbacks_); 146 fake_server_socket_ = fake_server_->Accept(); // accept() after client is connected to avoid blocking 147 std::queue<std::pair<uint8_t, HciPacket>> empty; 148 std::swap(incoming_packets_queue_, empty); 149 } 150 151 void TearDown() override { 152 hal_->unregisterIncomingPacketCallback(); 153 fake_registry_.StopAll(); 154 close(fake_server_socket_); 155 delete fake_server_; 156 delete thread_; 157 } 158 159 void SetFakeServerSocketToBlocking() { 160 int flags = fcntl(fake_server_socket_, F_GETFL, NULL); 161 int ret = fcntl(fake_server_socket_, F_SETFL, flags & ~O_NONBLOCK); 162 EXPECT_NE(ret, -1) << "Can't set accept fd to blocking"; 163 } 164 165 FakeRootcanalDesktopHciServer* fake_server_ = nullptr; 166 HciHal* hal_ = nullptr; 167 ModuleRegistry fake_registry_; 168 TestHciHalCallbacks callbacks_; 169 int fake_server_socket_ = -1; 170 Thread* thread_; 171 }; 172 173 void check_packet_equal(std::pair<uint8_t, HciPacket> hci_packet1_type_data_pair, H4Packet h4_packet2) { 174 auto packet1_hci_size = hci_packet1_type_data_pair.second.size(); 175 EXPECT_EQ(packet1_hci_size + 1, h4_packet2.size()); 176 EXPECT_EQ(hci_packet1_type_data_pair.first, h4_packet2[0]); 177 EXPECT_EQ(memcmp(hci_packet1_type_data_pair.second.data(), h4_packet2.data() + 1, packet1_hci_size), 0); 178 } 179 180 HciPacket make_sample_hci_cmd_pkt(uint8_t parameter_total_length) { 181 HciPacket pkt; 182 pkt.assign(2 + 1 + parameter_total_length, 0x01); 183 pkt[2] = parameter_total_length; 184 return pkt; 185 } 186 187 HciPacket make_sample_hci_acl_pkt(uint8_t payload_size) { 188 HciPacket pkt; 189 pkt.assign(2 + 2 + payload_size, 0x01); 190 pkt[2] = payload_size; 191 return pkt; 192 } 193 194 HciPacket make_sample_hci_sco_pkt(uint8_t payload_size) { 195 HciPacket pkt; 196 pkt.assign(3 + payload_size, 0x01); 197 pkt[2] = payload_size; 198 return pkt; 199 } 200 201 H4Packet make_sample_h4_evt_pkt(uint8_t parameter_total_length) { 202 H4Packet pkt; 203 pkt.assign(1 + 1 + 1 + parameter_total_length, 0x01); 204 pkt[0] = kH4Event; 205 pkt[2] = parameter_total_length; 206 return pkt; 207 } 208 209 HciPacket make_sample_h4_acl_pkt(uint8_t payload_size) { 210 HciPacket pkt; 211 pkt.assign(1 + 2 + 2 + payload_size, 0x01); 212 pkt[0] = kH4Acl; 213 pkt[3] = payload_size; 214 pkt[4] = 0; 215 return pkt; 216 } 217 218 HciPacket make_sample_h4_sco_pkt(uint8_t payload_size) { 219 HciPacket pkt; 220 pkt.assign(1 + 3 + payload_size, 0x01); 221 pkt[0] = kH4Sco; 222 pkt[3] = payload_size; 223 return pkt; 224 } 225 226 TEST_F(HciHalRootcanalTest, init_and_close) {} 227 228 TEST_F(HciHalRootcanalTest, receive_hci_evt) { 229 H4Packet incoming_packet = make_sample_h4_evt_pkt(3); 230 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size()); 231 while (incoming_packets_queue_.size() != 1) { 232 } 233 auto packet = incoming_packets_queue_.front(); 234 incoming_packets_queue_.pop(); 235 check_packet_equal(packet, incoming_packet); 236 } 237 238 TEST_F(HciHalRootcanalTest, receive_hci_acl) { 239 H4Packet incoming_packet = make_sample_h4_acl_pkt(3); 240 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size()); 241 while (incoming_packets_queue_.size() != 1) { 242 } 243 auto packet = incoming_packets_queue_.front(); 244 incoming_packets_queue_.pop(); 245 check_packet_equal(packet, incoming_packet); 246 } 247 248 TEST_F(HciHalRootcanalTest, receive_hci_sco) { 249 H4Packet incoming_packet = make_sample_h4_sco_pkt(3); 250 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size()); 251 while (incoming_packets_queue_.size() != 1) { 252 } 253 auto packet = incoming_packets_queue_.front(); 254 incoming_packets_queue_.pop(); 255 check_packet_equal(packet, incoming_packet); 256 } 257 258 TEST_F(HciHalRootcanalTest, receive_two_hci_evts) { 259 H4Packet incoming_packet = make_sample_h4_evt_pkt(3); 260 H4Packet incoming_packet2 = make_sample_h4_evt_pkt(5); 261 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size()); 262 write(fake_server_socket_, incoming_packet2.data(), incoming_packet2.size()); 263 while (incoming_packets_queue_.size() != 2) { 264 } 265 auto packet = incoming_packets_queue_.front(); 266 incoming_packets_queue_.pop(); 267 check_packet_equal(packet, incoming_packet); 268 packet = incoming_packets_queue_.front(); 269 incoming_packets_queue_.pop(); 270 check_packet_equal(packet, incoming_packet2); 271 } 272 273 TEST_F(HciHalRootcanalTest, receive_evt_and_acl) { 274 H4Packet incoming_packet = make_sample_h4_evt_pkt(3); 275 H4Packet incoming_packet2 = make_sample_h4_acl_pkt(5); 276 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size()); 277 write(fake_server_socket_, incoming_packet2.data(), incoming_packet2.size()); 278 while (incoming_packets_queue_.size() != 2) { 279 } 280 auto packet = incoming_packets_queue_.front(); 281 incoming_packets_queue_.pop(); 282 check_packet_equal(packet, incoming_packet); 283 packet = incoming_packets_queue_.front(); 284 incoming_packets_queue_.pop(); 285 check_packet_equal(packet, incoming_packet2); 286 } 287 288 TEST_F(HciHalRootcanalTest, receive_multiple_acl_batch) { 289 H4Packet incoming_packet = make_sample_h4_acl_pkt(5); 290 int num_packets = 1000; 291 for (int i = 0; i < num_packets; i++) { 292 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size()); 293 } 294 while (incoming_packets_queue_.size() != num_packets) { 295 } 296 for (int i = 0; i < num_packets; i++) { 297 auto packet = incoming_packets_queue_.front(); 298 incoming_packets_queue_.pop(); 299 check_packet_equal(packet, incoming_packet); 300 } 301 } 302 303 TEST_F(HciHalRootcanalTest, receive_multiple_acl_sequential) { 304 H4Packet incoming_packet = make_sample_h4_acl_pkt(5); 305 int num_packets = 1000; 306 for (int i = 0; i < num_packets; i++) { 307 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size()); 308 while (incoming_packets_queue_.empty()) { 309 } 310 auto packet = incoming_packets_queue_.front(); 311 incoming_packets_queue_.pop(); 312 check_packet_equal(packet, incoming_packet); 313 } 314 } 315 316 TEST_F(HciHalRootcanalTest, send_hci_cmd) { 317 uint8_t hci_cmd_param_size = 2; 318 HciPacket hci_data = make_sample_hci_cmd_pkt(hci_cmd_param_size); 319 hal_->sendHciCommand(hci_data); 320 H4Packet read_buf(1 + 2 + 1 + hci_cmd_param_size); 321 SetFakeServerSocketToBlocking(); 322 auto size_read = read(fake_server_socket_, read_buf.data(), read_buf.size()); 323 324 EXPECT_EQ(size_read, 1 + hci_data.size()); 325 check_packet_equal({kH4Command, hci_data}, read_buf); 326 } 327 328 TEST_F(HciHalRootcanalTest, send_acl) { 329 uint8_t acl_payload_size = 200; 330 HciPacket acl_packet = make_sample_hci_acl_pkt(acl_payload_size); 331 hal_->sendAclData(acl_packet); 332 H4Packet read_buf(1 + 2 + 2 + acl_payload_size); 333 SetFakeServerSocketToBlocking(); 334 auto size_read = read(fake_server_socket_, read_buf.data(), read_buf.size()); 335 336 EXPECT_EQ(size_read, 1 + acl_packet.size()); 337 check_packet_equal({kH4Acl, acl_packet}, read_buf); 338 } 339 340 TEST_F(HciHalRootcanalTest, send_sco) { 341 uint8_t sco_payload_size = 200; 342 HciPacket sco_packet = make_sample_hci_sco_pkt(sco_payload_size); 343 hal_->sendScoData(sco_packet); 344 H4Packet read_buf(1 + 3 + sco_payload_size); 345 SetFakeServerSocketToBlocking(); 346 auto size_read = read(fake_server_socket_, read_buf.data(), read_buf.size()); 347 348 EXPECT_EQ(size_read, 1 + sco_packet.size()); 349 check_packet_equal({kH4Sco, sco_packet}, read_buf); 350 } 351 352 TEST_F(HciHalRootcanalTest, send_multiple_acl_batch) { 353 uint8_t acl_payload_size = 200; 354 int num_packets = 1000; 355 HciPacket acl_packet = make_sample_hci_acl_pkt(acl_payload_size); 356 for (int i = 0; i < num_packets; i++) { 357 hal_->sendAclData(acl_packet); 358 } 359 H4Packet read_buf(1 + 2 + 2 + acl_payload_size); 360 SetFakeServerSocketToBlocking(); 361 for (int i = 0; i < num_packets; i++) { 362 auto size_read = read(fake_server_socket_, read_buf.data(), read_buf.size()); 363 EXPECT_EQ(size_read, 1 + acl_packet.size()); 364 check_packet_equal({kH4Acl, acl_packet}, read_buf); 365 } 366 } 367 368 TEST_F(HciHalRootcanalTest, send_multiple_acl_sequential) { 369 uint8_t acl_payload_size = 200; 370 int num_packets = 1000; 371 HciPacket acl_packet = make_sample_hci_acl_pkt(acl_payload_size); 372 SetFakeServerSocketToBlocking(); 373 for (int i = 0; i < num_packets; i++) { 374 hal_->sendAclData(acl_packet); 375 H4Packet read_buf(1 + 2 + 2 + acl_payload_size); 376 auto size_read = read(fake_server_socket_, read_buf.data(), read_buf.size()); 377 EXPECT_EQ(size_read, 1 + acl_packet.size()); 378 check_packet_equal({kH4Acl, acl_packet}, read_buf); 379 } 380 } 381 382 TEST(HciHalHidlTest, serialize) { 383 std::vector<uint8_t> bytes = {1, 2, 3, 4, 5, 6, 7, 8, 9}; 384 auto packet_bytes = hal::SerializePacket(std::unique_ptr<packet::BasePacketBuilder>(new packet::RawBuilder(bytes))); 385 EXPECT_EQ(bytes, packet_bytes); 386 } 387 } // namespace 388 } // namespace hal 389 } // namespace bluetooth 390