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