• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 #include <netdb.h>
21 #include <sys/socket.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include <chrono>
25 #include <csignal>
26 #include <mutex>
27 #include <queue>
28 
29 #include "hal/snoop_logger.h"
30 #include "os/log.h"
31 #include "os/reactor.h"
32 #include "os/thread.h"
33 
34 namespace {
35 constexpr int INVALID_FD = -1;
36 
37 constexpr uint8_t kH4Command = 0x01;
38 constexpr uint8_t kH4Acl = 0x02;
39 constexpr uint8_t kH4Sco = 0x03;
40 constexpr uint8_t kH4Event = 0x04;
41 
42 constexpr uint8_t kH4HeaderSize = 1;
43 constexpr uint8_t kHciAclHeaderSize = 4;
44 constexpr uint8_t kHciScoHeaderSize = 3;
45 constexpr uint8_t kHciEvtHeaderSize = 2;
46 constexpr int kBufSize = 1024 + 4 + 1;  // DeviceProperties::acl_data_packet_size_ + ACL header + H4 header
47 
ConnectToRootCanal(const std::string & server,int port)48 int ConnectToRootCanal(const std::string& server, int port) {
49   int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
50   if (socket_fd < 1) {
51     LOG_ERROR("can't create socket: %s", strerror(errno));
52     return INVALID_FD;
53   }
54 
55   struct hostent* host;
56   host = gethostbyname(server.c_str());
57   if (host == nullptr) {
58     LOG_ERROR("can't get server name");
59     return INVALID_FD;
60   }
61 
62   struct sockaddr_in serv_addr;
63   memset((void*)&serv_addr, 0, sizeof(serv_addr));
64   serv_addr.sin_family = AF_INET;
65   serv_addr.sin_addr.s_addr = INADDR_ANY;
66   serv_addr.sin_port = htons(port);
67 
68   int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
69   if (result < 0) {
70     LOG_ERROR("can't connect: %s", strerror(errno));
71     return INVALID_FD;
72   }
73 
74   timeval socket_timeout{
75       .tv_sec = 3,
76       .tv_usec = 0,
77   };
78   int ret = setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &socket_timeout, sizeof(socket_timeout));
79   if (ret == -1) {
80     LOG_ERROR("can't control socket fd: %s", strerror(errno));
81     return INVALID_FD;
82   }
83   return socket_fd;
84 }
85 }  // namespace
86 
87 namespace bluetooth {
88 namespace hal {
89 
90 const std::string SnoopLogger::DefaultFilePath = "/tmp/btsnoop_hci.log";
91 const bool SnoopLogger::AlwaysFlush = true;
92 
93 class HciHalHostRootcanal : public HciHal {
94  public:
registerIncomingPacketCallback(HciHalCallbacks * callback)95   void registerIncomingPacketCallback(HciHalCallbacks* callback) override {
96     std::lock_guard<std::mutex> lock(api_mutex_);
97     LOG_INFO("%s before", __func__);
98     {
99       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
100       ASSERT(incoming_packet_callback_ == nullptr && callback != nullptr);
101       incoming_packet_callback_ = callback;
102     }
103     LOG_INFO("%s after", __func__);
104   }
105 
unregisterIncomingPacketCallback()106   void unregisterIncomingPacketCallback() override {
107     std::lock_guard<std::mutex> lock(api_mutex_);
108     LOG_INFO("%s before", __func__);
109     {
110       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
111       incoming_packet_callback_ = nullptr;
112     }
113     LOG_INFO("%s after", __func__);
114   }
115 
sendHciCommand(HciPacket command)116   void sendHciCommand(HciPacket command) override {
117     std::lock_guard<std::mutex> lock(api_mutex_);
118     ASSERT(sock_fd_ != INVALID_FD);
119     std::vector<uint8_t> packet = std::move(command);
120     btsnoop_logger_->capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::CMD);
121     packet.insert(packet.cbegin(), kH4Command);
122     write_to_rootcanal_fd(packet);
123   }
124 
sendAclData(HciPacket data)125   void sendAclData(HciPacket data) override {
126     std::lock_guard<std::mutex> lock(api_mutex_);
127     ASSERT(sock_fd_ != INVALID_FD);
128     std::vector<uint8_t> packet = std::move(data);
129     btsnoop_logger_->capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::ACL);
130     packet.insert(packet.cbegin(), kH4Acl);
131     write_to_rootcanal_fd(packet);
132   }
133 
sendScoData(HciPacket data)134   void sendScoData(HciPacket data) override {
135     std::lock_guard<std::mutex> lock(api_mutex_);
136     ASSERT(sock_fd_ != INVALID_FD);
137     std::vector<uint8_t> packet = std::move(data);
138     btsnoop_logger_->capture(packet, SnoopLogger::Direction::OUTGOING, SnoopLogger::PacketType::SCO);
139     packet.insert(packet.cbegin(), kH4Sco);
140     write_to_rootcanal_fd(packet);
141   }
142 
143  protected:
ListDependencies(ModuleList * list)144   void ListDependencies(ModuleList* list) override {
145     list->add<SnoopLogger>();
146   }
147 
Start()148   void Start() override {
149     std::lock_guard<std::mutex> lock(api_mutex_);
150     ASSERT(sock_fd_ == INVALID_FD);
151     sock_fd_ = ConnectToRootCanal(config_->GetServerAddress(), config_->GetPort());
152     ASSERT(sock_fd_ != INVALID_FD);
153     reactable_ = hci_incoming_thread_.GetReactor()->Register(
154         sock_fd_, common::Bind(&HciHalHostRootcanal::incoming_packet_received, common::Unretained(this)),
155         common::Closure());
156     btsnoop_logger_ = GetDependency<SnoopLogger>();
157     LOG_INFO("Rootcanal HAL opened successfully");
158   }
159 
Stop()160   void Stop() override {
161     std::lock_guard<std::mutex> lock(api_mutex_);
162     LOG_INFO("Rootcanal HAL is closing");
163     if (reactable_ != nullptr) {
164       hci_incoming_thread_.GetReactor()->Unregister(reactable_);
165       LOG_INFO("Rootcanal HAL is stopping, start waiting for last callback");
166       // Wait up to 1 second for the last incoming packet callback to finish
167       hci_incoming_thread_.GetReactor()->WaitForUnregisteredReactable(std::chrono::milliseconds(1000));
168       LOG_INFO("Rootcanal HAL is stopping, finished waiting for last callback");
169       ASSERT(sock_fd_ != INVALID_FD);
170     }
171     reactable_ = nullptr;
172     {
173       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
174       incoming_packet_callback_ = nullptr;
175     }
176     ::close(sock_fd_);
177     sock_fd_ = INVALID_FD;
178     LOG_INFO("Rootcanal HAL is closed");
179   }
180 
181  private:
182   // Held when APIs are called, NOT to be held during callbacks
183   std::mutex api_mutex_;
184   HciHalHostRootcanalConfig* config_ = HciHalHostRootcanalConfig::Get();
185   HciHalCallbacks* incoming_packet_callback_ = nullptr;
186   std::mutex incoming_packet_callback_mutex_;
187   int sock_fd_ = INVALID_FD;
188   bluetooth::os::Thread hci_incoming_thread_ =
189       bluetooth::os::Thread("hci_incoming_thread", bluetooth::os::Thread::Priority::NORMAL);
190   bluetooth::os::Reactor::Reactable* reactable_ = nullptr;
191   std::queue<std::vector<uint8_t>> hci_outgoing_queue_;
192   SnoopLogger* btsnoop_logger_ = nullptr;
193 
write_to_rootcanal_fd(HciPacket packet)194   void write_to_rootcanal_fd(HciPacket packet) {
195     // TODO: replace this with new queue when it's ready
196     hci_outgoing_queue_.emplace(packet);
197     if (hci_outgoing_queue_.size() == 1) {
198       hci_incoming_thread_.GetReactor()->ModifyRegistration(
199           reactable_, common::Bind(&HciHalHostRootcanal::incoming_packet_received, common::Unretained(this)),
200           common::Bind(&HciHalHostRootcanal::send_packet_ready, common::Unretained(this)));
201     }
202   }
203 
send_packet_ready()204   void send_packet_ready() {
205     std::lock_guard<std::mutex> lock(this->api_mutex_);
206     auto packet_to_send = this->hci_outgoing_queue_.front();
207     auto bytes_written = write(this->sock_fd_, (void*)packet_to_send.data(), packet_to_send.size());
208     this->hci_outgoing_queue_.pop();
209     if (bytes_written == -1) {
210       abort();
211     }
212     if (hci_outgoing_queue_.empty()) {
213       this->hci_incoming_thread_.GetReactor()->ModifyRegistration(
214           this->reactable_, common::Bind(&HciHalHostRootcanal::incoming_packet_received, common::Unretained(this)),
215           common::Closure());
216     }
217   }
218 
incoming_packet_received()219   void incoming_packet_received() {
220     {
221       std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
222       if (incoming_packet_callback_ == nullptr) {
223         LOG_INFO("Dropping a packet");
224         return;
225       }
226     }
227     uint8_t buf[kBufSize] = {};
228 
229     ssize_t received_size;
230     RUN_NO_INTR(received_size = recv(sock_fd_, buf, kH4HeaderSize, 0));
231     ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno));
232     if (received_size == 0) {
233       LOG_WARN("Can't read H4 header. EOF received");
234       raise(SIGINT);
235       return;
236     }
237 
238     if (buf[0] == kH4Event) {
239       RUN_NO_INTR(received_size = recv(sock_fd_, buf + kH4HeaderSize, kHciEvtHeaderSize, 0));
240       ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno));
241       ASSERT_LOG(received_size == kHciEvtHeaderSize, "malformed HCI event header received");
242 
243       uint8_t hci_evt_parameter_total_length = buf[2];
244       ssize_t payload_size;
245       RUN_NO_INTR(payload_size =
246                       recv(sock_fd_, buf + kH4HeaderSize + kHciEvtHeaderSize, hci_evt_parameter_total_length, 0));
247       ASSERT_LOG(payload_size != -1, "Can't receive from socket: %s", strerror(errno));
248       ASSERT_LOG(payload_size == hci_evt_parameter_total_length,
249                  "malformed HCI event total parameter size received: %zu != %d", payload_size,
250                  hci_evt_parameter_total_length);
251 
252       HciPacket receivedHciPacket;
253       receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciEvtHeaderSize + payload_size);
254       btsnoop_logger_->capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::EVT);
255       {
256         std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
257         if (incoming_packet_callback_ == nullptr) {
258           LOG_INFO("Dropping an event after processing");
259           return;
260         }
261         incoming_packet_callback_->hciEventReceived(receivedHciPacket);
262       }
263     }
264 
265     if (buf[0] == kH4Acl) {
266       RUN_NO_INTR(received_size = recv(sock_fd_, buf + kH4HeaderSize, kHciAclHeaderSize, 0));
267       ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno));
268       ASSERT_LOG(received_size == kHciAclHeaderSize, "malformed ACL header received");
269 
270       uint16_t hci_acl_data_total_length = (buf[4] << 8) + buf[3];
271       int payload_size;
272       RUN_NO_INTR(payload_size = recv(sock_fd_, buf + kH4HeaderSize + kHciAclHeaderSize, hci_acl_data_total_length, 0));
273       ASSERT_LOG(payload_size != -1, "Can't receive from socket: %s", strerror(errno));
274       ASSERT_LOG(payload_size == hci_acl_data_total_length, "malformed ACL length received: %d != %d", payload_size,
275                  hci_acl_data_total_length);
276       ASSERT_LOG(hci_acl_data_total_length <= kBufSize - kH4HeaderSize - kHciAclHeaderSize, "packet too long");
277 
278       HciPacket receivedHciPacket;
279       receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciAclHeaderSize + payload_size);
280       btsnoop_logger_->capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::ACL);
281       {
282         std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
283         if (incoming_packet_callback_ == nullptr) {
284           LOG_INFO("Dropping an ACL packet after processing");
285           return;
286         }
287         incoming_packet_callback_->aclDataReceived(receivedHciPacket);
288       }
289     }
290 
291     if (buf[0] == kH4Sco) {
292       RUN_NO_INTR(received_size = recv(sock_fd_, buf + kH4HeaderSize, kHciScoHeaderSize, 0));
293       ASSERT_LOG(received_size != -1, "Can't receive from socket: %s", strerror(errno));
294       ASSERT_LOG(received_size == kHciScoHeaderSize, "malformed SCO header received");
295 
296       uint8_t hci_sco_data_total_length = buf[3];
297       int payload_size;
298       RUN_NO_INTR(payload_size = recv(sock_fd_, buf + kH4HeaderSize + kHciScoHeaderSize, hci_sco_data_total_length, 0));
299       ASSERT_LOG(payload_size != -1, "Can't receive from socket: %s", strerror(errno));
300       ASSERT_LOG(payload_size == hci_sco_data_total_length, "malformed SCO packet received: size mismatch");
301 
302       HciPacket receivedHciPacket;
303       receivedHciPacket.assign(buf + kH4HeaderSize, buf + kH4HeaderSize + kHciScoHeaderSize + payload_size);
304       btsnoop_logger_->capture(receivedHciPacket, SnoopLogger::Direction::INCOMING, SnoopLogger::PacketType::SCO);
305       {
306         std::lock_guard<std::mutex> incoming_packet_callback_lock(incoming_packet_callback_mutex_);
307         if (incoming_packet_callback_ == nullptr) {
308           LOG_INFO("Dropping a SCO packet after processing");
309           return;
310         }
311         incoming_packet_callback_->scoDataReceived(receivedHciPacket);
312       }
313     }
314     memset(buf, 0, kBufSize);
315   }
316 };
317 
__anond926f13c0202() 318 const ModuleFactory HciHal::Factory = ModuleFactory([]() { return new HciHalHostRootcanal(); });
319 
320 }  // namespace hal
321 }  // namespace bluetooth
322