• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2020, 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 #ifndef SRP_CLIENT_HPP_
30 #define SRP_CLIENT_HPP_
31 
32 #include "openthread-core-config.h"
33 
34 #if OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
35 
36 #include <openthread/srp_client.h>
37 
38 #include "common/as_core_type.hpp"
39 #include "common/clearable.hpp"
40 #include "common/linked_list.hpp"
41 #include "common/locator.hpp"
42 #include "common/log.hpp"
43 #include "common/message.hpp"
44 #include "common/non_copyable.hpp"
45 #include "common/notifier.hpp"
46 #include "common/numeric_limits.hpp"
47 #include "common/timer.hpp"
48 #include "crypto/ecdsa.hpp"
49 #include "net/dns_types.hpp"
50 #include "net/ip6.hpp"
51 #include "net/udp6.hpp"
52 #include "thread/network_data_service.hpp"
53 
54 /**
55  * @file
56  *   This file includes definitions for the SRP (Service Registration Protocol) client.
57  */
58 
59 namespace ot {
60 namespace Srp {
61 
62 #if !OPENTHREAD_CONFIG_ECDSA_ENABLE
63 #error "SRP Client feature requires ECDSA support (OPENTHREAD_CONFIG_ECDSA_ENABLE)."
64 #endif
65 
66 /**
67  * This class implements SRP client.
68  *
69  */
70 class Client : public InstanceLocator, private NonCopyable
71 {
72     friend class ot::Notifier;
73 
74     using DnsSrpUnicast = NetworkData::Service::DnsSrpUnicast;
75     using DnsSrpAnycast = NetworkData::Service::DnsSrpAnycast;
76 
77 public:
78     /**
79      * This enumeration types represents an SRP client item (service or host info) state.
80      *
81      */
82     enum ItemState : uint8_t
83     {
84         kToAdd      = OT_SRP_CLIENT_ITEM_STATE_TO_ADD,     ///< Item to be added/registered.
85         kAdding     = OT_SRP_CLIENT_ITEM_STATE_ADDING,     ///< Item is being added/registered.
86         kToRefresh  = OT_SRP_CLIENT_ITEM_STATE_TO_REFRESH, ///< Item to be refreshed (renew lease).
87         kRefreshing = OT_SRP_CLIENT_ITEM_STATE_REFRESHING, ///< Item is being refreshed.
88         kToRemove   = OT_SRP_CLIENT_ITEM_STATE_TO_REMOVE,  ///< Item to be removed.
89         kRemoving   = OT_SRP_CLIENT_ITEM_STATE_REMOVING,   ///< Item is being removed.
90         kRegistered = OT_SRP_CLIENT_ITEM_STATE_REGISTERED, ///< Item is registered with server.
91         kRemoved    = OT_SRP_CLIENT_ITEM_STATE_REMOVED,    ///< Item is removed.
92     };
93 
94     /**
95      * This function pointer type defines the callback used by SRP client to notify user of a changes/events/errors.
96      *
97      * Please see `otSrpClientCallback` for more details.
98      *
99      */
100     typedef otSrpClientCallback Callback;
101 
102     /**
103      * This type represents an SRP client host info.
104      *
105      */
106     class HostInfo : public otSrpClientHostInfo, private Clearable<HostInfo>
107     {
108         friend class Client;
109 
110     public:
111         /**
112          * This method initializes the `HostInfo` object.
113          *
114          */
115         void Init(void);
116 
117         /**
118          * This method clears the `HostInfo` object.
119          *
120          */
121         void Clear(void);
122 
123         /**
124          * This method gets the host name (label) string.
125          *
126          * @returns The host name (label) string, or `nullptr` if not yet set.
127          *
128          */
GetName(void) const129         const char *GetName(void) const { return mName; }
130 
131         /**
132          * This method indicates whether or not the host auto address mode is enabled.
133          *
134          * @retval TRUE  If the auto address mode is enabled.
135          * @retval FALSE If the auto address mode is disabled.
136          *
137          */
IsAutoAddressEnabled(void) const138         bool IsAutoAddressEnabled(void) const { return mAutoAddress; }
139 
140         /**
141          * This method gets the number of host IPv6 addresses.
142          *
143          * @returns The number of host IPv6 addresses.
144          *
145          */
GetNumAddresses(void) const146         uint8_t GetNumAddresses(void) const { return mNumAddresses; }
147 
148         /**
149          * This method gets the host IPv6 address at a given index.
150          *
151          * @param[in] aIndex  The index to get (MUST be smaller than `GetNumAddresses()`).
152          *
153          * @returns  The host IPv6 address at index @p aIndex.
154          *
155          */
GetAddress(uint8_t aIndex) const156         const Ip6::Address &GetAddress(uint8_t aIndex) const { return AsCoreType(&mAddresses[aIndex]); }
157 
158         /**
159          * This method gets the state of `HostInfo`.
160          *
161          * @returns The `HostInfo` state.
162          *
163          */
GetState(void) const164         ItemState GetState(void) const { return static_cast<ItemState>(mState); }
165 
166     private:
SetName(const char * aName)167         void SetName(const char *aName) { mName = aName; }
168         void SetState(ItemState aState);
169         void SetAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses);
170         void EnableAutoAddress(void);
171     };
172 
173     /**
174      * This type represents an SRP client service.
175      *
176      */
177     class Service : public otSrpClientService, public LinkedListEntry<Service>
178     {
179         friend class Client;
180         friend class LinkedList<Service>;
181 
182     public:
183         /**
184          * This method initializes and validates the `Service` object and its fields.
185          *
186          * @retval kErrorNone         Successfully initialized and validated the `Service` object.
187          * @retval kErrorInvalidArgs  The info in `Service` object is not valid (e.g. null name or bad `TxtEntry`).
188          *
189          */
190         Error Init(void);
191 
192         /**
193          * This method gets the service name labels string.
194          *
195          * @returns The service name label string (e.g., "_chip._udp", not the full domain name).
196          *
197          */
GetName(void) const198         const char *GetName(void) const { return mName; }
199 
200         /**
201          * This method gets the service instance name label (not the full name).
202          *
203          * @returns The service instance name label string.
204          *
205          */
GetInstanceName(void) const206         const char *GetInstanceName(void) const { return mInstanceName; }
207 
208         /**
209          * This method indicates whether or not the service has any subtypes.
210          *
211          * @retval TRUE   The service has at least one subtype.
212          * @retval FALSE  The service does not have any subtype.
213          *
214          */
HasSubType(void) const215         bool HasSubType(void) const { return (mSubTypeLabels != nullptr); }
216 
217         /**
218          * This method gets the subtype label at a given index.
219          *
220          * This method MUST be used only after `HasSubType()` indicates that service has a subtype.
221          *
222          * @param[in] aIndex  The index into list of subtype labels.
223          *
224          * @returns A pointer to subtype label at @p aIndex, or `nullptr` if there is no label (@p aIndex is after the
225          *          end of the subtype list).
226          *
227          */
GetSubTypeLabelAt(uint16_t aIndex) const228         const char *GetSubTypeLabelAt(uint16_t aIndex) const { return mSubTypeLabels[aIndex]; }
229 
230         /**
231          * This method gets the service port number.
232          *
233          * @returns The service port number.
234          *
235          */
GetPort(void) const236         uint16_t GetPort(void) const { return mPort; }
237 
238         /**
239          * This method gets the service priority.
240          *
241          * @returns The service priority.
242          *
243          */
GetPriority(void) const244         uint16_t GetPriority(void) const { return mPriority; }
245 
246         /**
247          * This method gets the service weight.
248          *
249          * @returns The service weight.
250          *
251          */
GetWeight(void) const252         uint16_t GetWeight(void) const { return mWeight; }
253 
254         /**
255          * This method gets the array of service TXT entries.
256          *
257          * @returns A pointer to an array of service TXT entries.
258          *
259          */
GetTxtEntries(void) const260         const Dns::TxtEntry *GetTxtEntries(void) const { return AsCoreTypePtr(mTxtEntries); }
261 
262         /**
263          * This method gets the number of entries in the service TXT entry array.
264          *
265          * @returns The number of entries in the service TXT entry array.
266          *
267          */
GetNumTxtEntries(void) const268         uint8_t GetNumTxtEntries(void) const { return mNumTxtEntries; }
269 
270         /**
271          * This method get the state of service.
272          *
273          * @returns The service state.
274          *
275          */
GetState(void) const276         ItemState GetState(void) const { return static_cast<ItemState>(mState); }
277 
278     private:
279         void      SetState(ItemState aState);
GetLeaseRenewTime(void) const280         TimeMilli GetLeaseRenewTime(void) const { return TimeMilli(mData); }
SetLeaseRenewTime(TimeMilli aTime)281         void      SetLeaseRenewTime(TimeMilli aTime) { mData = aTime.GetValue(); }
282         bool      Matches(const Service &aOther) const;
Matches(ItemState aState) const283         bool      Matches(ItemState aState) const { return GetState() == aState; }
284     };
285 
286     /**
287      * This constructor initializes the SRP `Client` object.
288      *
289      * @param[in]  aInstance  A reference to the OpenThread instance.
290      *
291      */
292     explicit Client(Instance &aInstance);
293 
294     /**
295      * This method starts the SRP client operation.
296      *
297      * SRP client will prepare and send "SRP Update" message to the SRP server once all the following conditions are
298      * met:
299      *
300      *  - The SRP client is started - `Start()` is called
301      *  - Host name is set - `SetHostName()` is called.
302      *  - At least one host IPv6 address is set - `SetHostAddresses()` is called.
303      *  - At least one service is added - `AddService()` is called.
304      *
305      * It does not matter in which order these methods are called. When all conditions are met, the SRP client will
306      * wait for a short delay before preparing an "SRP Update" message and sending it to server. This delay allows for
307      * user to add multiple services and/or IPv6 addresses before the first SRP Update message is sent (ensuring a
308      * single SRP Update is sent containing all the info).
309      *
310      * @param[in] aServerSockAddr  The socket address (IPv6 address and port number) of the SRP server.
311      *
312      * @retval kErrorNone     SRP client operation started successfully or it is already running with same server
313      *                        socket address and callback.
314      * @retval kErrorBusy     SRP client is busy running with a different socket address.
315      * @retval kErrorFailed   Failed to open/connect the client's UDP socket.
316      *
317      */
Start(const Ip6::SockAddr & aServerSockAddr)318     Error Start(const Ip6::SockAddr &aServerSockAddr) { return Start(aServerSockAddr, kRequesterUser); }
319 
320     /**
321      * This method stops the SRP client operation.
322      *
323      * This method stops any further interactions with the SRP server. Note that it does not remove or clear host info
324      * and/or list of services. It marks all services to be added/removed again once the client is started again.
325      *
326      * If `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE` (auto-start feature) is enabled, a call to this method
327      * also disables the auto-start mode.
328      *
329      */
Stop(void)330     void Stop(void) { Stop(kRequesterUser, kResetRetryInterval); }
331 
332 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
333     /**
334      * This function pointer type defines the callback used by SRP client to notify user when it is auto-started or
335      * stopped.
336      *
337      */
338     typedef otSrpClientAutoStartCallback AutoStartCallback;
339 
340     /**
341      * This method enables the auto-start mode.
342      *
343      * Config option `OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE` specifies the default auto-start mode
344      * (whether it is enabled or disabled at the start of OT stack).
345      *
346      * When auto-start is enabled, the SRP client will monitor the Thread Network Data for SRP Server Service entries
347      * and automatically start and stop the client when an SRP server is detected.
348      *
349      * If multiple SRP servers are found, a random one will be selected. If the selected SRP server is no longer
350      * detected (not longer present in the Thread Network Data), the SRP client will be stopped and then it may switch
351      * to another SRP server (if available).
352      *
353      * When the SRP client is explicitly started through a successful call to `Start()`, the given SRP server address
354      * in `Start()` will continue to be used regardless of the state of auto-start mode and whether the same SRP
355      * server address is discovered or not in the Thread Network Data. In this case, only an explicit `Stop()` call
356      * will stop the client.
357      *
358      * @param[in] aCallback   A callback to notify when client is auto-started/stopped. Can be `nullptr` if not needed.
359      * @param[in] aContext    A context to be passed when invoking @p aCallback.
360      *
361      */
362     void EnableAutoStartMode(AutoStartCallback aCallback, void *aContext);
363 
364     /**
365      * This method disables the auto-start mode.
366      *
367      * Disabling the auto-start mode will not stop the client if it is already running but the client stops monitoring
368      * the Thread Network Data to verify that the selected SRP server is still present in it.
369      *
370      * Note that a call to `Stop()` will also disable the auto-start mode.
371      *
372      */
DisableAutoStartMode(void)373     void DisableAutoStartMode(void) { mAutoStart.SetState(AutoStart::kDisabled); }
374 
375     /**
376      * This method indicates the current state of auto-start mode (enabled or disabled).
377      *
378      * @returns TRUE if the auto-start mode is enabled, FALSE otherwise.
379      *
380      */
IsAutoStartModeEnabled(void) const381     bool IsAutoStartModeEnabled(void) const { return mAutoStart.GetState() != AutoStart::kDisabled; }
382 
383     /**
384      * This method indicates whether or not the current SRP server's address is selected by auto-start.
385      *
386      * @returns TRUE if the SRP server's address is selected by auto-start, FALSE otherwise.
387      *
388      */
IsServerSelectedByAutoStart(void) const389     bool IsServerSelectedByAutoStart(void) const { return mAutoStart.HasSelectedServer(); }
390 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
391 
392     /**
393      * This method indicates whether the SRP client is running or not.
394      *
395      * @returns TRUE if the SRP client is running, FALSE otherwise.
396      *
397      */
IsRunning(void) const398     bool IsRunning(void) const { return (mState != kStateStopped); }
399 
400     /**
401      * This method gets the socket address (IPv6 address and port number) of the SRP server which is being used by SRP
402      * client.
403      *
404      * If the client is not running, the address is unspecified (all zero) with zero port number.
405      *
406      * @returns The SRP server's socket address.
407      *
408      */
GetServerAddress(void) const409     const Ip6::SockAddr &GetServerAddress(void) const { return mSocket.GetPeerName(); }
410 
411     /**
412      * This method sets the callback used to notify caller of events/changes.
413      *
414      * The SRP client allows a single callback to be registered. So consecutive calls to this method will overwrite any
415      * previously set callback functions.
416      *
417      * @param[in] aCallback        The callback to notify of events and changes. Can be `nullptr` if not needed.
418      * @param[in] aContext         An arbitrary context used with @p aCallback.
419      *
420      */
421     void SetCallback(Callback aCallback, void *aContext);
422 
423     /**
424      * This method gets the TTL used in SRP update requests.
425      *
426      * Note that this is the TTL requested by the SRP client. The server may choose to accept a different TTL.
427      *
428      * By default, the TTL will equal the lease interval. Passing 0 or a value larger than the lease interval via
429      * `otSrpClientSetTtl()` will also cause the TTL to equal the lease interval.
430      *
431      * @returns The TTL (in seconds).
432      *
433      */
GetTtl(void) const434     uint32_t GetTtl(void) const { return (0 < mTtl && mTtl < mLeaseInterval) ? mTtl : mLeaseInterval; }
435 
436     /**
437      * This method sets the TTL used in SRP update requests.
438      *
439      * Changing the TTL does not impact the TTL of already registered services/host-info.
440      * It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services).
441      *
442      * @param[in] aTtl  The TTL (in seconds). If value is zero or greater than lease interval, the TTL is set to the
443      *                  lease interval.
444      *
445      */
SetTtl(uint32_t aTtl)446     void SetTtl(uint32_t aTtl) { mTtl = aTtl; }
447 
448     /**
449      * This method gets the lease interval used in SRP update requests.
450      *
451      * Note that this is lease duration that would be requested by the SRP client. Server may choose to accept a
452      * different lease interval.
453      *
454      * @returns The lease interval (in seconds).
455      *
456      */
GetLeaseInterval(void) const457     uint32_t GetLeaseInterval(void) const { return mLeaseInterval; }
458 
459     /**
460      * This method sets the lease interval used in SRP update requests.
461      *
462      * Changing the lease interval does not impact the accepted lease interval of already registered services/host-info.
463      * It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services).
464      *
465      * @param[in] aInterval  The lease interval (in seconds). If zero, the default value `kDefaultLease` would be used.
466      *
467      */
SetLeaseInterval(uint32_t aInterval)468     void SetLeaseInterval(uint32_t aInterval) { mLeaseInterval = GetBoundedLeaseInterval(aInterval, kDefaultLease); }
469 
470     /**
471      * This method gets the key lease interval used in SRP update requests.
472      *
473      * @returns The key lease interval (in seconds).
474      *
475      */
GetKeyLeaseInterval(void) const476     uint32_t GetKeyLeaseInterval(void) const { return mKeyLeaseInterval; }
477 
478     /**
479      * This method sets the key lease interval used in SRP update requests.
480      *
481      * Changing the lease interval does not impact the accepted lease interval of already registered services/host-info.
482      * It only changes any future SRP update messages (i.e adding new services and/or refreshes of existing services).
483      *
484      * @param[in] aInterval The key lease interval (in seconds). If zero, the default value `kDefaultKeyLease` would be
485      *                      used.
486      *
487      */
SetKeyLeaseInterval(uint32_t aInterval)488     void SetKeyLeaseInterval(uint32_t aInterval)
489     {
490         mKeyLeaseInterval = GetBoundedLeaseInterval(aInterval, kDefaultKeyLease);
491     }
492 
493     /**
494      * This method gets the host info.
495      *
496      * @returns A reference to host info structure.
497      *
498      */
GetHostInfo(void) const499     const HostInfo &GetHostInfo(void) const { return mHostInfo; }
500 
501     /**
502      * This method sets the host name label.
503      *
504      * After a successful call to this method, `Callback` will be called to report the status of host info
505      *  registration with SRP server.
506      *
507      * The host name can be set before client is started or after start but before host info is registered with server
508      * (host info should be in either `kToAdd` or `kRemoved`).
509      *
510      * @param[in] aName       A pointer to host name label string (MUST NOT be NULL). Pointer the string buffer MUST
511      *                        persist and remain valid and constant after return from this method.
512      *
513      * @retval kErrorNone           The host name label was set successfully.
514      * @retval kErrorInvalidArgs    The @p aName is NULL.
515      * @retval kErrorInvalidState   The host name is already set and registered with the server.
516      *
517      */
518     Error SetHostName(const char *aName);
519 
520     /**
521      * This method enables auto host address mode.
522      *
523      * When enabled host IPv6 addresses are automatically set by SRP client using all the unicast addresses on Thread
524      * netif excluding the link-local and mesh-local addresses. If there is no valid address, then Mesh Local EID
525      * address is added. The SRP client will automatically re-register when/if addresses on Thread netif are updated
526      * (new addresses are added or existing addresses are removed).
527      *
528      * The auto host address mode can be enabled before start or during operation of SRP client except when the host
529      * info is being removed (client is busy handling a remove request from an call to `RemoveHostAndServices()` and
530      * host info still being in  either `kStateToRemove` or `kStateRemoving` states).
531      *
532      * After auto host address mode is enabled, it can be disabled by a call to `SetHostAddresses()` which then
533      * explicitly sets the host addresses.
534      *
535      * @retval kErrorNone          Successfully enabled auto host address mode.
536      * @retval kErrorInvalidState  Host is being removed and therefore cannot enable auto host address mode.
537      *
538      */
539     Error EnableAutoHostAddress(void);
540 
541     /**
542      * This method sets/updates the list of host IPv6 address.
543      *
544      * Host IPv6 addresses can be set/changed before start or even during operation of SRP client (e.g. to add/remove
545      * or change a previously registered host address), except when the host info is being removed (client is busy
546      * handling a remove request from an earlier call to `RemoveHostAndServices()` and host info still being in either
547      * `kStateToRemove` or `kStateRemoving` states).
548      *
549      * After a successful call to this method, `Callback` will be called to report the status of the address
550      * registration with SRP server.
551      *
552      * Calling this method disables auto host address mode if it was previously enabled from a successful call to
553      * `EnableAutoHostAddress()`.
554      *
555      * @param[in] aAddresses          A pointer to the an array containing the host IPv6 addresses.
556      * @param[in] aNumAddresses       The number of addresses in the @p aAddresses array.
557      *
558      * @retval kErrorNone           The host IPv6 address list change started successfully. The `Callback` will be
559      *                              called to report the status of registering addresses with server.
560      * @retval kErrorInvalidArgs    The address list is invalid (e.g., must contain at least one address).
561      * @retval kErrorInvalidState   Host is being removed and therefore cannot change host address.
562      *
563      */
564     Error SetHostAddresses(const Ip6::Address *aAddresses, uint8_t aNumAddresses);
565 
566     /**
567      * This method adds a service to be registered with server.
568      *
569      * After a successful call to this method, `Callback` will be called to report the status of the service
570      * addition/registration with SRP server.
571      *
572      * @param[in] aService         A `Service` to add (the instance must persist and remain unchanged after
573      *                             successful return from this method).
574      *
575      * @retval kErrorNone          The addition of service started successfully. The `Callback` will be called to
576      *                             report the status.
577      * @retval kErrorAlready       A service with the same service and instance names is already in the list.
578      * @retval kErrorInvalidArgs   The service structure is invalid (e.g., bad service name or `TxEntry`).
579      *
580      */
581     Error AddService(Service &aService);
582 
583     /**
584      * This method removes a service to be unregistered with server.
585      *
586      * @param[in] aService         A `Service` to remove (the instance must persist and remain unchanged after
587      *                             successful return from this method).
588      *
589      * @retval kErrorNone      The removal of service started successfully. The `Callback` will be called to report
590      *                         the status.
591      * @retval kErrorNotFound  The service could not be found in the list.
592      *
593      */
594 
595     Error RemoveService(Service &aService);
596 
597     /**
598      * This method clears a service, immediately removing it from the client service list.
599      *
600      * Unlike `RemoveService()` which sends an update message to the server to remove the service, this method clears
601      * the service from the client's service list without any interaction with the server. On a successful call
602      * to this method, the `Callback` will NOT be called and the @p aService entry can be reclaimed and re-used by the
603      * caller immediately.
604      *
605      * @param[in] aService     A service to delete from the list.
606      *
607      * @retval kErrorNone      The @p aService is cleared successfully. It can be reclaimed and re-used immediately.
608      * @retval kErrorNotFound  The service could not be found in the list.
609      *
610      */
611     Error ClearService(Service &aService);
612 
613     /**
614      * This method gets the list of services being managed by client.
615      *
616      * @returns The list of services.
617      *
618      */
GetServices(void) const619     const LinkedList<Service> &GetServices(void) const { return mServices; }
620 
621     /**
622      * This method starts the remove process of the host info and all services.
623      *
624      * After returning from this method, `Callback` will be called to report the status of remove request with
625      * SRP server.
626      *
627      * If the host info is to be permanently removed from server, @p aRemoveKeyLease should be set to `true` which
628      * removes the key lease associated with host on server. Otherwise, the key lease record is kept as before, which
629      * ensures that the server holds the host name in reserve for when the client once again able to provide and
630      * register its service(s).
631      *
632      * The @p aSendUnregToServer determines the behavior when the host info is not yet registered with the server. If
633      * @p aSendUnregToServer is set to `false` (which is the default/expected value) then the SRP client will
634      * immediately remove the host info and services without sending an update message to server (no need to update the
635      * server if nothing is yet registered with it). If @p aSendUnregToServer is set to `true` then the SRP client will
636      * send an update message to the server. Note that if the host info is registered then the value of
637      * @p aSendUnregToServer does not matter and the SRP client will always send an update message to server requesting
638      * removal of all info.
639      *
640      * One situation where @p aSendUnregToServer can be useful is on a device reset/reboot, caller may want to remove
641      * any previously registered services with the server. In this case, caller can `SetHostName()` and then request
642      * `RemoveHostAndServices()` with `aSendUnregToServer` as `true`.
643      *
644      * @param[in] aShouldRemoveKeyLease  A boolean indicating whether or not the host key lease should also be removed.
645      * @param[in] aSendUnregToServer     A boolean indicating whether to send update to server when host info is not
646      *                                   registered.
647      *
648      * @retval kErrorNone      The removal of host and services started successfully. The `Callback` will be called
649      *                         to report the status.
650      * @retval kErrorAlready   The host is already removed.
651      *
652      */
653     Error RemoveHostAndServices(bool aShouldRemoveKeyLease, bool aSendUnregToServer = false);
654 
655     /**
656      * This method clears all host info and all the services.
657      *
658      * Unlike `RemoveHostAndServices()` which sends an update message to the server to remove all the info, this method
659      * clears all the info immediately without any interaction with the server.
660      *
661      */
662     void ClearHostAndServices(void);
663 
664 #if OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE
665     /**
666      * This method gets the domain name being used by SRP client.
667      *
668      * If domain name is not set, "default.service.arpa" will be used.
669      *
670      * @returns The domain name string.
671      *
672      */
GetDomainName(void) const673     const char *GetDomainName(void) const { return mDomainName; }
674 
675     /**
676      * This method sets the domain name to be used by SRP client.
677      *
678      * This is an optional method. If not set "default.service.arpa" will be used.
679      *
680      * The domain name can be set before client is started or after start but before host info is registered with server
681      * (host info should be in either `kToAdd` or `kToRemove`).
682      *
683      * @param[in] aName      A pointer to the domain name string. If NULL sets it to default "default.service.arpa".
684      *
685      * @retval kErrorNone           The domain name label was set successfully.
686      * @retval kErrorInvalidState   The host info is already registered with server.
687      *
688      */
689     Error SetDomainName(const char *aName);
690 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_DOMAIN_NAME_API_ENABLE
691 
692     /**
693      * This static method converts a `ItemState` to a string.
694      *
695      * @param[in] aState   An `ItemState`.
696      *
697      * @returns A string representation of @p aState.
698      *
699      */
700     static const char *ItemStateToString(ItemState aState);
701 
702 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
703     /**
704      * This method enables/disables "service key record inclusion" mode.
705      *
706      * When enabled, SRP client will include KEY record in Service Description Instructions in the SRP update messages
707      * that it sends.
708      *
709      * @note KEY record is optional in Service Description Instruction (it is required and always included in the Host
710      * Description Instruction). The default behavior of SRP client is to not include it. This method is added under
711      * `REFERENCE_DEVICE` config and is intended to override the default behavior for testing only.
712      *
713      * @param[in] aEnabled   TRUE to enable, FALSE to disable the "service key record inclusion" mode.
714      *
715      */
SetServiceKeyRecordEnabled(bool aEnabled)716     void SetServiceKeyRecordEnabled(bool aEnabled) { mServiceKeyRecordEnabled = aEnabled; }
717 
718     /**
719      * This method indicates whether the "service key record inclusion" mode is enabled or disabled.
720      *
721      * @returns TRUE if "service key record inclusion" mode is enabled, FALSE otherwise.
722      *
723      */
IsServiceKeyRecordEnabled(void) const724     bool IsServiceKeyRecordEnabled(void) const { return mServiceKeyRecordEnabled; }
725 #endif // OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
726 
727 private:
728     // Number of fast data polls after SRP Update tx (11x 188ms = ~2 seconds)
729     static constexpr uint8_t kFastPollsAfterUpdateTx = 11;
730 
731 #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
732     static constexpr uint8_t kMaxTimeoutFailuresToSwitchServer =
733         OPENTHREAD_CONFIG_SRP_CLIENT_MAX_TIMEOUT_FAILURES_TO_SWITCH_SERVER;
734 #endif
735 
736     static constexpr uint16_t kUdpPayloadSize = Ip6::kMaxDatagramLength - sizeof(Ip6::Udp::Header);
737 
738     // -------------------------------
739     // Lease related constants
740 
741     static constexpr uint32_t kDefaultLease    = OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_LEASE;     // in seconds.
742     static constexpr uint32_t kDefaultKeyLease = OPENTHREAD_CONFIG_SRP_CLIENT_DEFAULT_KEY_LEASE; // in seconds.
743 
744     // The guard interval determines how much earlier (relative to
745     // the lease expiration time) the client will send an update
746     // to renew the lease. Value is in seconds.
747     static constexpr uint32_t kLeaseRenewGuardInterval = OPENTHREAD_CONFIG_SRP_CLIENT_LEASE_RENEW_GUARD_INTERVAL;
748 
749     // Max allowed lease time to avoid timer roll-over (~24.8 days).
750     static constexpr uint32_t kMaxLease = (Timer::kMaxDelay / 1000) - 1;
751 
752     // Opportunistic early refresh: When sending an SRP update, the
753     // services that are not yet expired but are close, are allowed
754     // to refresh early and are included in the SRP update. This
755     // helps place more services on the same lease refresh schedule
756     // reducing number of messages sent to the SRP server. The
757     // "early lease renewal interval" is used to determine if a
758     // service can renew early. The interval is calculated by
759     // multiplying the accepted lease interval by the"early lease
760     // renewal factor" which is given as a fraction (numerator and
761     // denominator).
762     //
763     // If the factor is set to zero (numerator=0, denominator=1),
764     // the opportunistic early refresh behavior is disabled. If
765     // denominator is set to zero (the factor is set to infinity),
766     // then all services (including previously registered ones)
767     // are always included in SRP update message.
768 
769     static constexpr uint32_t kEarlyLeaseRenewFactorNumerator =
770         OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_NUMERATOR;
771     static constexpr uint32_t kEarlyLeaseRenewFactorDenominator =
772         OPENTHREAD_CONFIG_SRP_CLIENT_EARLY_LEASE_RENEW_FACTOR_DENOMINATOR;
773 
774     // -------------------------------
775     // When there is a change (e.g., a new service is added/removed)
776     // that requires an update, the SRP client will wait for a short
777     // delay as specified by `kUpdateTxDelay` before sending an SRP
778     // update to server. This allows the user to provide more change
779     // that are then all sent in same update message.
780     static constexpr uint32_t kUpdateTxMinDelay = OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MIN_DELAY; // in msec.
781     static constexpr uint32_t kUpdateTxMaxDelay = OPENTHREAD_CONFIG_SRP_CLIENT_UPDATE_TX_MAX_DELAY; // in msec.
782 
783     // -------------------------------
784     // Retry related constants
785     //
786     // If the preparation or transmission of an SRP update message
787     // fails (e.g., no buffer to allocate the message), SRP client
788     // will retry after a short interval `kTxFailureRetryInterval`
789     // up to `kMaxTxFailureRetries` attempts. After this, the retry
790     // wait interval will be used (which keeps growing on each failure
791     // - please see bellow).
792     //
793     // If the update message is sent successfully but there is no
794     // response from server or if server rejects the update, the
795     // client will retransmit the update message after some wait
796     // interval. The wait interval starts from the minimum value and
797     // is increased by the growth factor on back-to-back failures up
798     // to the max value. The growth factor is given as a fraction
799     // (e.g., for 1.5, we can use 15 as the numerator and 10 as the
800     // denominator). A random jitter is added to the retry interval.
801     // If the current wait interval value is smaller than the jitter
802     // interval, then wait interval value itself is used as the
803     // jitter value. For example, with jitter interval of 2 seconds
804     // if the current retry interval is 800ms, then a random wait
805     // interval in [0,2*800] ms will be used.
806 
807     static constexpr uint32_t kTxFailureRetryInterval = 250; // in ms
808     static constexpr uint32_t kMaxTxFailureRetries    = 8;   // num of quick retries after tx failure
809     static constexpr uint32_t kMinRetryWaitInterval   = OPENTHREAD_CONFIG_SRP_CLIENT_MIN_RETRY_WAIT_INTERVAL; // in ms
810     static constexpr uint32_t kMaxRetryWaitInterval   = OPENTHREAD_CONFIG_SRP_CLIENT_MAX_RETRY_WAIT_INTERVAL; // in ms
811     static constexpr uint32_t kRetryIntervalGrowthFactorNumerator =
812         OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_NUMERATOR;
813     static constexpr uint32_t kRetryIntervalGrowthFactorDenominator =
814         OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_INTERVAL_GROWTH_FACTOR_DENOMINATOR;
815 
816     static constexpr uint16_t kTxFailureRetryJitter = 10;                                                      // in ms
817     static constexpr uint16_t kRetryIntervalJitter  = OPENTHREAD_CONFIG_SRP_CLIENT_RETRY_WAIT_INTERVAL_JITTER; // in ms
818 
819     static_assert(kDefaultLease <= static_cast<uint32_t>(kMaxLease), "kDefaultLease is larger than max");
820     static_assert(kDefaultKeyLease <= static_cast<uint32_t>(kMaxLease), "kDefaultKeyLease is larger than max");
821 
822     enum State : uint8_t
823     {
824         kStateStopped,  // Client is stopped.
825         kStatePaused,   // Client is paused (due to device being detached).
826         kStateToUpdate, // Waiting to send SRP update
827         kStateUpdating, // SRP update is sent, waiting for response from server.
828         kStateUpdated,  // SRP update response received from server.
829         kStateToRetry,  // SRP update tx failed, waiting to retry.
830     };
831 
832     static constexpr bool kAutoStartDefaultMode = OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE;
833     static constexpr bool kDisallowSwitchOnRegisteredHost =
834         OPENTHREAD_CONFIG_SRP_CLIENT_DISALLOW_SERVER_SWITCH_WITH_REGISTERED_HOST;
835 
836     // Port number to use when server is discovered using "network data anycast service".
837     static constexpr uint16_t kAnycastServerPort = 53;
838 
839     // This enumeration type is used by the private `Start()` and
840     // `Stop()` methods to indicate whether it is being requested by the
841     // user or by the auto-start feature.
842     enum Requester : uint8_t
843     {
844         kRequesterUser,
845 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
846         kRequesterAuto,
847 #endif
848     };
849 
850     // This enumeration is used as an input to private `Stop()` to
851     // indicate whether to reset the retry interval or keep it as is.
852     enum StopMode : uint8_t
853     {
854         kResetRetryInterval,
855         kKeepRetryInterval,
856     };
857 
858     class SingleServiceMode
859     {
860     public:
SingleServiceMode(void)861         SingleServiceMode(void)
862             : mEnabled(false)
863             , mService(nullptr)
864         {
865         }
866 
Enable(void)867         void     Enable(void) { mEnabled = true, mService = nullptr; }
Disable(void)868         void     Disable(void) { mEnabled = false; }
IsEnabled(void) const869         bool     IsEnabled(void) const { return mEnabled; }
GetService(void)870         Service *GetService(void) { return mService; }
SetService(Service & aService)871         void     SetService(Service &aService) { mService = &aService; }
872 
873     private:
874         bool     mEnabled;
875         Service *mService;
876     };
877 
878 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
879     class AutoStart : Clearable<AutoStart>
880     {
881     public:
882         enum State : uint8_t{
883             kDisabled,                 // AutoStart is disabled.
884             kSelectedNone,             // AutoStart is enabled but not yet selected any servers.
885             kSelectedUnicastPreferred, // AutoStart selected a preferred unicast entry (address in service data).
886             kSelectedAnycast,          // AutoStart selected an anycast entry with `mAnycastSeqNum`.
887             kSelectedUnicast,          // AutoStart selected a unicast entry (address in server data).
888         };
889 
890         AutoStart(void);
891         bool    HasSelectedServer(void) const;
GetState(void) const892         State   GetState(void) const { return mState; }
893         void    SetState(State aState);
GetAnycastSeqNum(void) const894         uint8_t GetAnycastSeqNum(void) const { return mAnycastSeqNum; }
SetAnycastSeqNum(uint8_t aAnycastSeqNum)895         void    SetAnycastSeqNum(uint8_t aAnycastSeqNum) { mAnycastSeqNum = aAnycastSeqNum; }
896         void    SetCallback(AutoStartCallback aCallback, void *aContext);
897         void    InvokeCallback(const Ip6::SockAddr *aServerSockAddr) const;
898 
899 #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
GetTimoutFailureCount(void) const900         uint8_t GetTimoutFailureCount(void) const { return mTimoutFailureCount; }
ResetTimoutFailureCount(void)901         void    ResetTimoutFailureCount(void) { mTimoutFailureCount = 0; }
IncrementTimoutFailureCount(void)902         void    IncrementTimoutFailureCount(void)
903         {
904             if (mTimoutFailureCount < NumericLimits<uint8_t>::kMax)
905             {
906                 mTimoutFailureCount++;
907             }
908         }
909 #endif
910 
911     private:
912         static constexpr bool kDefaultMode = OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_DEFAULT_MODE;
913 
914         static const char *StateToString(State aState);
915 
916         AutoStartCallback mCallback;
917         void *            mContext;
918         State             mState;
919         uint8_t           mAnycastSeqNum;
920 #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
921         uint8_t mTimoutFailureCount; // Number of no-response timeout failures with the currently selected server.
922 #endif
923     };
924 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
925 
926     struct Info : public Clearable<Info>
927     {
928         static constexpr uint16_t kUnknownOffset = 0; // Unknown offset value (used when offset is not yet set).
929 
930         uint16_t                     mDomainNameOffset; // Offset of domain name serialization
931         uint16_t                     mHostNameOffset;   // Offset of host name serialization.
932         uint16_t                     mRecordCount;      // Number of resource records in Update section.
933         Crypto::Ecdsa::P256::KeyPair mKeyPair;          // The ECDSA key pair.
934     };
935 
936     Error        Start(const Ip6::SockAddr &aServerSockAddr, Requester aRequester);
937     void         Stop(Requester aRequester, StopMode aMode);
938     void         Resume(void);
939     void         Pause(void);
940     void         HandleNotifierEvents(Events aEvents);
941     void         HandleRoleChanged(void);
942     Error        UpdateHostInfoStateOnAddressChange(void);
943     void         UpdateServiceStateToRemove(Service &aService);
GetState(void) const944     State        GetState(void) const { return mState; }
945     void         SetState(State aState);
946     void         ChangeHostAndServiceStates(const ItemState *aNewStates);
947     void         InvokeCallback(Error aError) const;
948     void         InvokeCallback(Error aError, const HostInfo &aHostInfo, const Service *aRemovedServices) const;
949     void         HandleHostInfoOrServiceChange(void);
950     void         SendUpdate(void);
951     Error        PrepareUpdateMessage(Message &aMessage);
952     Error        ReadOrGenerateKey(Crypto::Ecdsa::P256::KeyPair &aKeyPair);
953     Error        AppendServiceInstructions(Service &aService, Message &aMessage, Info &aInfo);
954     Error        AppendHostDescriptionInstruction(Message &aMessage, Info &aInfo);
955     Error        AppendKeyRecord(Message &aMessage, Info &aInfo) const;
956     Error        AppendDeleteAllRrsets(Message &aMessage) const;
957     Error        AppendHostName(Message &aMessage, Info &aInfo, bool aDoNotCompress = false) const;
958     Error        AppendAaaaRecord(const Ip6::Address &aAddress, Message &aMessage, Info &aInfo) const;
959     Error        AppendUpdateLeaseOptRecord(Message &aMessage) const;
960     Error        AppendSignature(Message &aMessage, Info &aInfo);
961     void         UpdateRecordLengthInMessage(Dns::ResourceRecord &aRecord, uint16_t aOffset, Message &aMessage) const;
962     static void  HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
963     void         ProcessResponse(Message &aMessage);
964     void         HandleUpdateDone(void);
965     void         GetRemovedServices(LinkedList<Service> &aRemovedServices);
966     static Error ReadResourceRecord(const Message &aMessage, uint16_t &aOffset, Dns::ResourceRecord &aRecord);
967     Error        ProcessOptRecord(const Message &aMessage, uint16_t aOffset, const Dns::OptRecord &aOptRecord);
968     void         UpdateState(void);
GetRetryWaitInterval(void) const969     uint32_t     GetRetryWaitInterval(void) const { return mRetryWaitInterval; }
ResetRetryWaitInterval(void)970     void         ResetRetryWaitInterval(void) { mRetryWaitInterval = kMinRetryWaitInterval; }
971     void         GrowRetryWaitInterval(void);
972     uint32_t     GetBoundedLeaseInterval(uint32_t aInterval, uint32_t aDefaultInterval) const;
973     bool         ShouldRenewEarly(const Service &aService) const;
974     static void  HandleTimer(Timer &aTimer);
975     void         HandleTimer(void);
976 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
977     void  ProcessAutoStart(void);
978     Error SelectUnicastEntry(DnsSrpUnicast::Origin aOrigin, DnsSrpUnicast::Info &aInfo) const;
979 #if OPENTHREAD_CONFIG_SRP_CLIENT_SWITCH_SERVER_ON_FAILURE
980     void SelectNextServer(bool aDisallowSwitchOnRegisteredHost);
981 #endif
982 #endif
983 
984 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
985     static const char *StateToString(State aState);
986     void               LogRetryWaitInterval(void) const;
987 #else
LogRetryWaitInterval(void) const988     void LogRetryWaitInterval(void) const {}
989 #endif
990 
991     static const char kDefaultDomainName[];
992 
993     static_assert(kMaxTxFailureRetries < 16, "kMaxTxFailureRetries exceed the range of mTxFailureRetryCount (4-bit)");
994 
995     State   mState;
996     uint8_t mTxFailureRetryCount : 4;
997     bool    mShouldRemoveKeyLease : 1;
998     bool    mAutoHostAddressAddedMeshLocal : 1;
999 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
1000     bool mServiceKeyRecordEnabled : 1;
1001 #endif
1002 
1003     uint16_t mUpdateMessageId;
1004     uint32_t mRetryWaitInterval;
1005 
1006     TimeMilli mLeaseRenewTime;
1007     uint32_t  mAcceptedLeaseInterval;
1008     uint32_t  mTtl;
1009     uint32_t  mLeaseInterval;
1010     uint32_t  mKeyLeaseInterval;
1011 
1012     Ip6::Udp::Socket mSocket;
1013 
1014     Callback            mCallback;
1015     void *              mCallbackContext;
1016     const char *        mDomainName;
1017     HostInfo            mHostInfo;
1018     LinkedList<Service> mServices;
1019     SingleServiceMode   mSingleServiceMode;
1020     TimerMilli          mTimer;
1021 #if OPENTHREAD_CONFIG_SRP_CLIENT_AUTO_START_API_ENABLE
1022     AutoStart mAutoStart;
1023 #endif
1024 };
1025 
1026 } // namespace Srp
1027 
1028 DefineCoreType(otSrpClientHostInfo, Srp::Client::HostInfo);
1029 DefineCoreType(otSrpClientService, Srp::Client::Service);
1030 DefineMapEnum(otSrpClientItemState, Srp::Client::ItemState);
1031 
1032 } // namespace ot
1033 
1034 #endif // OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE
1035 
1036 #endif // SRP_CLIENT_HPP_
1037