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() override {
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);
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 = ConnectionManagementCommandView::Create(CommandPacketView::Create(PacketView<kLittleEndian>(
124 std::make_shared<std::vector<uint8_t>>(request->packet().begin(), request->packet().end()))));
125 if (!command_view.IsValid()) {
126 return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid command packet");
127 }
128 switch (command_view.GetOpCode()) {
129 case OpCode::DISCONNECT: {
130 auto view = DisconnectView::Create(command_view);
131 GET_CONNECTION(view);
132 connection->second.connection_->Disconnect(view.GetReason());
133 return ::grpc::Status::OK;
134 }
135 default:
136 return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid command packet");
137 }
138 }
139 #undef GET_CONNECTION
140
FetchIncomingConnection(::grpc::ServerContext * context,const google::protobuf::Empty * request,::grpc::ServerWriter<LeConnectionEvent> * writer)141 ::grpc::Status FetchIncomingConnection(
142 ::grpc::ServerContext* context,
143 const google::protobuf::Empty* request,
144 ::grpc::ServerWriter<LeConnectionEvent>* writer) override {
145 if (per_connection_events_.size() > current_connection_request_) {
146 return ::grpc::Status(::grpc::StatusCode::RESOURCE_EXHAUSTED, "Only one outstanding connection is supported");
147 }
148 per_connection_events_.emplace_back(std::make_unique<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>>(
149 std::string("incoming connection ") + std::to_string(current_connection_request_)));
150 return per_connection_events_[current_connection_request_]->RunLoop(context, writer);
151 }
152
SendAclData(::grpc::ServerContext * context,const LeAclData * request,::google::protobuf::Empty * response)153 ::grpc::Status SendAclData(
154 ::grpc::ServerContext* context, const LeAclData* request, ::google::protobuf::Empty* response) override {
155 std::promise<void> promise;
156 auto future = promise.get_future();
157 {
158 std::unique_lock<std::mutex> lock(acl_connections_mutex_);
159 auto connection = acl_connections_.find(request->handle());
160 if (connection == acl_connections_.end()) {
161 return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle");
162 }
163 connection->second.connection_->GetAclQueueEnd()->RegisterEnqueue(
164 facade_handler_,
165 common::Bind(
166 &LeAclManagerFacadeService::enqueue_packet,
167 common::Unretained(this),
168 common::Unretained(request),
169 common::Passed(std::move(promise))));
170 auto status = future.wait_for(std::chrono::milliseconds(1000));
171 if (status != std::future_status::ready) {
172 return ::grpc::Status(::grpc::StatusCode::RESOURCE_EXHAUSTED, "Can't send packet");
173 }
174 }
175 return ::grpc::Status::OK;
176 }
177
enqueue_packet(const LeAclData * request,std::promise<void> promise)178 std::unique_ptr<BasePacketBuilder> enqueue_packet(const LeAclData* request, std::promise<void> promise) {
179 auto connection = acl_connections_.find(request->handle());
180 ASSERT_LOG(connection != acl_connections_.end(), "handle %d", request->handle());
181 connection->second.connection_->GetAclQueueEnd()->UnregisterEnqueue();
182 std::unique_ptr<RawBuilder> packet =
183 std::make_unique<RawBuilder>(std::vector<uint8_t>(request->payload().begin(), request->payload().end()));
184 promise.set_value();
185 return packet;
186 }
187
FetchAclData(::grpc::ServerContext * context,const LeHandleMsg * request,::grpc::ServerWriter<LeAclData> * writer)188 ::grpc::Status FetchAclData(
189 ::grpc::ServerContext* context, const LeHandleMsg* request, ::grpc::ServerWriter<LeAclData>* writer) override {
190 auto connection = acl_connections_.find(request->handle());
191 if (connection == acl_connections_.end()) {
192 return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle");
193 }
194 return connection->second.pending_acl_data_.RunLoop(context, writer);
195 }
196
to_handle(uint32_t current_request)197 static inline uint16_t to_handle(uint32_t current_request) {
198 return (current_request + 0x10) % 0xe00;
199 }
200
builder_to_string(std::unique_ptr<BasePacketBuilder> builder)201 static inline std::string builder_to_string(std::unique_ptr<BasePacketBuilder> builder) {
202 std::vector<uint8_t> bytes;
203 BitInserter bit_inserter(bytes);
204 builder->Serialize(bit_inserter);
205 return std::string(bytes.begin(), bytes.end());
206 }
207
on_incoming_acl(std::shared_ptr<LeAclConnection> connection,uint16_t handle)208 void on_incoming_acl(std::shared_ptr<LeAclConnection> connection, uint16_t handle) {
209 auto packet = connection->GetAclQueueEnd()->TryDequeue();
210 auto connection_tracker = acl_connections_.find(handle);
211 ASSERT_LOG(connection_tracker != acl_connections_.end(), "handle %d", handle);
212 LeAclData acl_data;
213 acl_data.set_handle(handle);
214 acl_data.set_payload(std::string(packet->begin(), packet->end()));
215 connection_tracker->second.pending_acl_data_.OnIncomingEvent(acl_data);
216 }
217
OnLeConnectSuccess(AddressWithType address_with_type,std::unique_ptr<LeAclConnection> connection)218 void OnLeConnectSuccess(AddressWithType address_with_type, std::unique_ptr<LeAclConnection> connection) override {
219 LOG_DEBUG("%s", address_with_type.ToString().c_str());
220
221 std::unique_lock<std::mutex> lock(acl_connections_mutex_);
222 auto addr = address_with_type.GetAddress();
223 std::shared_ptr<LeAclConnection> shared_connection = std::move(connection);
224 uint16_t handle = to_handle(current_connection_request_);
225 acl_connections_.emplace(
226 std::piecewise_construct,
227 std::forward_as_tuple(handle),
228 std::forward_as_tuple(handle, shared_connection, per_connection_events_[current_connection_request_]));
229 shared_connection->GetAclQueueEnd()->RegisterDequeue(
230 facade_handler_,
231 common::Bind(&LeAclManagerFacadeService::on_incoming_acl, common::Unretained(this), shared_connection, handle));
232 auto callbacks = acl_connections_.find(handle)->second.GetCallbacks();
233 shared_connection->RegisterCallbacks(callbacks, facade_handler_);
234 {
235 std::unique_ptr<BasePacketBuilder> builder = LeConnectionCompleteBuilder::Create(
236 ErrorCode::SUCCESS,
237 handle,
238 Role::MASTER,
239 address_with_type.GetAddressType(),
240 addr,
241 1,
242 2,
243 3,
244 ClockAccuracy::PPM_20);
245 LeConnectionEvent success;
246 success.set_event(builder_to_string(std::move(builder)));
247 per_connection_events_[current_connection_request_]->OnIncomingEvent(success);
248 }
249 current_connection_request_++;
250 }
251
OnLeConnectFail(AddressWithType address,ErrorCode reason)252 void OnLeConnectFail(AddressWithType address, ErrorCode reason) override {
253 std::unique_ptr<BasePacketBuilder> builder = LeConnectionCompleteBuilder::Create(
254 reason, 0, Role::MASTER, address.GetAddressType(), address.GetAddress(), 0, 0, 0, ClockAccuracy::PPM_20);
255 LeConnectionEvent fail;
256 fail.set_event(builder_to_string(std::move(builder)));
257 per_connection_events_[current_connection_request_]->OnIncomingEvent(fail);
258 current_connection_request_++;
259 }
260
261 class Connection : public LeConnectionManagementCallbacks {
262 public:
Connection(uint16_t handle,std::shared_ptr<LeAclConnection> connection,std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>> event_stream)263 Connection(
264 uint16_t handle,
265 std::shared_ptr<LeAclConnection> connection,
266 std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>> event_stream)
267 : handle_(handle), connection_(std::move(connection)), event_stream_(std::move(event_stream)) {}
OnConnectionUpdate(uint16_t connection_interval,uint16_t connection_latency,uint16_t supervision_timeout)268 void OnConnectionUpdate(
269 uint16_t connection_interval, uint16_t connection_latency, uint16_t supervision_timeout) override {
270 LOG_DEBUG(
271 "interval: 0x%hx, latency: 0x%hx, timeout 0x%hx",
272 connection_interval,
273 connection_latency,
274 supervision_timeout);
275 }
276
OnDisconnection(ErrorCode reason)277 void OnDisconnection(ErrorCode reason) override {
278 std::unique_ptr<BasePacketBuilder> builder =
279 DisconnectionCompleteBuilder::Create(ErrorCode::SUCCESS, handle_, reason);
280 LeConnectionEvent disconnection;
281 disconnection.set_event(builder_to_string(std::move(builder)));
282 event_stream_->OnIncomingEvent(disconnection);
283 }
284
GetCallbacks()285 LeConnectionManagementCallbacks* GetCallbacks() {
286 return this;
287 }
288
289 uint16_t handle_;
290 std::shared_ptr<LeAclConnection> connection_;
291 std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>> event_stream_;
292 ::bluetooth::grpc::GrpcEventQueue<LeAclData> pending_acl_data_{std::string("PendingAclData") +
293 std::to_string(handle_)};
294 };
295
296 private:
297 AclManager* acl_manager_;
298 ::bluetooth::os::Handler* facade_handler_;
299 mutable std::mutex acl_connections_mutex_;
300 std::vector<std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>>> per_connection_events_;
301 std::map<uint16_t, Connection> acl_connections_;
302 uint32_t current_connection_request_{0};
303 };
304
ListDependencies(ModuleList * list)305 void LeAclManagerFacadeModule::ListDependencies(ModuleList* list) {
306 ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
307 list->add<AclManager>();
308 }
309
Start()310 void LeAclManagerFacadeModule::Start() {
311 ::bluetooth::grpc::GrpcFacadeModule::Start();
312 service_ = new LeAclManagerFacadeService(GetDependency<AclManager>(), GetHandler());
313 }
314
Stop()315 void LeAclManagerFacadeModule::Stop() {
316 delete service_;
317 ::bluetooth::grpc::GrpcFacadeModule::Stop();
318 }
319
GetService() const320 ::grpc::Service* LeAclManagerFacadeModule::GetService() const {
321 return service_;
322 }
323
324 const ModuleFactory LeAclManagerFacadeModule::Factory =
__anonf2789db90102() 325 ::bluetooth::ModuleFactory([]() { return new LeAclManagerFacadeModule(); });
326
327 } // namespace facade
328 } // namespace hci
329 } // namespace bluetooth
330