1 /*
2  *  Copyright (c) 2021, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for the SRP client buffers and service pool.
32  */
33 
34 #ifndef SRP_CLIENT_BUFFERS_HPP_
35 #define SRP_CLIENT_BUFFERS_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/srp_client_buffers.h>
40 
41 #include "common/clearable.hpp"
42 #include "common/locator.hpp"
43 #include "common/non_copyable.hpp"
44 #include "common/pool.hpp"
45 #include "net/srp_client.hpp"
46 
47 namespace ot {
48 namespace Utils {
49 
50 #if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
51 
52 #if !OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
53 #error "OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE requires OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE feature."
54 #endif
55 
56 /**
57  * This class represents the SRP client buffers and service pool.
58  *
59  */
60 class SrpClientBuffers : public InstanceLocator, private NonCopyable
61 {
62 public:
63     /**
64      * Maximum number of service entries in the pool.
65      *
66      */
67     static constexpr uint16_t kMaxServices = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES;
68 
69     /**
70      * Max number of host address entries.
71      *
72      */
73     static constexpr uint16_t kMaxHostAddresses = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_HOST_ADDRESSES;
74 
75     /**
76      * Size (number of char) of host name string (includes null `\0` termination char).
77      *
78      */
79     static constexpr uint16_t kHostNameSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_HOST_NAME_SIZE;
80 
81     /**
82      * Size (number of char) of service name string (includes null `\0` termination char).
83      *
84      */
85     static constexpr uint16_t kServiceNameSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_NAME_SIZE;
86 
87     /**
88      * Array length for service subtype label.
89      *
90      */
91     static constexpr uint16_t kServiceMaxSubTypes = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_MAX_SUB_TYPES;
92 
93     /**
94      * Size (number of char) of service instance name string (includes null `\0` termination char).
95      *
96      */
97     static constexpr uint16_t kInstanceNameSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_INSTANCE_NAME_SIZE;
98 
99     /**
100      * Size (number of bytes) of TXT record buffer.
101      *
102      */
103     static constexpr uint16_t kTxtBufferSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_TXT_BUFFER_SIZE;
104 
105     /**
106      * This class represents a SRP client service entry from the pool.
107      *
108      */
109     class ServiceEntry : public otSrpClientBuffersServiceEntry, public Clearable<ServiceEntry>
110     {
111         friend class SrpClientBuffers;
112         friend class LinkedList<ServiceEntry>;
113 
114     public:
115         /**
116          * This method gets the string buffer for the service name from the service entry.
117          *
118          * @param[out] aSize    Reference to a variable to return the size (number of bytes) of the string buffer.
119          *
120          * @returns A pointer to the string buffer.
121          *
122          */
GetServiceNameString(uint16_t & aSize)123         char *GetServiceNameString(uint16_t &aSize)
124         {
125             aSize = sizeof(mServiceName);
126             return mServiceName;
127         }
128 
129         /**
130          * This method gets the string buffer for the instance name from the service entry.
131          *
132          * @param[out] aSize    Reference to a variable to return the size (number of bytes) of the string buffer.
133          *
134          * @returns A pointer to the string buffer.
135          *
136          */
GetInstanceNameString(uint16_t & aSize)137         char *GetInstanceNameString(uint16_t &aSize)
138         {
139             aSize = sizeof(mInstanceName);
140             return mInstanceName;
141         }
142 
143         /**
144          * This method gets the buffer for the TXT value from the service entry.
145          *
146          * @param[out] aSize    Reference to a variable to return the size (number of bytes) of the buffer.
147          *
148          * @returns A pointer to the buffer.
149          *
150          */
GetTxtBuffer(uint16_t & aSize)151         uint8_t *GetTxtBuffer(uint16_t &aSize)
152         {
153             aSize = sizeof(mTxtBuffer);
154             return mTxtBuffer;
155         }
156 
157         /**
158          * This method gets the array for service subtype labels from the service entry.
159          *
160          * @param[out] aArrayLength    Reference to a variable to return the array length.
161          *
162          * @returns A pointer to the array.
163          *
164          */
GetSubTypeLabelsArray(uint16_t & aArrayLength)165         const char **GetSubTypeLabelsArray(uint16_t &aArrayLength)
166         {
167             aArrayLength = OT_ARRAY_LENGTH(mSubTypeLabels);
168             return mSubTypeLabels;
169         }
170 
171     private:
GetNext(void)172         ServiceEntry *      GetNext(void) { return reinterpret_cast<ServiceEntry *>(mService.mNext); }
GetNext(void) const173         const ServiceEntry *GetNext(void) const { return reinterpret_cast<const ServiceEntry *>(mService.mNext); }
SetNext(ServiceEntry * aEntry)174         void SetNext(ServiceEntry *aEntry) { mService.mNext = reinterpret_cast<Srp::Client::Service *>(aEntry); }
175 
176         char        mServiceName[kServiceNameSize];
177         char        mInstanceName[kInstanceNameSize];
178         uint8_t     mTxtBuffer[kTxtBufferSize];
179         const char *mSubTypeLabels[kServiceMaxSubTypes + 1];
180     };
181 
182     /**
183      * This constructor initializes the `SrpClientBuffers` object.
184      *
185      * @param[in]  aInstance  A reference to the OpenThread instance.
186      *
187      */
188     explicit SrpClientBuffers(Instance &aInstance);
189 
190     /**
191      * This method gets the string buffer to use for SRP client host name.
192      *
193      * @param[out] aSize      Reference to a variable to return the size (number of bytes) of the string buffer.
194      *
195      * @returns A pointer to char buffer to use for SRP client host name.
196      *
197      */
GetHostNameString(uint16_t & aSize)198     char *GetHostNameString(uint16_t &aSize)
199     {
200         aSize = sizeof(mHostName);
201         return mHostName;
202     }
203 
204     /**
205      * This method gets the array of IPv6 address entries to use as SRP client host address list.
206      *
207      * @param[out] aArrayLength  Reference to a variable to return the array length (number of IPv6 address entries in
208      * *                         the array).
209      *
210      * @returns A pointer to an array of `Ip6::Address` entries (number of entries is returned in @p aArrayLength).
211      *
212      */
GetHostAddressesArray(uint8_t & aArrayLength)213     Ip6::Address *GetHostAddressesArray(uint8_t &aArrayLength)
214     {
215         aArrayLength = OT_ARRAY_LENGTH(mHostAddresses);
216         return &mHostAddresses[0];
217     }
218 
219     /**
220      * This method allocates a new service entry from the pool.
221      *
222      * The returned service entry instance will be initialized as follows:
223      *
224      *  - `mService.mName` points to a string buffer which can be retrieved using `GetServiceNameString()`.
225      *  - `mService.mInstanceName` points to a string buffer which can be retrieved using `GetInstanceNameString()`.
226      *  - `mService.mSubTypeLabels` points to array which can be retrieved using `GetSubTypeLabelsArray()`.
227      *  - `mService.mTxtEntries` points to `mTxtEntry`.
228      *  - `mService.mNumTxtEntries` is set to one (one entry in the list).
229      *  - Other `mService` fields (port, priority, weight) are set to zero.
230      *  - `mTxtEntry.mKey` is set to `nullptr` (value is treated as already encoded data).
231      *  - `mTxtEntry.mValue` points to a buffer which can be retrieved using `GetTxtBuffer()`
232      *  - `mTxtEntry.mValueLength` is set to zero.
233      *  - All related data/string buffers and arrays are cleared to all zero.
234      *
235      * @returns A pointer to the newly allocated service entry or `nullptr` if not more entry available in the pool.
236      *
237      */
238     ServiceEntry *AllocateService(void);
239 
240     /**
241      * This method frees a previously allocated service entry.
242      *
243      * The @p aService MUST be previously allocated using `AllocateService()` and not yet freed. Otherwise the behavior
244      * of this method is undefined.
245      *
246      * @param[in] aServiceEntry     A service entry to free.
247      *
248      */
FreeService(ServiceEntry & aServiceEntry)249     void FreeService(ServiceEntry &aServiceEntry) { mServicePool.Free(aServiceEntry); }
250 
251     /**
252      * This method frees all previously allocated service entries.
253      *
254      */
FreeAllServices(void)255     void FreeAllServices(void) { mServicePool.FreeAll(); }
256 
257 private:
258     char                             mHostName[kHostNameSize];
259     Ip6::Address                     mHostAddresses[kMaxHostAddresses];
260     Pool<ServiceEntry, kMaxServices> mServicePool;
261 };
262 
263 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
264 
265 } // namespace Utils
266 } // namespace ot
267 
268 #endif // SRP_CLIENT_BUFFERS_HPP_
269