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