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