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