• 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 #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