• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_bluetooth_sapphire/internal/host/gatt/server.h"
16 
17 #include <lib/fit/function.h>
18 
19 #include "pw_bluetooth_sapphire/internal/host/att/att.h"
20 #include "pw_bluetooth_sapphire/internal/host/att/database.h"
21 #include "pw_bluetooth_sapphire/internal/host/att/permissions.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
23 #include "pw_bluetooth_sapphire/internal/host/common/slab_allocator.h"
24 #include "pw_bluetooth_sapphire/internal/host/common/trace.h"
25 #include "pw_bluetooth_sapphire/internal/host/common/uuid.h"
26 #include "pw_bluetooth_sapphire/internal/host/gatt/gatt_defs.h"
27 
28 namespace bt::gatt {
29 
30 class AttBasedServer final : public Server {
31  public:
AttBasedServer(PeerId peer_id,LocalServiceManager::WeakPtr local_services,att::Bearer::WeakPtr bearer)32   AttBasedServer(PeerId peer_id,
33                  LocalServiceManager::WeakPtr local_services,
34                  att::Bearer::WeakPtr bearer)
35       : peer_id_(peer_id),
36         local_services_(std::move(local_services)),
37         att_(std::move(bearer)),
38         weak_self_(this) {
39     BT_ASSERT(local_services_.is_alive());
40     BT_DEBUG_ASSERT(att_.is_alive());
41 
42     exchange_mtu_id_ = att_->RegisterHandler(
43         att::kExchangeMTURequest,
44         fit::bind_member<&AttBasedServer::OnExchangeMTU>(this));
45     find_information_id_ = att_->RegisterHandler(
46         att::kFindInformationRequest,
47         fit::bind_member<&AttBasedServer::OnFindInformation>(this));
48     read_by_group_type_id_ = att_->RegisterHandler(
49         att::kReadByGroupTypeRequest,
50         fit::bind_member<&AttBasedServer::OnReadByGroupType>(this));
51     read_by_type_id_ = att_->RegisterHandler(
52         att::kReadByTypeRequest,
53         fit::bind_member<&AttBasedServer::OnReadByType>(this));
54     read_req_id_ = att_->RegisterHandler(
55         att::kReadRequest,
56         fit::bind_member<&AttBasedServer::OnReadRequest>(this));
57     write_req_id_ = att_->RegisterHandler(
58         att::kWriteRequest,
59         fit::bind_member<&AttBasedServer::OnWriteRequest>(this));
60     write_cmd_id_ = att_->RegisterHandler(
61         att::kWriteCommand,
62         fit::bind_member<&AttBasedServer::OnWriteCommand>(this));
63     read_blob_req_id_ = att_->RegisterHandler(
64         att::kReadBlobRequest,
65         fit::bind_member<&AttBasedServer::OnReadBlobRequest>(this));
66     find_by_type_value_id_ = att_->RegisterHandler(
67         att::kFindByTypeValueRequest,
68         fit::bind_member<&AttBasedServer::OnFindByTypeValueRequest>(this));
69     prepare_write_id_ = att_->RegisterHandler(
70         att::kPrepareWriteRequest,
71         fit::bind_member<&AttBasedServer::OnPrepareWriteRequest>(this));
72     exec_write_id_ = att_->RegisterHandler(
73         att::kExecuteWriteRequest,
74         fit::bind_member<&AttBasedServer::OnExecuteWriteRequest>(this));
75   }
76 
~AttBasedServer()77   ~AttBasedServer() override {
78     att_->UnregisterHandler(exec_write_id_);
79     att_->UnregisterHandler(prepare_write_id_);
80     att_->UnregisterHandler(find_by_type_value_id_);
81     att_->UnregisterHandler(read_blob_req_id_);
82     att_->UnregisterHandler(write_cmd_id_);
83     att_->UnregisterHandler(write_req_id_);
84     att_->UnregisterHandler(read_req_id_);
85     att_->UnregisterHandler(read_by_type_id_);
86     att_->UnregisterHandler(read_by_group_type_id_);
87     att_->UnregisterHandler(find_information_id_);
88     att_->UnregisterHandler(exchange_mtu_id_);
89   }
90 
91  private:
92   // Convenience "alias"
db()93   inline att::Database::WeakPtr db() { return local_services_->database(); }
94 
95   // Server overrides:
SendUpdate(IdType service_id,IdType chrc_id,BufferView value,IndicationCallback indicate_cb)96   void SendUpdate(IdType service_id,
97                   IdType chrc_id,
98                   BufferView value,
99                   IndicationCallback indicate_cb) override {
100     auto buffer =
101         NewBuffer(sizeof(att::Header) + sizeof(att::Handle) + value.size());
102     BT_ASSERT(buffer);
103 
104     LocalServiceManager::ClientCharacteristicConfig config;
105     if (!local_services_->GetCharacteristicConfig(
106             service_id, chrc_id, peer_id_, &config)) {
107       bt_log(TRACE,
108              "gatt",
109              "peer has not configured characteristic: %s",
110              bt_str(peer_id_));
111       if (indicate_cb) {
112         indicate_cb(ToResult(HostError::kNotSupported));
113       }
114       return;
115     }
116 
117     // Make sure that the client has subscribed to the requested protocol
118     // method.
119     if ((indicate_cb && !config.indicate) || (!indicate_cb && !config.notify)) {
120       bt_log(TRACE,
121              "gatt",
122              "peer has not enabled (%s): %s",
123              (indicate_cb ? "indications" : "notifications"),
124              bt_str(peer_id_));
125       if (indicate_cb) {
126         indicate_cb(ToResult(HostError::kNotSupported));
127       }
128       return;
129     }
130 
131     att::PacketWriter writer(
132         indicate_cb ? att::kIndication : att::kNotification, buffer.get());
133     auto rsp_params = writer.mutable_payload<att::AttributeData>();
134     rsp_params->handle = htole16(config.handle);
135     writer.mutable_payload_data().Write(value, sizeof(att::AttributeData));
136 
137     if (!indicate_cb) {
138       [[maybe_unused]] bool _ = att_->SendWithoutResponse(std::move(buffer));
139       return;
140     }
141     auto transaction_cb = [indicate_cb = std::move(indicate_cb)](
142                               att::Bearer::TransactionResult result) mutable {
143       if (result.is_ok()) {
144         bt_log(DEBUG, "gatt", "got indication ACK");
145         indicate_cb(fit::ok());
146       } else {
147         const auto& [error, handle] = result.error_value();
148         bt_log(WARN,
149                "gatt",
150                "indication failed (error %s, handle: %#.4x)",
151                bt_str(error),
152                handle);
153         indicate_cb(fit::error(error));
154       }
155     };
156     att_->StartTransaction(std::move(buffer), std::move(transaction_cb));
157   }
158 
ShutDown()159   void ShutDown() override { att_->ShutDown(); }
160 
161   // ATT protocol request handlers:
OnExchangeMTU(att::Bearer::TransactionId tid,const att::PacketReader & packet)162   void OnExchangeMTU(att::Bearer::TransactionId tid,
163                      const att::PacketReader& packet) {
164     BT_DEBUG_ASSERT(packet.opcode() == att::kExchangeMTURequest);
165 
166     if (packet.payload_size() != sizeof(att::ExchangeMTURequestParams)) {
167       att_->ReplyWithError(
168           tid, att::kInvalidHandle, att::ErrorCode::kInvalidPDU);
169       return;
170     }
171 
172     const auto& params = packet.payload<att::ExchangeMTURequestParams>();
173     uint16_t client_mtu = le16toh(params.client_rx_mtu);
174     uint16_t server_mtu = att_->preferred_mtu();
175 
176     auto buffer =
177         NewBuffer(sizeof(att::Header) + sizeof(att::ExchangeMTUResponseParams));
178     BT_ASSERT(buffer);
179 
180     att::PacketWriter writer(att::kExchangeMTUResponse, buffer.get());
181     auto rsp_params = writer.mutable_payload<att::ExchangeMTUResponseParams>();
182     rsp_params->server_rx_mtu = htole16(server_mtu);
183 
184     att_->Reply(tid, std::move(buffer));
185 
186     // If the minimum value is less than the default MTU, then go with the
187     // default MTU (Vol 3, Part F, 3.4.2.2).
188     // TODO(armansito): This needs to use on kBREDRMinATTMTU for BR/EDR. Make
189     // the default MTU configurable.
190     att_->set_mtu(std::max(att::kLEMinMTU, std::min(client_mtu, server_mtu)));
191   }
192 
OnFindInformation(att::Bearer::TransactionId tid,const att::PacketReader & packet)193   void OnFindInformation(att::Bearer::TransactionId tid,
194                          const att::PacketReader& packet) {
195     BT_DEBUG_ASSERT(packet.opcode() == att::kFindInformationRequest);
196     TRACE_DURATION("bluetooth", "gatt::Server::OnFindInformation");
197 
198     if (packet.payload_size() != sizeof(att::FindInformationRequestParams)) {
199       att_->ReplyWithError(
200           tid, att::kInvalidHandle, att::ErrorCode::kInvalidPDU);
201       return;
202     }
203 
204     const auto& params = packet.payload<att::FindInformationRequestParams>();
205     att::Handle start = le16toh(params.start_handle);
206     att::Handle end = le16toh(params.end_handle);
207 
208     constexpr size_t kRspStructSize =
209         sizeof(att::FindInformationResponseParams);
210     constexpr size_t kHeaderSize = sizeof(att::Header) + kRspStructSize;
211     BT_DEBUG_ASSERT(kHeaderSize <= att_->mtu());
212 
213     if (start == att::kInvalidHandle || start > end) {
214       att_->ReplyWithError(tid, start, att::ErrorCode::kInvalidHandle);
215       return;
216     }
217 
218     // Find all attributes within range with the same compact UUID size that can
219     // fit within the current MTU.
220     size_t max_payload_size = att_->mtu() - kHeaderSize;
221     size_t uuid_size;
222     size_t entry_size;
223     std::list<const att::Attribute*> results;
224     for (auto it = db()->GetIterator(start, end); !it.AtEnd(); it.Advance()) {
225       const auto* attr = it.get();
226       BT_DEBUG_ASSERT(attr);
227 
228       // GATT does not allow 32-bit UUIDs
229       size_t compact_size = attr->type().CompactSize(/*allow_32bit=*/false);
230       if (results.empty()) {
231         // |uuid_size| is determined by the first attribute.
232         uuid_size = compact_size;
233         entry_size =
234             std::min(uuid_size + sizeof(att::Handle), max_payload_size);
235       } else if (compact_size != uuid_size || entry_size > max_payload_size) {
236         break;
237       }
238 
239       results.push_back(attr);
240       max_payload_size -= entry_size;
241     }
242 
243     if (results.empty()) {
244       att_->ReplyWithError(tid, start, att::ErrorCode::kAttributeNotFound);
245       return;
246     }
247 
248     BT_DEBUG_ASSERT(!results.empty());
249 
250     size_t pdu_size = kHeaderSize + entry_size * results.size();
251 
252     auto buffer = NewBuffer(pdu_size);
253     BT_ASSERT(buffer);
254 
255     att::PacketWriter writer(att::kFindInformationResponse, buffer.get());
256     auto rsp_params =
257         writer.mutable_payload<att::FindInformationResponseParams>();
258     rsp_params->format =
259         (entry_size == 4) ? att::UUIDType::k16Bit : att::UUIDType::k128Bit;
260 
261     // |out_entries| initially references |params->information_data|. The loop
262     // below modifies it as entries are written into the list.
263     auto out_entries =
264         writer.mutable_payload_data().mutable_view(kRspStructSize);
265     for (const auto& attr : results) {
266       *reinterpret_cast<att::Handle*>(out_entries.mutable_data()) =
267           htole16(attr->handle());
268       auto uuid_view = out_entries.mutable_view(sizeof(att::Handle));
269       attr->type().ToBytes(&uuid_view, /*allow_32bit=*/false);
270 
271       // advance
272       out_entries = out_entries.mutable_view(entry_size);
273     }
274 
275     att_->Reply(tid, std::move(buffer));
276   }
277 
OnFindByTypeValueRequest(att::Bearer::TransactionId tid,const att::PacketReader & packet)278   void OnFindByTypeValueRequest(att::Bearer::TransactionId tid,
279                                 const att::PacketReader& packet) {
280     BT_DEBUG_ASSERT(packet.opcode() == att::kFindByTypeValueRequest);
281 
282     if (packet.payload_size() < sizeof(att::FindByTypeValueRequestParams)) {
283       att_->ReplyWithError(
284           tid, att::kInvalidHandle, att::ErrorCode::kInvalidPDU);
285       return;
286     }
287 
288     const auto& params = packet.payload<att::FindByTypeValueRequestParams>();
289     att::Handle start = le16toh(params.start_handle);
290     att::Handle end = le16toh(params.end_handle);
291     UUID type(params.type);
292     constexpr size_t kParamsSize = sizeof(att::FindByTypeValueRequestParams);
293 
294     BufferView value = packet.payload_data().view(
295         kParamsSize, packet.payload_size() - kParamsSize);
296 
297     if (start == att::kInvalidHandle || start > end) {
298       att_->ReplyWithError(
299           tid, att::kInvalidHandle, att::ErrorCode::kInvalidHandle);
300       return;
301     }
302 
303     auto iter = db()->GetIterator(start, end, &type, /*groups_only=*/false);
304     if (iter.AtEnd()) {
305       att_->ReplyWithError(
306           tid, att::kInvalidHandle, att::ErrorCode::kAttributeNotFound);
307       return;
308     }
309 
310     std::list<const att::Attribute*> results;
311 
312     // Filter for identical values
313     for (; !iter.AtEnd(); iter.Advance()) {
314       const auto* attr = iter.get();
315       BT_DEBUG_ASSERT(attr);
316 
317       // Only support static values for this Request type
318       if (attr->value()) {
319         if (*attr->value() == value) {
320           results.push_back(attr);
321         }
322       }
323     }
324 
325     // No attributes match the value
326     if (results.size() == 0) {
327       att_->ReplyWithError(
328           tid, att::kInvalidHandle, att::ErrorCode::kAttributeNotFound);
329       return;
330     }
331 
332     constexpr size_t kRspStructSize = sizeof(att::HandlesInformationList);
333     size_t pdu_size = sizeof(att::Header) + kRspStructSize * results.size();
334     auto buffer = NewBuffer(pdu_size);
335     BT_ASSERT(buffer);
336 
337     att::PacketWriter writer(att::kFindByTypeValueResponse, buffer.get());
338 
339     // Points to the next entry in the target PDU.
340     auto next_entry = writer.mutable_payload_data();
341     for (const auto& attr : results) {
342       auto* entry = reinterpret_cast<att::HandlesInformationList*>(
343           next_entry.mutable_data());
344       entry->handle = htole16(attr->handle());
345       if (attr->group().active()) {
346         entry->group_end_handle = htole16(attr->group().end_handle());
347       } else {
348         entry->group_end_handle = htole16(attr->handle());
349       }
350       next_entry = next_entry.mutable_view(kRspStructSize);
351     }
352 
353     att_->Reply(tid, std::move(buffer));
354   }
355 
OnReadByGroupType(att::Bearer::TransactionId tid,const att::PacketReader & packet)356   void OnReadByGroupType(att::Bearer::TransactionId tid,
357                          const att::PacketReader& packet) {
358     BT_DEBUG_ASSERT(packet.opcode() == att::kReadByGroupTypeRequest);
359     TRACE_DURATION("bluetooth", "gatt::Server::OnReadByGroupType");
360 
361     att::Handle start, end;
362     UUID group_type;
363 
364     // The group type is represented as either a 16-bit or 128-bit UUID.
365     if (packet.payload_size() == sizeof(att::ReadByTypeRequestParams16)) {
366       const auto& params = packet.payload<att::ReadByTypeRequestParams16>();
367       start = le16toh(params.start_handle);
368       end = le16toh(params.end_handle);
369       group_type = UUID(le16toh(params.type));
370     } else if (packet.payload_size() ==
371                sizeof(att::ReadByTypeRequestParams128)) {
372       const auto& params = packet.payload<att::ReadByTypeRequestParams128>();
373       start = le16toh(params.start_handle);
374       end = le16toh(params.end_handle);
375       group_type = UUID(params.type);
376     } else {
377       att_->ReplyWithError(
378           tid, att::kInvalidHandle, att::ErrorCode::kInvalidPDU);
379       return;
380     }
381 
382     if (group_type != types::kPrimaryService &&
383         group_type != types::kSecondaryService) {
384       att_->ReplyWithError(tid, start, att::ErrorCode::kUnsupportedGroupType);
385       return;
386     }
387 
388     constexpr size_t kRspStructSize =
389         sizeof(att::ReadByGroupTypeResponseParams);
390     constexpr size_t kHeaderSize = sizeof(att::Header) + kRspStructSize;
391     BT_DEBUG_ASSERT(kHeaderSize <= att_->mtu());
392 
393     size_t value_size;
394     std::list<const att::Attribute*> results;
395     fit::result<att::ErrorCode> status =
396         ReadByTypeHelper(start,
397                          end,
398                          group_type,
399                          /*group_type=*/true,
400                          att_->mtu() - kHeaderSize,
401                          att::kMaxReadByGroupTypeValueLength,
402                          sizeof(att::AttributeGroupDataEntry),
403                          &value_size,
404                          &results);
405     if (status.is_error()) {
406       att_->ReplyWithError(tid, start, status.error_value());
407       return;
408     }
409 
410     BT_DEBUG_ASSERT(!results.empty());
411 
412     size_t entry_size = value_size + sizeof(att::AttributeGroupDataEntry);
413     size_t pdu_size = kHeaderSize + entry_size * results.size();
414     BT_DEBUG_ASSERT(pdu_size <= att_->mtu());
415 
416     auto buffer = NewBuffer(pdu_size);
417     BT_ASSERT(buffer);
418 
419     att::PacketWriter writer(att::kReadByGroupTypeResponse, buffer.get());
420     auto params = writer.mutable_payload<att::ReadByGroupTypeResponseParams>();
421 
422     BT_DEBUG_ASSERT(entry_size <= std::numeric_limits<uint8_t>::max());
423     params->length = static_cast<uint8_t>(entry_size);
424 
425     // Points to the next entry in the target PDU.
426     auto next_entry =
427         writer.mutable_payload_data().mutable_view(kRspStructSize);
428     for (const auto& attr : results) {
429       auto* entry = reinterpret_cast<att::AttributeGroupDataEntry*>(
430           next_entry.mutable_data());
431       entry->start_handle = htole16(attr->group().start_handle());
432       entry->group_end_handle = htole16(attr->group().end_handle());
433       next_entry.Write(attr->group().decl_value().view(0, value_size),
434                        sizeof(att::AttributeGroupDataEntry));
435 
436       next_entry = next_entry.mutable_view(entry_size);
437     }
438 
439     att_->Reply(tid, std::move(buffer));
440   }
441 
OnReadByType(att::Bearer::TransactionId tid,const att::PacketReader & packet)442   void OnReadByType(att::Bearer::TransactionId tid,
443                     const att::PacketReader& packet) {
444     BT_DEBUG_ASSERT(packet.opcode() == att::kReadByTypeRequest);
445     TRACE_DURATION("bluetooth", "gatt::Server::OnReadByType");
446 
447     att::Handle start, end;
448     UUID type;
449 
450     // The attribute type is represented as either a 16-bit or 128-bit UUID.
451     if (packet.payload_size() == sizeof(att::ReadByTypeRequestParams16)) {
452       const auto& params = packet.payload<att::ReadByTypeRequestParams16>();
453       start = le16toh(params.start_handle);
454       end = le16toh(params.end_handle);
455       type = UUID(le16toh(params.type));
456     } else if (packet.payload_size() ==
457                sizeof(att::ReadByTypeRequestParams128)) {
458       const auto& params = packet.payload<att::ReadByTypeRequestParams128>();
459       start = le16toh(params.start_handle);
460       end = le16toh(params.end_handle);
461       type = UUID(params.type);
462     } else {
463       att_->ReplyWithError(
464           tid, att::kInvalidHandle, att::ErrorCode::kInvalidPDU);
465       return;
466     }
467 
468     constexpr size_t kRspStructSize = sizeof(att::ReadByTypeResponseParams);
469     constexpr size_t kHeaderSize = sizeof(att::Header) + kRspStructSize;
470     BT_DEBUG_ASSERT(kHeaderSize <= att_->mtu());
471 
472     size_t value_size;
473     std::list<const att::Attribute*> results;
474     fit::result<att::ErrorCode> status =
475         ReadByTypeHelper(start,
476                          end,
477                          type,
478                          /*group_type=*/false,
479                          att_->mtu() - kHeaderSize,
480                          att::kMaxReadByTypeValueLength,
481                          sizeof(att::AttributeData),
482                          &value_size,
483                          &results);
484     if (status.is_error()) {
485       att_->ReplyWithError(tid, start, status.error_value());
486       return;
487     }
488 
489     BT_DEBUG_ASSERT(!results.empty());
490 
491     // If the value is dynamic, then delegate the read to any registered
492     // handler.
493     if (!results.front()->value()) {
494       BT_DEBUG_ASSERT(results.size() == 1u);
495 
496       const size_t kMaxValueSize =
497           std::min(att_->mtu() - kHeaderSize - sizeof(att::AttributeData),
498                    static_cast<size_t>(att::kMaxReadByTypeValueLength));
499 
500       att::Handle handle = results.front()->handle();
501       auto self = weak_self_.GetWeakPtr();
502       auto result_cb = [self, tid, handle, kMaxValueSize](
503                            fit::result<att::ErrorCode> status,
504                            const auto& value) {
505         if (!self.is_alive())
506           return;
507 
508         if (status.is_error()) {
509           self->att_->ReplyWithError(tid, handle, status.error_value());
510           return;
511         }
512 
513         // Respond with just a single entry.
514         size_t value_size = std::min(value.size(), kMaxValueSize);
515         size_t entry_size = value_size + sizeof(att::AttributeData);
516         auto buffer = NewBuffer(entry_size + kHeaderSize);
517         att::PacketWriter writer(att::kReadByTypeResponse, buffer.get());
518 
519         auto params = writer.mutable_payload<att::ReadByTypeResponseParams>();
520         params->length = static_cast<uint8_t>(entry_size);
521         params->attribute_data_list->handle = htole16(handle);
522         writer.mutable_payload_data().Write(
523             value.data(), value_size, sizeof(params->length) + sizeof(handle));
524 
525         self->att_->Reply(tid, std::move(buffer));
526       };
527 
528       // Respond with an error if no read handler was registered.
529       if (!results.front()->ReadAsync(peer_id_, 0, result_cb)) {
530         att_->ReplyWithError(tid, handle, att::ErrorCode::kReadNotPermitted);
531       }
532       return;
533     }
534 
535     size_t entry_size = sizeof(att::AttributeData) + value_size;
536     BT_DEBUG_ASSERT(entry_size <= std::numeric_limits<uint8_t>::max());
537 
538     size_t pdu_size = kHeaderSize + entry_size * results.size();
539     BT_DEBUG_ASSERT(pdu_size <= att_->mtu());
540 
541     auto buffer = NewBuffer(pdu_size);
542     BT_ASSERT(buffer);
543 
544     att::PacketWriter writer(att::kReadByTypeResponse, buffer.get());
545     auto params = writer.mutable_payload<att::ReadByTypeResponseParams>();
546     params->length = static_cast<uint8_t>(entry_size);
547 
548     // Points to the next entry in the target PDU.
549     auto next_entry =
550         writer.mutable_payload_data().mutable_view(kRspStructSize);
551     for (const auto& attr : results) {
552       auto* entry =
553           reinterpret_cast<att::AttributeData*>(next_entry.mutable_data());
554       entry->handle = htole16(attr->handle());
555       next_entry.Write(attr->value()->view(0, value_size),
556                        sizeof(entry->handle));
557 
558       next_entry = next_entry.mutable_view(entry_size);
559     }
560 
561     att_->Reply(tid, std::move(buffer));
562   }
563 
OnReadBlobRequest(att::Bearer::TransactionId tid,const att::PacketReader & packet)564   void OnReadBlobRequest(att::Bearer::TransactionId tid,
565                          const att::PacketReader& packet) {
566     BT_DEBUG_ASSERT(packet.opcode() == att::kReadBlobRequest);
567 
568     if (packet.payload_size() != sizeof(att::ReadBlobRequestParams)) {
569       att_->ReplyWithError(
570           tid, att::kInvalidHandle, att::ErrorCode::kInvalidPDU);
571       return;
572     }
573 
574     const auto& params = packet.payload<att::ReadBlobRequestParams>();
575     att::Handle handle = le16toh(params.handle);
576     uint16_t offset = le16toh(params.offset);
577 
578     const auto* attr = db()->FindAttribute(handle);
579     if (!attr) {
580       att_->ReplyWithError(tid, handle, att::ErrorCode::kInvalidHandle);
581       return;
582     }
583 
584     fit::result<att::ErrorCode> status =
585         att::CheckReadPermissions(attr->read_reqs(), att_->security());
586     if (status.is_error()) {
587       att_->ReplyWithError(tid, handle, status.error_value());
588       return;
589     }
590 
591     constexpr size_t kHeaderSize = sizeof(att::Header);
592 
593     auto self = weak_self_.GetWeakPtr();
594     auto callback = [self, tid, handle](fit::result<att::ErrorCode> status,
595                                         const auto& value) {
596       if (!self.is_alive())
597         return;
598 
599       if (status.is_error()) {
600         self->att_->ReplyWithError(tid, handle, status.error_value());
601         return;
602       }
603 
604       size_t value_size =
605           std::min(value.size(), self->att_->mtu() - kHeaderSize);
606       auto buffer = NewBuffer(value_size + kHeaderSize);
607       BT_ASSERT(buffer);
608 
609       att::PacketWriter writer(att::kReadBlobResponse, buffer.get());
610       writer.mutable_payload_data().Write(value.view(0, value_size));
611 
612       self->att_->Reply(tid, std::move(buffer));
613     };
614 
615     // Use the cached value if there is one.
616     if (attr->value()) {
617       if (offset >= attr->value()->size()) {
618         att_->ReplyWithError(tid, handle, att::ErrorCode::kInvalidOffset);
619         return;
620       }
621       size_t value_size =
622           std::min(attr->value()->size(), self->att_->mtu() - kHeaderSize);
623       callback(fit::ok(), attr->value()->view(offset, value_size));
624       return;
625     }
626 
627     // TODO(fxbug.dev/42142121): Add a timeout to this
628     if (!attr->ReadAsync(peer_id_, offset, callback)) {
629       att_->ReplyWithError(tid, handle, att::ErrorCode::kReadNotPermitted);
630     }
631   }
632 
OnReadRequest(att::Bearer::TransactionId tid,const att::PacketReader & packet)633   void OnReadRequest(att::Bearer::TransactionId tid,
634                      const att::PacketReader& packet) {
635     BT_DEBUG_ASSERT(packet.opcode() == att::kReadRequest);
636 
637     if (packet.payload_size() != sizeof(att::ReadRequestParams)) {
638       att_->ReplyWithError(
639           tid, att::kInvalidHandle, att::ErrorCode::kInvalidPDU);
640       return;
641     }
642 
643     const auto& params = packet.payload<att::WriteRequestParams>();
644     att::Handle handle = le16toh(params.handle);
645 
646     const auto* attr = db()->FindAttribute(handle);
647     if (!attr) {
648       att_->ReplyWithError(tid, handle, att::ErrorCode::kInvalidHandle);
649       return;
650     }
651 
652     fit::result<att::ErrorCode> status =
653         att::CheckReadPermissions(attr->read_reqs(), att_->security());
654     if (status.is_error()) {
655       att_->ReplyWithError(tid, handle, status.error_value());
656       return;
657     }
658 
659     constexpr size_t kHeaderSize = sizeof(att::Header);
660 
661     auto self = weak_self_.GetWeakPtr();
662     auto callback = [self, tid, handle](fit::result<att::ErrorCode> status,
663                                         const auto& value) {
664       if (!self.is_alive())
665         return;
666 
667       if (status.is_error()) {
668         self->att_->ReplyWithError(tid, handle, status.error_value());
669         return;
670       }
671 
672       size_t value_size =
673           std::min(value.size(), self->att_->mtu() - kHeaderSize);
674       auto buffer = NewBuffer(value_size + kHeaderSize);
675       BT_ASSERT(buffer);
676 
677       att::PacketWriter writer(att::kReadResponse, buffer.get());
678       writer.mutable_payload_data().Write(value.view(0, value_size));
679 
680       self->att_->Reply(tid, std::move(buffer));
681     };
682 
683     // Use the cached value if there is one.
684     if (attr->value()) {
685       callback(fit::ok(), *attr->value());
686       return;
687     }
688 
689     if (!attr->ReadAsync(peer_id_, 0, callback)) {
690       att_->ReplyWithError(tid, handle, att::ErrorCode::kReadNotPermitted);
691     }
692   }
693 
OnWriteCommand(att::Bearer::TransactionId tid,const att::PacketReader & packet)694   void OnWriteCommand(att::Bearer::TransactionId tid,
695                       const att::PacketReader& packet) {
696     BT_DEBUG_ASSERT(packet.opcode() == att::kWriteCommand);
697 
698     if (packet.payload_size() < sizeof(att::WriteRequestParams)) {
699       // Ignore if wrong size, no response allowed
700       return;
701     }
702 
703     const auto& params = packet.payload<att::WriteRequestParams>();
704     att::Handle handle = le16toh(params.handle);
705     const auto* attr = db()->FindAttribute(handle);
706 
707     // Attributes can be invalid if the handle is invalid
708     if (!attr) {
709       return;
710     }
711 
712     fit::result<att::ErrorCode> status =
713         att::CheckWritePermissions(attr->write_reqs(), att_->security());
714     if (status.is_error()) {
715       return;
716     }
717 
718     // Attributes with a static value cannot be written.
719     if (attr->value()) {
720       return;
721     }
722 
723     auto value_view = packet.payload_data().view(sizeof(params.handle));
724     if (value_view.size() > att::kMaxAttributeValueLength) {
725       return;
726     }
727 
728     // No response allowed for commands, ignore the cb
729     attr->WriteAsync(peer_id_, 0, value_view, nullptr);
730   }
731 
OnWriteRequest(att::Bearer::TransactionId tid,const att::PacketReader & packet)732   void OnWriteRequest(att::Bearer::TransactionId tid,
733                       const att::PacketReader& packet) {
734     BT_DEBUG_ASSERT(packet.opcode() == att::kWriteRequest);
735 
736     if (packet.payload_size() < sizeof(att::WriteRequestParams)) {
737       att_->ReplyWithError(
738           tid, att::kInvalidHandle, att::ErrorCode::kInvalidPDU);
739       return;
740     }
741 
742     const auto& params = packet.payload<att::WriteRequestParams>();
743     att::Handle handle = le16toh(params.handle);
744 
745     const auto* attr = db()->FindAttribute(handle);
746     if (!attr) {
747       att_->ReplyWithError(tid, handle, att::ErrorCode::kInvalidHandle);
748       return;
749     }
750 
751     fit::result<att::ErrorCode> status =
752         att::CheckWritePermissions(attr->write_reqs(), att_->security());
753     if (status.is_error()) {
754       att_->ReplyWithError(tid, handle, status.error_value());
755       return;
756     }
757 
758     // Attributes with a static value cannot be written.
759     if (attr->value()) {
760       att_->ReplyWithError(tid, handle, att::ErrorCode::kWriteNotPermitted);
761       return;
762     }
763 
764     auto value_view = packet.payload_data().view(sizeof(params.handle));
765     if (value_view.size() > att::kMaxAttributeValueLength) {
766       att_->ReplyWithError(
767           tid, handle, att::ErrorCode::kInvalidAttributeValueLength);
768       return;
769     }
770 
771     auto self = weak_self_.GetWeakPtr();
772     auto result_cb = [self, tid, handle](fit::result<att::ErrorCode> status) {
773       if (!self.is_alive())
774         return;
775 
776       if (status.is_error()) {
777         self->att_->ReplyWithError(tid, handle, status.error_value());
778         return;
779       }
780 
781       auto buffer = NewBuffer(1);
782       (*buffer)[0] = att::kWriteResponse;
783       self->att_->Reply(tid, std::move(buffer));
784     };
785 
786     if (!attr->WriteAsync(peer_id_, 0, value_view, result_cb)) {
787       att_->ReplyWithError(tid, handle, att::ErrorCode::kWriteNotPermitted);
788     }
789   }
790 
OnPrepareWriteRequest(att::Bearer::TransactionId tid,const att::PacketReader & packet)791   void OnPrepareWriteRequest(att::Bearer::TransactionId tid,
792                              const att::PacketReader& packet) {
793     BT_DEBUG_ASSERT(packet.opcode() == att::kPrepareWriteRequest);
794 
795     if (packet.payload_size() < sizeof(att::PrepareWriteRequestParams)) {
796       att_->ReplyWithError(
797           tid, att::kInvalidHandle, att::ErrorCode::kInvalidPDU);
798       return;
799     }
800 
801     const auto& params = packet.payload<att::PrepareWriteRequestParams>();
802     att::Handle handle = le16toh(params.handle);
803     uint16_t offset = le16toh(params.offset);
804     auto value_view = packet.payload_data().view(sizeof(params.handle) +
805                                                  sizeof(params.offset));
806 
807     if (prepare_queue_.size() >= att::kPrepareQueueMaxCapacity) {
808       att_->ReplyWithError(tid, handle, att::ErrorCode::kPrepareQueueFull);
809       return;
810     }
811 
812     // Validate attribute handle and perform security checks (see Vol 3, Part F,
813     // 3.4.6.1 for required checks)
814     const auto* attr = db()->FindAttribute(handle);
815     if (!attr) {
816       att_->ReplyWithError(tid, handle, att::ErrorCode::kInvalidHandle);
817       return;
818     }
819 
820     fit::result<att::ErrorCode> status =
821         att::CheckWritePermissions(attr->write_reqs(), att_->security());
822     if (status.is_error()) {
823       att_->ReplyWithError(tid, handle, status.error_value());
824       return;
825     }
826 
827     prepare_queue_.push(att::QueuedWrite(handle, offset, value_view));
828 
829     // Reply back with the request payload.
830     auto buffer = std::make_unique<DynamicByteBuffer>(packet.size());
831     att::PacketWriter writer(att::kPrepareWriteResponse, buffer.get());
832     writer.mutable_payload_data().Write(packet.payload_data());
833 
834     att_->Reply(tid, std::move(buffer));
835   }
836 
OnExecuteWriteRequest(att::Bearer::TransactionId tid,const att::PacketReader & packet)837   void OnExecuteWriteRequest(att::Bearer::TransactionId tid,
838                              const att::PacketReader& packet) {
839     BT_DEBUG_ASSERT(packet.opcode() == att::kExecuteWriteRequest);
840 
841     if (packet.payload_size() != sizeof(att::ExecuteWriteRequestParams)) {
842       att_->ReplyWithError(
843           tid, att::kInvalidHandle, att::ErrorCode::kInvalidPDU);
844       return;
845     }
846 
847     const auto& params = packet.payload<att::ExecuteWriteRequestParams>();
848     if (params.flags == att::ExecuteWriteFlag::kCancelAll) {
849       prepare_queue_ = {};
850 
851       auto buffer = std::make_unique<DynamicByteBuffer>(1);
852       att::PacketWriter writer(att::kExecuteWriteResponse, buffer.get());
853       att_->Reply(tid, std::move(buffer));
854       return;
855     }
856 
857     if (params.flags != att::ExecuteWriteFlag::kWritePending) {
858       att_->ReplyWithError(
859           tid, att::kInvalidHandle, att::ErrorCode::kInvalidPDU);
860       return;
861     }
862 
863     auto self = weak_self_.GetWeakPtr();
864     auto result_cb = [self,
865                       tid](fit::result<std::tuple<att::Handle, att::ErrorCode>>
866                                result) mutable {
867       if (!self.is_alive())
868         return;
869 
870       if (result.is_error()) {
871         auto [handle, ecode] = result.error_value();
872         self->att_->ReplyWithError(tid, handle, ecode);
873         return;
874       }
875 
876       auto rsp = std::make_unique<DynamicByteBuffer>(1);
877       att::PacketWriter writer(att::kExecuteWriteResponse, rsp.get());
878       self->att_->Reply(tid, std::move(rsp));
879     };
880     db()->ExecuteWriteQueue(peer_id_,
881                             std::move(prepare_queue_),
882                             att_->security(),
883                             std::move(result_cb));
884   }
885 
886   // Helper function to serve the Read By Type and Read By Group Type requests.
887   // This searches |db| for attributes with the given |type| and adds as many
888   // attributes as it can fit within the given |max_data_list_size|. The
889   // attribute value that should be included within each attribute data list
890   // entry is returned in |out_value_size|.
891   //
892   // If the result is a dynamic attribute, |out_results| will contain at most
893   // one entry. |out_value_size| will point to an undefined value in that case.
894   //
895   // On error, returns an error code that can be used in a ATT Error Response.
ReadByTypeHelper(att::Handle start,att::Handle end,const UUID & type,bool group_type,size_t max_data_list_size,size_t max_value_size,size_t entry_prefix_size,size_t * out_value_size,std::list<const att::Attribute * > * out_results)896   fit::result<att::ErrorCode> ReadByTypeHelper(
897       att::Handle start,
898       att::Handle end,
899       const UUID& type,
900       bool group_type,
901       size_t max_data_list_size,
902       size_t max_value_size,
903       size_t entry_prefix_size,
904       size_t* out_value_size,
905       std::list<const att::Attribute*>* out_results) {
906     BT_DEBUG_ASSERT(out_results);
907     BT_DEBUG_ASSERT(out_value_size);
908 
909     if (start == att::kInvalidHandle || start > end)
910       return fit::error(att::ErrorCode::kInvalidHandle);
911 
912     auto iter = db()->GetIterator(start, end, &type, group_type);
913     if (iter.AtEnd())
914       return fit::error(att::ErrorCode::kAttributeNotFound);
915 
916     // |value_size| is the size of the complete attribute value for each result
917     // entry. |entry_size| = |value_size| + |entry_prefix_size|. We store these
918     // separately to avoid recalculating one every it gets checked.
919     size_t value_size;
920     size_t entry_size;
921     std::list<const att::Attribute*> results;
922 
923     for (; !iter.AtEnd(); iter.Advance()) {
924       const auto* attr = iter.get();
925       BT_DEBUG_ASSERT(attr);
926 
927       fit::result<att::ErrorCode> security_result =
928           att::CheckReadPermissions(attr->read_reqs(), att_->security());
929       if (security_result.is_error()) {
930         // Return error only if this is the first result that matched. We simply
931         // stop the search otherwise.
932         if (results.empty()) {
933           return security_result;
934         }
935         break;
936       }
937 
938       // The first result determines |value_size| and |entry_size|.
939       if (results.empty()) {
940         if (!attr->value()) {
941           // If the first value is dynamic then this is the only attribute that
942           // this call will return. No need to calculate the value size.
943           results.push_back(attr);
944           break;
945         }
946 
947         value_size = attr->value()->size();  // untruncated value size
948         entry_size =
949             std::min(std::min(value_size, max_value_size) + entry_prefix_size,
950                      max_data_list_size);
951 
952         // Actual value size to include in a PDU.
953         *out_value_size = entry_size - entry_prefix_size;
954 
955       } else if (!attr->value() || attr->value()->size() != value_size ||
956                  entry_size > max_data_list_size) {
957         // Stop the search and exclude this attribute because either:
958         // a. we ran into a dynamic value in a result that contains static
959         // values, b. the matching attribute has a different value size than the
960         // first
961         //    attribute,
962         // c. there is no remaining space in the response PDU.
963         break;
964       }
965 
966       results.push_back(attr);
967       max_data_list_size -= entry_size;
968     }
969 
970     if (results.empty())
971       return fit::error(att::ErrorCode::kAttributeNotFound);
972 
973     *out_results = std::move(results);
974     return fit::ok();
975   }
976 
977   PeerId peer_id_;
978   LocalServiceManager::WeakPtr local_services_;
979   att::Bearer::WeakPtr att_;
980 
981   // The queue data structure used for queued writes (see Vol 3, Part F, 3.4.6).
982   att::PrepareWriteQueue prepare_queue_;
983 
984   // ATT protocol request handler IDs
985   // TODO(armansito): Storing all these IDs here feels wasteful. Provide a way
986   // to unregister GATT server callbacks collectively from an att::Bearer, given
987   // that it's server-role functionalities are uniquely handled by this class.
988   att::Bearer::HandlerId exchange_mtu_id_;
989   att::Bearer::HandlerId find_information_id_;
990   att::Bearer::HandlerId read_by_group_type_id_;
991   att::Bearer::HandlerId read_by_type_id_;
992   att::Bearer::HandlerId read_req_id_;
993   att::Bearer::HandlerId write_req_id_;
994   att::Bearer::HandlerId write_cmd_id_;
995   att::Bearer::HandlerId read_blob_req_id_;
996   att::Bearer::HandlerId find_by_type_value_id_;
997   att::Bearer::HandlerId prepare_write_id_;
998   att::Bearer::HandlerId exec_write_id_;
999 
1000   WeakSelf<AttBasedServer> weak_self_;
1001 
1002   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(AttBasedServer);
1003 };
1004 
1005 // static
Create(PeerId peer_id,LocalServiceManager::WeakPtr local_services,att::Bearer::WeakPtr bearer)1006 std::unique_ptr<Server> Server::Create(
1007     PeerId peer_id,
1008     LocalServiceManager::WeakPtr local_services,
1009     att::Bearer::WeakPtr bearer) {
1010   return std::make_unique<AttBasedServer>(
1011       peer_id, std::move(local_services), std::move(bearer));
1012 }
1013 }  // namespace bt::gatt
1014