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 #pragma once 16 #include <set> 17 #include <unordered_map> 18 #include <unordered_set> 19 #include <vector> 20 21 #include "pw_bluetooth_sapphire/internal/host/sdp/sdp.h" 22 23 namespace bt::sdp { 24 25 // A ServiceRecord represents a service record in a SDP database. 26 // The service has a number of attributes identified by defined IDs and each 27 // attribute has a value. 28 class ServiceRecord { 29 public: 30 // Create a new service record. 31 // Generates a UUID and sets the Service ID attribute. 32 ServiceRecord(); 33 34 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ServiceRecord); 35 // Allow move. 36 ServiceRecord(ServiceRecord&&) = default; 37 38 // Directly sets an attribute to a specific DataElement 39 void SetAttribute(AttributeId id, DataElement value); 40 41 // Get the value of an attribute. The attribute must be set. 42 // Use HasAttribute() to detect if an attribute is set. 43 const DataElement& GetAttribute(AttributeId id) const; 44 45 // Returns true if there is an attribute with |id| in this record. 46 bool HasAttribute(AttributeId id) const; 47 48 // Removes the attribute identified by |id|. Idempotent. 49 void RemoveAttribute(AttributeId id); 50 51 // Protocol-only services only reserve a protocol endpoint, and don't 52 // advertise a service in the SDP database. 53 bool IsProtocolOnly() const; 54 55 // Returns true if the ServiceRecord contains the required fields 56 // needed for SDP registration. 57 bool IsRegisterable() const; 58 59 // Returns the handle of this service. handle()60 ServiceHandle handle() const { return handle_; } 61 62 void SetHandle(ServiceHandle handle); 63 64 // Returns the set of attributes in this record that are in 65 // the range |start| - |end| inclusive. 66 // If |start| > |end| or no attributes are present, returns a 67 // an empty set. 68 std::set<AttributeId> GetAttributesInRange(AttributeId start, 69 AttributeId end) const; 70 71 // Returns true if any value of the attributes in this service contain all 72 // of the |uuids| given. The uuids need not be in any specific attribute 73 // value. 74 bool FindUUID(const std::unordered_set<UUID>& uuids) const; 75 76 // Convenience function to set the service class id list attribute. 77 void SetServiceClassUUIDs(const std::vector<UUID>& classes); 78 79 using ProtocolListId = uint8_t; 80 81 constexpr static ProtocolListId kPrimaryProtocolList = 0x00; 82 83 // Adds a protocol to a protocol descriptor list. 84 // Convenience function for adding protocol descriptor list attributes. 85 // |id| identifies the list to be added to. 86 // |uuid| must be a protocol UUID. 87 // |params| is either: 88 // - a DataElement sequence of parameters 89 // - a null DataElement, for which nothing will be appended 90 // - a single DataElement parameter 91 // kPrimaryProtocolList is presented as the primary protocol. 92 // Other protocol will be added to the additional protocol lists, 93 void AddProtocolDescriptor(const ProtocolListId id, 94 const UUID& uuid, 95 DataElement params); 96 97 // Adds a profile to the bluetooth profile descriptor list attribute. 98 // |uuid| is the UUID of the profile. |major| and |minor| are the major and 99 // minor versions of the profile supported. 100 void AddProfile(const UUID& uuid, uint8_t major, uint8_t minor); 101 102 // Adds a set of language attributes. 103 // |language| is required (and must be two characters long) 104 // At least one other attribute must be non-empty. 105 // Empty attributes will be omitted. 106 // All strings are UTF-8 encoded. 107 // Returns true if attributes were added, false otherwise. 108 bool AddInfo(const std::string& language_code, 109 const std::string& name, 110 const std::string& description, 111 const std::string& provider); 112 113 // Set the security level required to connect to this service. 114 // See v5.0, Vol 3, Part C, Section 5.2.2.8 set_security_level(SecurityLevel security_level)115 void set_security_level(SecurityLevel security_level) { 116 security_level_ = security_level; 117 } security_level()118 SecurityLevel security_level() const { return security_level_; } 119 120 // Debug representation of a service record used for Inspect. 121 // Only includes kBluetoothProfileDescriptorList and kServiceClassIdList to 122 // minimize log spam. 123 std::string ToString() const; 124 125 private: 126 ServiceHandle handle_; 127 128 std::map<AttributeId, DataElement> attributes_; 129 130 // Additional protocol lists, by id. 131 // Each one of these elements is a sequence of the form that would qualify as 132 // a protocol list (a sequence of sequences of protocols and params) 133 std::unordered_map<ProtocolListId, DataElement> addl_protocols_; 134 135 SecurityLevel security_level_; 136 }; 137 138 } // namespace bt::sdp 139