• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2021, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file implements Anycast Locator functionality.
32  */
33 
34 #include "anycast_locator.hpp"
35 
36 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
37 
38 #include "common/as_core_type.hpp"
39 #include "common/code_utils.hpp"
40 #include "common/instance.hpp"
41 #include "common/locator_getters.hpp"
42 #include "thread/thread_tlvs.hpp"
43 #include "thread/uri_paths.hpp"
44 
45 namespace ot {
46 
AnycastLocator(Instance & aInstance)47 AnycastLocator::AnycastLocator(Instance &aInstance)
48     : InstanceLocator(aInstance)
49     , mCallback(nullptr)
50     , mContext(nullptr)
51 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_SEND_RESPONSE
52     , mAnycastLocate(UriPath::kAnycastLocate, HandleAnycastLocate, this)
53 #endif
54 
55 {
56 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_SEND_RESPONSE
57     Get<Tmf::Agent>().AddResource(mAnycastLocate);
58 #endif
59 }
60 
Locate(const Ip6::Address & aAnycastAddress,Callback aCallback,void * aContext)61 Error AnycastLocator::Locate(const Ip6::Address &aAnycastAddress, Callback aCallback, void *aContext)
62 {
63     Error            error   = kErrorNone;
64     Coap::Message *  message = nullptr;
65     Tmf::MessageInfo messageInfo(GetInstance());
66 
67     VerifyOrExit((aCallback != nullptr) && Get<Mle::Mle>().IsAnycastLocator(aAnycastAddress),
68                  error = kErrorInvalidArgs);
69 
70     message = Get<Tmf::Agent>().NewConfirmablePostMessage(UriPath::kAnycastLocate);
71     VerifyOrExit(message != nullptr, error = kErrorNoBufs);
72 
73     if (mCallback != nullptr)
74     {
75         IgnoreError(Get<Tmf::Agent>().AbortTransaction(HandleResponse, this));
76     }
77 
78     messageInfo.SetSockAddrToRlocPeerAddrTo(aAnycastAddress);
79 
80     SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo, HandleResponse, this));
81 
82     mCallback = aCallback;
83     mContext  = aContext;
84 
85 exit:
86     FreeMessageOnError(message, error);
87     return error;
88 }
89 
HandleResponse(void * aContext,otMessage * aMessage,const otMessageInfo * aMessageInfo,Error aError)90 void AnycastLocator::HandleResponse(void *               aContext,
91                                     otMessage *          aMessage,
92                                     const otMessageInfo *aMessageInfo,
93                                     Error                aError)
94 {
95     static_cast<AnycastLocator *>(aContext)->HandleResponse(AsCoapMessagePtr(aMessage), AsCoreTypePtr(aMessageInfo),
96                                                             aError);
97 }
98 
HandleResponse(Coap::Message * aMessage,const Ip6::MessageInfo * aMessageInfo,Error aError)99 void AnycastLocator::HandleResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aError)
100 {
101     OT_UNUSED_VARIABLE(aMessageInfo);
102 
103     uint16_t            rloc16  = Mac::kShortAddrInvalid;
104     const Ip6::Address *address = nullptr;
105     Ip6::Address        meshLocalAddress;
106 
107     SuccessOrExit(aError);
108     OT_ASSERT(aMessage != nullptr);
109 
110     meshLocalAddress.SetPrefix(Get<Mle::Mle>().GetMeshLocalPrefix());
111     SuccessOrExit(Tlv::Find<ThreadMeshLocalEidTlv>(*aMessage, meshLocalAddress.GetIid()));
112     SuccessOrExit(Tlv::Find<ThreadRloc16Tlv>(*aMessage, rloc16));
113 
114 #if OPENTHREAD_FTD
115     Get<AddressResolver>().UpdateSnoopedCacheEntry(meshLocalAddress, rloc16, Get<Mac::Mac>().GetShortAddress());
116 #endif
117 
118     address = &meshLocalAddress;
119 
120 exit:
121     if (mCallback != nullptr)
122     {
123         Callback callback = mCallback;
124 
125         mCallback = nullptr;
126         callback(mContext, aError, address, rloc16);
127     }
128 }
129 
130 #if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_SEND_RESPONSE
131 
HandleAnycastLocate(void * aContext,otMessage * aMessage,const otMessageInfo * aMessageInfo)132 void AnycastLocator::HandleAnycastLocate(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
133 {
134     static_cast<AnycastLocator *>(aContext)->HandleAnycastLocate(AsCoapMessage(aMessage), AsCoreType(aMessageInfo));
135 }
136 
HandleAnycastLocate(const Coap::Message & aRequest,const Ip6::MessageInfo & aMessageInfo)137 void AnycastLocator::HandleAnycastLocate(const Coap::Message &aRequest, const Ip6::MessageInfo &aMessageInfo)
138 {
139     Coap::Message *message = nullptr;
140 
141     VerifyOrExit(aRequest.IsConfirmablePostRequest());
142 
143     message = Get<Tmf::Agent>().NewResponseMessage(aRequest);
144     VerifyOrExit(message != nullptr);
145 
146     SuccessOrExit(Tlv::Append<ThreadMeshLocalEidTlv>(*message, Get<Mle::Mle>().GetMeshLocal64().GetIid()));
147     SuccessOrExit(Tlv::Append<ThreadRloc16Tlv>(*message, Get<Mle::Mle>().GetRloc16()));
148 
149     SuccessOrExit(Get<Tmf::Agent>().SendMessage(*message, aMessageInfo));
150     message = nullptr;
151 
152 exit:
153     FreeMessage(message);
154 }
155 
156 #endif // OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_SEND_RESPONSE
157 
158 } // namespace ot
159 
160 #endif // OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
161