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 #if OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
40 
41 #include <openthread/srp_client_buffers.h>
42 
43 #include "common/array.hpp"
44 #include "common/as_core_type.hpp"
45 #include "common/clearable.hpp"
46 #include "common/locator.hpp"
47 #include "common/non_copyable.hpp"
48 #include "common/pool.hpp"
49 #include "net/srp_client.hpp"
50 
51 namespace ot {
52 namespace Utils {
53 
54 #if !OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
55 #error "OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE requires OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE feature."
56 #endif
57 
58 /**
59  * Represents the SRP client buffers and service pool.
60  *
61  */
62 class SrpClientBuffers : public InstanceLocator, private NonCopyable
63 {
64 public:
65     /**
66      * Maximum number of service entries in the pool.
67      *
68      */
69     static constexpr uint16_t kMaxServices = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_SERVICES;
70 
71     /**
72      * Max number of host address entries.
73      *
74      */
75     static constexpr uint16_t kMaxHostAddresses = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_MAX_HOST_ADDRESSES;
76 
77     /**
78      * Size (number of char) of host name string (includes null `\0` termination char).
79      *
80      */
81     static constexpr uint16_t kHostNameSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_HOST_NAME_SIZE;
82 
83     /**
84      * Size (number of char) of service name string (includes null `\0` termination char).
85      *
86      */
87     static constexpr uint16_t kServiceNameSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_NAME_SIZE;
88 
89     /**
90      * Array length for service subtype label.
91      *
92      */
93     static constexpr uint16_t kServiceMaxSubTypes = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_MAX_SUB_TYPES;
94 
95     /**
96      * Size (number of char) of service instance name string (includes null `\0` termination char).
97      *
98      */
99     static constexpr uint16_t kInstanceNameSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_SERVICE_INSTANCE_NAME_SIZE;
100 
101     /**
102      * Size (number of bytes) of TXT record buffer.
103      *
104      */
105     static constexpr uint16_t kTxtBufferSize = OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_TXT_BUFFER_SIZE;
106 
107     /**
108      * Represents a SRP client service entry from the pool.
109      *
110      */
111     class ServiceEntry : public otSrpClientBuffersServiceEntry, public Clearable<ServiceEntry>
112     {
113         friend class SrpClientBuffers;
114         friend class LinkedList<ServiceEntry>;
115 
116     public:
117         /**
118          * Gets the string buffer for the service name from the service entry.
119          *
120          * @param[out] aSize    Reference to a variable to return the size (number of bytes) of the string buffer.
121          *
122          * @returns A pointer to the string buffer.
123          *
124          */
GetServiceNameString(uint16_t & aSize)125         char *GetServiceNameString(uint16_t &aSize)
126         {
127             aSize = sizeof(mServiceName);
128             return mServiceName;
129         }
130 
131         /**
132          * Gets the string buffer for the instance name from the service entry.
133          *
134          * @param[out] aSize    Reference to a variable to return the size (number of bytes) of the string buffer.
135          *
136          * @returns A pointer to the string buffer.
137          *
138          */
GetInstanceNameString(uint16_t & aSize)139         char *GetInstanceNameString(uint16_t &aSize)
140         {
141             aSize = sizeof(mInstanceName);
142             return mInstanceName;
143         }
144 
145         /**
146          * Gets the buffer for the TXT value from the service entry.
147          *
148          * @param[out] aSize    Reference to a variable to return the size (number of bytes) of the buffer.
149          *
150          * @returns A pointer to the buffer.
151          *
152          */
GetTxtBuffer(uint16_t & aSize)153         uint8_t *GetTxtBuffer(uint16_t &aSize)
154         {
155             aSize = sizeof(mTxtBuffer);
156             return mTxtBuffer;
157         }
158 
159         /**
160          * Gets the array for service subtype labels from the service entry.
161          *
162          * @param[out] aArrayLength    Reference to a variable to return the array length.
163          *
164          * @returns A pointer to the array.
165          *
166          */
GetSubTypeLabelsArray(uint16_t & aArrayLength)167         const char **GetSubTypeLabelsArray(uint16_t &aArrayLength)
168         {
169             aArrayLength = GetArrayLength(mSubTypeLabels);
170             return mSubTypeLabels;
171         }
172 
173     private:
GetNext(void)174         ServiceEntry       *GetNext(void) { return reinterpret_cast<ServiceEntry *>(mService.mNext); }
GetNext(void) const175         const ServiceEntry *GetNext(void) const { return reinterpret_cast<const ServiceEntry *>(mService.mNext); }
SetNext(ServiceEntry * aEntry)176         void SetNext(ServiceEntry *aEntry) { mService.mNext = reinterpret_cast<Srp::Client::Service *>(aEntry); }
177 
178         char        mServiceName[kServiceNameSize];
179         char        mInstanceName[kInstanceNameSize];
180         uint8_t     mTxtBuffer[kTxtBufferSize];
181         const char *mSubTypeLabels[kServiceMaxSubTypes + 1];
182     };
183 
184     /**
185      * Initializes the `SrpClientBuffers` object.
186      *
187      * @param[in]  aInstance  A reference to the OpenThread instance.
188      *
189      */
190     explicit SrpClientBuffers(Instance &aInstance);
191 
192     /**
193      * Gets the string buffer to use for SRP client host name.
194      *
195      * @param[out] aSize      Reference to a variable to return the size (number of bytes) of the string buffer.
196      *
197      * @returns A pointer to char buffer to use for SRP client host name.
198      *
199      */
GetHostNameString(uint16_t & aSize)200     char *GetHostNameString(uint16_t &aSize)
201     {
202         aSize = sizeof(mHostName);
203         return mHostName;
204     }
205 
206     /**
207      * Gets the array of IPv6 address entries to use as SRP client host address list.
208      *
209      * @param[out] aArrayLength  Reference to a variable to return the array length (number of IPv6 address entries in
210      * *                         the array).
211      *
212      * @returns A pointer to an array of `Ip6::Address` entries (number of entries is returned in @p aArrayLength).
213      *
214      */
GetHostAddressesArray(uint8_t & aArrayLength)215     Ip6::Address *GetHostAddressesArray(uint8_t &aArrayLength)
216     {
217         aArrayLength = static_cast<uint8_t>(GetArrayLength(mHostAddresses));
218         return &mHostAddresses[0];
219     }
220 
221     /**
222      * Allocates a new service entry from the pool.
223      *
224      * The returned service entry instance will be initialized as follows:
225      *
226      *  - `mService.mName` points to a string buffer which can be retrieved using `GetServiceNameString()`.
227      *  - `mService.mInstanceName` points to a string buffer which can be retrieved using `GetInstanceNameString()`.
228      *  - `mService.mSubTypeLabels` points to array which can be retrieved using `GetSubTypeLabelsArray()`.
229      *  - `mService.mTxtEntries` points to `mTxtEntry`.
230      *  - `mService.mNumTxtEntries` is set to one (one entry in the list).
231      *  - Other `mService` fields (port, priority, weight) are set to zero.
232      *  - `mTxtEntry.mKey` is set to `nullptr` (value is treated as already encoded data).
233      *  - `mTxtEntry.mValue` points to a buffer which can be retrieved using `GetTxtBuffer()`
234      *  - `mTxtEntry.mValueLength` is set to zero.
235      *  - All related data/string buffers and arrays are cleared to all zero.
236      *
237      * @returns A pointer to the newly allocated service entry or `nullptr` if not more entry available in the pool.
238      *
239      */
240     ServiceEntry *AllocateService(void);
241 
242     /**
243      * Frees a previously allocated service entry.
244      *
245      * The @p aService MUST be previously allocated using `AllocateService()` and not yet freed. Otherwise the behavior
246      * of this method is undefined.
247      *
248      * @param[in] aServiceEntry     A service entry to free.
249      *
250      */
FreeService(ServiceEntry & aServiceEntry)251     void FreeService(ServiceEntry &aServiceEntry) { mServicePool.Free(aServiceEntry); }
252 
253     /**
254      * Frees all previously allocated service entries.
255      *
256      */
FreeAllServices(void)257     void FreeAllServices(void) { mServicePool.FreeAll(); }
258 
259 private:
260     char                             mHostName[kHostNameSize];
261     Ip6::Address                     mHostAddresses[kMaxHostAddresses];
262     Pool<ServiceEntry, kMaxServices> mServicePool;
263 };
264 
265 } // namespace Utils
266 
267 DefineCoreType(otSrpClientBuffersServiceEntry, Utils::SrpClientBuffers::ServiceEntry);
268 
269 } // namespace ot
270 
271 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_BUFFERS_ENABLE
272 
273 #endif // SRP_CLIENT_BUFFERS_HPP_
274