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 "hci/facade/le_acl_manager_facade.h"
18 
19 #include <condition_variable>
20 #include <memory>
21 #include <mutex>
22 
23 #include "common/bind.h"
24 #include "grpc/grpc_event_queue.h"
25 #include "hci/acl_manager.h"
26 #include "hci/facade/le_acl_manager_facade.grpc.pb.h"
27 #include "hci/facade/le_acl_manager_facade.pb.h"
28 #include "hci/hci_packets.h"
29 #include "packet/raw_builder.h"
30 
31 using ::grpc::ServerAsyncResponseWriter;
32 using ::grpc::ServerAsyncWriter;
33 using ::grpc::ServerContext;
34 
35 using ::bluetooth::packet::RawBuilder;
36 
37 namespace bluetooth {
38 namespace hci {
39 namespace facade {
40 
41 using acl_manager::LeAclConnection;
42 using acl_manager::LeConnectionCallbacks;
43 using acl_manager::LeConnectionManagementCallbacks;
44 
45 class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeConnectionCallbacks {
46  public:
LeAclManagerFacadeService(AclManager * acl_manager,::bluetooth::os::Handler * facade_handler)47   LeAclManagerFacadeService(AclManager* acl_manager, ::bluetooth::os::Handler* facade_handler)
48       : acl_manager_(acl_manager), facade_handler_(facade_handler) {
49     acl_manager_->RegisterLeCallbacks(this, facade_handler_);
50   }
51 
~LeAclManagerFacadeService()52   ~LeAclManagerFacadeService() {
53     std::unique_lock<std::mutex> lock(acl_connections_mutex_);
54     for (auto& conn : acl_connections_) {
55       if (conn.second.connection_ != nullptr) {
56         conn.second.connection_->GetAclQueueEnd()->UnregisterDequeue();
57         conn.second.connection_.reset();
58       }
59     }
60   }
61 
CreateConnection(::grpc::ServerContext * context,const::bluetooth::facade::BluetoothAddressWithType * request,::grpc::ServerWriter<LeConnectionEvent> * writer)62   ::grpc::Status CreateConnection(
63       ::grpc::ServerContext* context,
64       const ::bluetooth::facade::BluetoothAddressWithType* request,
65       ::grpc::ServerWriter<LeConnectionEvent>* writer) override {
66     Address peer_address;
67     ASSERT(Address::FromString(request->address().address(), peer_address));
68     AddressWithType peer(peer_address, static_cast<AddressType>(request->type()));
69     acl_manager_->CreateLeConnection(peer, /* is_direct */ true);
70     if (per_connection_events_.size() > current_connection_request_) {
71       return ::grpc::Status(::grpc::StatusCode::RESOURCE_EXHAUSTED, "Only one outstanding request is supported");
72     }
73     per_connection_events_.emplace_back(std::make_unique<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>>(
74         std::string("connection attempt ") + std::to_string(current_connection_request_)));
75     return per_connection_events_[current_connection_request_]->RunLoop(context, writer);
76   }
77 
CancelConnection(::grpc::ServerContext * context,const::bluetooth::facade::BluetoothAddressWithType * request,google::protobuf::Empty * response)78   ::grpc::Status CancelConnection(
79       ::grpc::ServerContext* context,
80       const ::bluetooth::facade::BluetoothAddressWithType* request,
81       google::protobuf::Empty* response) override {
82     Address peer_address;
83     ASSERT(Address::FromString(request->address().address(), peer_address));
84     AddressWithType peer(peer_address, static_cast<AddressType>(request->type()));
85     if (per_connection_events_.size() == current_connection_request_) {
86       // Todo: Check that the address matches an outstanding connection request
87       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "No matching outstanding connection");
88     }
89     acl_manager_->CancelLeConnect(peer);
90     return ::grpc::Status::OK;
91   }
92 
Disconnect(::grpc::ServerContext * context,const LeHandleMsg * request,::google::protobuf::Empty * response)93   ::grpc::Status Disconnect(::grpc::ServerContext* context, const LeHandleMsg* request,
94                             ::google::protobuf::Empty* response) override {
95     std::unique_lock<std::mutex> lock(acl_connections_mutex_);
96     auto connection = acl_connections_.find(request->handle());
97     if (connection == acl_connections_.end()) {
98       LOG_ERROR("Invalid handle");
99       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle");
100     } else {
101       connection->second.connection_->Disconnect(DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION);
102       return ::grpc::Status::OK;
103     }
104   }
105 
106 #define GET_CONNECTION(view)                                                         \
107   std::map<uint16_t, Connection>::iterator connection;                               \
108   do {                                                                               \
109     if (!view.IsValid()) {                                                           \
110       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle"); \
111     }                                                                                \
112     std::unique_lock<std::mutex> lock(acl_connections_mutex_);                       \
113     connection = acl_connections_.find(view.GetConnectionHandle());                  \
114     if (connection == acl_connections_.end()) {                                      \
115       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle"); \
116     }                                                                                \
117   } while (0)
118 
ConnectionCommand(::grpc::ServerContext * context,const LeConnectionCommandMsg * request,::google::protobuf::Empty * response)119   ::grpc::Status ConnectionCommand(
120       ::grpc::ServerContext* context,
121       const LeConnectionCommandMsg* request,
122       ::google::protobuf::Empty* response) override {
123     auto command_view =
124         ConnectionManagementCommandView::Create(AclCommandView::Create(CommandView::Create(PacketView<kLittleEndian>(
125             std::make_shared<std::vector<uint8_t>>(request->packet().begin(), request->packet().end())))));
126     if (!command_view.IsValid()) {
127       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid command packet");
128     }
129     switch (command_view.GetOpCode()) {
130       case OpCode::DISCONNECT: {
131         auto view = DisconnectView::Create(command_view);
132         GET_CONNECTION(view);
133         connection->second.connection_->Disconnect(view.GetReason());
134         return ::grpc::Status::OK;
135       }
136       default:
137         return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid command packet");
138     }
139   }
140 #undef GET_CONNECTION
141 
FetchIncomingConnection(::grpc::ServerContext * context,const google::protobuf::Empty * request,::grpc::ServerWriter<LeConnectionEvent> * writer)142   ::grpc::Status FetchIncomingConnection(
143       ::grpc::ServerContext* context,
144       const google::protobuf::Empty* request,
145       ::grpc::ServerWriter<LeConnectionEvent>* writer) override {
146     if (per_connection_events_.size() > current_connection_request_) {
147       return ::grpc::Status(::grpc::StatusCode::RESOURCE_EXHAUSTED, "Only one outstanding connection is supported");
148     }
149     per_connection_events_.emplace_back(std::make_unique<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>>(
150         std::string("incoming connection ") + std::to_string(current_connection_request_)));
151     return per_connection_events_[current_connection_request_]->RunLoop(context, writer);
152   }
153 
SendAclData(::grpc::ServerContext * context,const LeAclData * request,::google::protobuf::Empty * response)154   ::grpc::Status SendAclData(
155       ::grpc::ServerContext* context, const LeAclData* request, ::google::protobuf::Empty* response) override {
156     std::promise<void> promise;
157     auto future = promise.get_future();
158     {
159       std::unique_lock<std::mutex> lock(acl_connections_mutex_);
160       auto connection = acl_connections_.find(request->handle());
161       if (connection == acl_connections_.end()) {
162         return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle");
163       }
164       connection->second.connection_->GetAclQueueEnd()->RegisterEnqueue(
165           facade_handler_,
166           common::Bind(
167               &LeAclManagerFacadeService::enqueue_packet,
168               common::Unretained(this),
169               common::Unretained(request),
170               common::Passed(std::move(promise))));
171       auto status = future.wait_for(std::chrono::milliseconds(1000));
172       if (status != std::future_status::ready) {
173         return ::grpc::Status(::grpc::StatusCode::RESOURCE_EXHAUSTED, "Can't send packet");
174       }
175     }
176     return ::grpc::Status::OK;
177   }
178 
enqueue_packet(const LeAclData * request,std::promise<void> promise)179   std::unique_ptr<BasePacketBuilder> enqueue_packet(const LeAclData* request, std::promise<void> promise) {
180     auto connection = acl_connections_.find(request->handle());
181     ASSERT_LOG(connection != acl_connections_.end(), "handle %d", request->handle());
182     connection->second.connection_->GetAclQueueEnd()->UnregisterEnqueue();
183     std::unique_ptr<RawBuilder> packet =
184         std::make_unique<RawBuilder>(std::vector<uint8_t>(request->payload().begin(), request->payload().end()));
185     promise.set_value();
186     return packet;
187   }
188 
FetchAclData(::grpc::ServerContext * context,const LeHandleMsg * request,::grpc::ServerWriter<LeAclData> * writer)189   ::grpc::Status FetchAclData(
190       ::grpc::ServerContext* context, const LeHandleMsg* request, ::grpc::ServerWriter<LeAclData>* writer) override {
191     auto connection = acl_connections_.find(request->handle());
192     if (connection == acl_connections_.end()) {
193       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle");
194     }
195     return connection->second.pending_acl_data_.RunLoop(context, writer);
196   }
197 
builder_to_string(std::unique_ptr<BasePacketBuilder> builder)198   static inline std::string builder_to_string(std::unique_ptr<BasePacketBuilder> builder) {
199     std::vector<uint8_t> bytes;
200     BitInserter bit_inserter(bytes);
201     builder->Serialize(bit_inserter);
202     return std::string(bytes.begin(), bytes.end());
203   }
204 
on_incoming_acl(std::shared_ptr<LeAclConnection> connection,uint16_t handle)205   void on_incoming_acl(std::shared_ptr<LeAclConnection> connection, uint16_t handle) {
206     auto packet = connection->GetAclQueueEnd()->TryDequeue();
207     auto connection_tracker = acl_connections_.find(handle);
208     ASSERT_LOG(connection_tracker != acl_connections_.end(), "handle %d", handle);
209     LeAclData acl_data;
210     acl_data.set_handle(handle);
211     acl_data.set_payload(std::string(packet->begin(), packet->end()));
212     connection_tracker->second.pending_acl_data_.OnIncomingEvent(acl_data);
213   }
214 
OnLeConnectSuccess(AddressWithType address_with_type,std::unique_ptr<LeAclConnection> connection)215   void OnLeConnectSuccess(AddressWithType address_with_type, std::unique_ptr<LeAclConnection> connection) override {
216     LOG_INFO("%s", address_with_type.ToString().c_str());
217 
218     std::unique_lock<std::mutex> lock(acl_connections_mutex_);
219     auto addr = address_with_type.GetAddress();
220     std::shared_ptr<LeAclConnection> shared_connection = std::move(connection);
221     uint16_t handle = shared_connection->GetHandle();
222     acl_connections_.emplace(
223         std::piecewise_construct,
224         std::forward_as_tuple(handle),
225         std::forward_as_tuple(handle, shared_connection, per_connection_events_[current_connection_request_]));
226     shared_connection->GetAclQueueEnd()->RegisterDequeue(
227         facade_handler_,
228         common::Bind(&LeAclManagerFacadeService::on_incoming_acl, common::Unretained(this), shared_connection, handle));
229     auto callbacks = acl_connections_.find(handle)->second.GetCallbacks();
230     shared_connection->RegisterCallbacks(callbacks, facade_handler_);
231     {
232       std::unique_ptr<BasePacketBuilder> builder = LeConnectionCompleteBuilder::Create(
233           ErrorCode::SUCCESS,
234           handle,
235           Role::CENTRAL,
236           address_with_type.GetAddressType(),
237           addr,
238           1,
239           2,
240           3,
241           ClockAccuracy::PPM_20);
242       LeConnectionEvent success;
243       success.set_payload(builder_to_string(std::move(builder)));
244       per_connection_events_[current_connection_request_]->OnIncomingEvent(success);
245     }
246     current_connection_request_++;
247   }
248 
OnLeConnectFail(AddressWithType address,ErrorCode reason)249   void OnLeConnectFail(AddressWithType address, ErrorCode reason) override {
250     std::unique_ptr<BasePacketBuilder> builder = LeConnectionCompleteBuilder::Create(
251         reason, 0, Role::CENTRAL, address.GetAddressType(), address.GetAddress(), 0, 0, 0, ClockAccuracy::PPM_20);
252     LeConnectionEvent fail;
253     fail.set_payload(builder_to_string(std::move(builder)));
254     per_connection_events_[current_connection_request_]->OnIncomingEvent(fail);
255     current_connection_request_++;
256   }
257 
258   class Connection : public LeConnectionManagementCallbacks {
259    public:
Connection(uint16_t handle,std::shared_ptr<LeAclConnection> connection,std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>> event_stream)260     Connection(
261         uint16_t handle,
262         std::shared_ptr<LeAclConnection> connection,
263         std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>> event_stream)
264         : handle_(handle), connection_(std::move(connection)), event_stream_(std::move(event_stream)) {}
OnConnectionUpdate(hci::ErrorCode hci_status,uint16_t connection_interval,uint16_t connection_latency,uint16_t supervision_timeout)265     void OnConnectionUpdate(
266         hci::ErrorCode hci_status,
267         uint16_t connection_interval,
268         uint16_t connection_latency,
269         uint16_t supervision_timeout) override {
270       LOG_INFO(
271           "interval: 0x%hx, latency: 0x%hx, timeout 0x%hx",
272           connection_interval,
273           connection_latency,
274           supervision_timeout);
275     }
276 
OnDataLengthChange(uint16_t tx_octets,uint16_t tx_time,uint16_t rx_octets,uint16_t rx_time)277     void OnDataLengthChange(uint16_t tx_octets, uint16_t tx_time, uint16_t rx_octets, uint16_t rx_time) override {
278       LOG_INFO(
279           "tx_octets: 0x%hx, tx_time: 0x%hx, rx_octets 0x%hx, rx_time 0x%hx", tx_octets, tx_time, rx_octets, rx_time);
280     }
281 
OnPhyUpdate(hci::ErrorCode hci_status,uint8_t tx_phy,uint8_t rx_phy)282     void OnPhyUpdate(hci::ErrorCode hci_status, uint8_t tx_phy, uint8_t rx_phy) override {}
OnLocalAddressUpdate(AddressWithType address_with_type)283     void OnLocalAddressUpdate(AddressWithType address_with_type) override {}
OnDisconnection(ErrorCode reason)284     void OnDisconnection(ErrorCode reason) override {
285       std::unique_ptr<BasePacketBuilder> builder =
286           DisconnectionCompleteBuilder::Create(ErrorCode::SUCCESS, handle_, reason);
287       LeConnectionEvent disconnection;
288       disconnection.set_payload(builder_to_string(std::move(builder)));
289       event_stream_->OnIncomingEvent(disconnection);
290     }
291 
OnReadRemoteVersionInformationComplete(hci::ErrorCode hci_status,uint8_t lmp_version,uint16_t manufacturer_name,uint16_t sub_version)292     void OnReadRemoteVersionInformationComplete(
293         hci::ErrorCode hci_status, uint8_t lmp_version, uint16_t manufacturer_name, uint16_t sub_version) override {}
294 
GetCallbacks()295     LeConnectionManagementCallbacks* GetCallbacks() {
296       return this;
297     }
298 
299     uint16_t handle_;
300     std::shared_ptr<LeAclConnection> connection_;
301     std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>> event_stream_;
302     ::bluetooth::grpc::GrpcEventQueue<LeAclData> pending_acl_data_{std::string("PendingAclData") +
303                                                                    std::to_string(handle_)};
304   };
305 
306  private:
307   AclManager* acl_manager_;
308   ::bluetooth::os::Handler* facade_handler_;
309   mutable std::mutex acl_connections_mutex_;
310   std::vector<std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>>> per_connection_events_;
311   std::map<uint16_t, Connection> acl_connections_;
312   uint32_t current_connection_request_{0};
313 };
314 
ListDependencies(ModuleList * list)315 void LeAclManagerFacadeModule::ListDependencies(ModuleList* list) {
316   ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
317   list->add<AclManager>();
318 }
319 
Start()320 void LeAclManagerFacadeModule::Start() {
321   ::bluetooth::grpc::GrpcFacadeModule::Start();
322   service_ = new LeAclManagerFacadeService(GetDependency<AclManager>(), GetHandler());
323 }
324 
Stop()325 void LeAclManagerFacadeModule::Stop() {
326   delete service_;
327   ::bluetooth::grpc::GrpcFacadeModule::Stop();
328 }
329 
GetService() const330 ::grpc::Service* LeAclManagerFacadeModule::GetService() const {
331   return service_;
332 }
333 
334 const ModuleFactory LeAclManagerFacadeModule::Factory =
__anon04b747a50102() 335     ::bluetooth::ModuleFactory([]() { return new LeAclManagerFacadeModule(); });
336 
337 }  // namespace facade
338 }  // namespace hci
339 }  // namespace bluetooth
340