• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2018, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for the BorderAgent role.
32  */
33 
34 #ifndef BORDER_AGENT_HPP_
35 #define BORDER_AGENT_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
40 
41 #include <openthread/border_agent.h>
42 
43 #include "border_router/routing_manager.hpp"
44 #include "common/appender.hpp"
45 #include "common/as_core_type.hpp"
46 #include "common/heap_allocatable.hpp"
47 #include "common/linked_list.hpp"
48 #include "common/locator.hpp"
49 #include "common/non_copyable.hpp"
50 #include "common/notifier.hpp"
51 #include "common/owned_ptr.hpp"
52 #include "common/tasklet.hpp"
53 #include "meshcop/dataset.hpp"
54 #include "meshcop/secure_transport.hpp"
55 #include "net/dns_types.hpp"
56 #include "net/socket.hpp"
57 #include "net/udp6.hpp"
58 #include "thread/tmf.hpp"
59 #include "thread/uri_paths.hpp"
60 
61 namespace ot {
62 
63 namespace MeshCoP {
64 
65 #if !OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
66 #error "Border Agent feature requires `OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE`"
67 #endif
68 
69 #if !OPENTHREAD_CONFIG_UPTIME_ENABLE
70 #error "Border Agent feature requires `OPENTHREAD_CONFIG_UPTIME_ENABLE`"
71 #endif
72 
73 class BorderAgent : public InstanceLocator, private NonCopyable
74 {
75 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
76     friend class ot::BorderRouter::RoutingManager;
77 #endif
78     friend class ot::Notifier;
79     friend class Tmf::Agent;
80 
81     class CoapDtlsSession;
82 
83 public:
84     typedef otBorderAgentId          Id;          ///< Border Agent ID.
85     typedef otBorderAgentCounters    Counters;    ///< Border Agent Counters.
86     typedef otBorderAgentSessionInfo SessionInfo; ///< A session info.
87 
88     /**
89      * Represents an iterator for secure sessions.
90      */
91     class SessionIterator : public otBorderAgentSessionIterator
92     {
93     public:
94         /**
95          * Initializes the `SessionIterator`.
96          *
97          * @param[in] aInstance  The OpenThread instance.
98          */
99         void Init(Instance &aInstance);
100 
101         /**
102          * Retrieves the next session information.
103          *
104          * @param[out] aSessionInfo     A `SessionInfo` to populate.
105          *
106          * @retval kErrorNone        Successfully retrieved the next session. @p aSessionInfo is updated.
107          * @retval kErrorNotFound    No more sessions are available. The end of the list has been reached.
108          */
109         Error GetNextSessionInfo(SessionInfo &aSessionInfo);
110 
111     private:
GetSession(void) const112         CoapDtlsSession *GetSession(void) const { return static_cast<CoapDtlsSession *>(mPtr); }
SetSession(CoapDtlsSession * aSession)113         void             SetSession(CoapDtlsSession *aSession) { mPtr = aSession; }
GetInitTime(void) const114         uint64_t         GetInitTime(void) const { return mData; }
SetInitTime(uint64_t aInitTime)115         void             SetInitTime(uint64_t aInitTime) { mData = aInitTime; }
116     };
117 
118     /**
119      * Initializes the `BorderAgent` object.
120      *
121      * @param[in]  aInstance     A reference to the OpenThread instance.
122      */
123     explicit BorderAgent(Instance &aInstance);
124 
125 #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
126     /**
127      * Gets the randomly generated Border Agent ID.
128      *
129      * The ID is saved in persistent storage and survives reboots. The typical use case of the ID is to
130      * be published in the MeshCoP mDNS service as the `id` TXT value for the client to identify this
131      * Border Router/Agent device.
132      *
133      * @param[out] aId  Reference to return the Border Agent ID.
134      *
135      * @retval kErrorNone  If successfully retrieved the Border Agent ID.
136      * @retval ...         If failed to retrieve the Border Agent ID.
137      */
138     Error GetId(Id &aId);
139 
140     /**
141      * Sets the Border Agent ID.
142      *
143      * The Border Agent ID will be saved in persistent storage and survive reboots. It's required
144      * to set the ID only once after factory reset. If the ID has never been set by calling this
145      * method, a random ID will be generated and returned when `GetId()` is called.
146      *
147      * @param[out] aId  specifies the Border Agent ID.
148      *
149      * @retval kErrorNone  If successfully set the Border Agent ID.
150      * @retval ...         If failed to set the Border Agent ID.
151      */
152     Error SetId(const Id &aId);
153 #endif
154 
155     /**
156      * Gets the UDP port of this service.
157      *
158      * @returns  UDP port number.
159      */
160     uint16_t GetUdpPort(void) const;
161 
162     /**
163      * Indicates whether the Border Agent service is running.
164      *
165      * @retval TRUE  Border Agent service is running.
166      * @retval FALSE Border Agent service is not running.
167      */
IsRunning(void) const168     bool IsRunning(void) const { return mIsRunning; }
169 
170     typedef otBorderAgentMeshCoPServiceChangedCallback MeshCoPServiceChangedCallback;
171 
172     /**
173      * Sets the callback function used by the Border Agent to notify any changes on the MeshCoP service TXT values.
174      *
175      * The callback is invoked when the state of MeshCoP service TXT values changes. For example, it is
176      * invoked when the network name or the extended PAN ID changes and pass the updated encoded TXT data to the
177      * application layer.
178      *
179      * This callback is invoked once right after this API is called to provide initial states of the MeshCoP
180      * service to the application.
181      *
182      * @param[in] aCallback  The callback to invoke when there are any changes of the MeshCoP service.
183      * @param[in] aContext   A pointer to application-specific context.
184      */
185     void SetMeshCoPServiceChangedCallback(MeshCoPServiceChangedCallback aCallback, void *aContext);
186 
187     typedef otBorderAgentMeshCoPServiceTxtData MeshCoPServiceTxtData;
188 
189     /**
190      * Gets the MeshCoP service TXT data.
191      *
192      * @param[out] aTxtData   A reference to a MeshCoP Service TXT data struct to get the data.
193      *
194      * @retval kErrorNone     If successfully retrieved the Border Agent MeshCoP Service TXT data.
195      * @retval kErrorNoBufs   If the buffer in @p aTxtData doesn't have enough size.
196      */
197     Error GetMeshCoPServiceTxtData(MeshCoPServiceTxtData &aTxtData) const;
198 
199 #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
200     /**
201      * Manages the ephemeral key use by Border Agent.
202      */
203     class EphemeralKeyManager : public InstanceLocator, private NonCopyable
204     {
205         friend class BorderAgent;
206 
207     public:
208         static constexpr uint16_t kMinKeyLength   = OT_BORDER_AGENT_MIN_EPHEMERAL_KEY_LENGTH;      ///< Min key len.
209         static constexpr uint16_t kMaxKeyLength   = OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_LENGTH;      ///< Max key len.
210         static constexpr uint32_t kDefaultTimeout = OT_BORDER_AGENT_DEFAULT_EPHEMERAL_KEY_TIMEOUT; //< Default timeout.
211         static constexpr uint32_t kMaxTimeout     = OT_BORDER_AGENT_MAX_EPHEMERAL_KEY_TIMEOUT;     ///< Max timeout.
212 
213         typedef otBorderAgentEphemeralKeyCallback CallbackHandler; ///< Callback function pointer.
214 
215         /**
216          * Represents the state of the `EphemeralKeyManager`.
217          */
218         enum State : uint8_t
219         {
220             kStateDisabled  = OT_BORDER_AGENT_STATE_DISABLED,  ///< Ephemeral key feature is disabled.
221             kStateStopped   = OT_BORDER_AGENT_STATE_STOPPED,   ///< Enabled, but the key is not set and started.
222             kStateStarted   = OT_BORDER_AGENT_STATE_STARTED,   ///< Key is set and listening to accept connection.
223             kStateConnected = OT_BORDER_AGENT_STATE_CONNECTED, ///< Session connected, not full commissioner.
224             kStateAccepted  = OT_BORDER_AGENT_STATE_ACCEPTED,  ///< Session connected and accepted as full commissioner.
225         };
226 
227         /**
228          * Enables/disables Ephemeral Key Manager.
229          *
230          * If this method is called to disable, while an an ephemeral key is in use, the ephemeral key use will
231          * be stopped (as if `Stop()` is called).
232          *
233          * @param[in] aEnabled  Whether to enable or disable.
234          */
235         void SetEnabled(bool aEnabled);
236 
237         /**
238          * Starts using an ephemeral key for a given timeout duration.
239          *
240          * An ephemeral key can only be set when `GetState()` is `kStateStopped`. Otherwise, `kErrorInvalidState` is
241          * returned. This means that setting the ephemeral key again while a previously set key is still in use will
242          * fail. Callers can stop the previous key by calling `Stop()` before starting with a new key.
243          *
244          * The given @p aKeyString is used directly as the ephemeral PSK (excluding the trailing null `\0` character).
245          * Its length must be between `kMinKeyLength` and `kMaxKeyLength`, inclusive.
246          *
247          * The ephemeral key can be used only once by an external commissioner candidate to establish a secure session.
248          * After the commissioner candidate disconnects, the use of the ephemeral key is stopped. If the timeout
249          * expires, the use of the ephemeral key is also stopped, and any established session using the key is
250          * immediately disconnected.
251          *
252          * @param[in] aKeyString   The ephemeral key.
253          * @param[in] aTimeout     The timeout duration, in milliseconds, to use the ephemeral key.
254          *                         If zero, the default `kDefaultTimeout` value is used. If the timeout value is
255          *                         larger than `kMaxTimeout`, the maximum value is used instead.
256          * @param[in] aUdpPort     The UDP port to use with the ephemeral key. If the UDP port is zero, an ephemeral
257          *                         port is used. `GetUdpPort()` returns the current UDP port being used.
258          *
259          * @retval kErrorNone           Successfully started using the ephemeral key.
260          * @retval kErrorInvalidState   A previously set ephemeral key is still in use or feature is disabled.
261          * @retval kErrorInvalidArgs    The given @p aKeyString is not valid.
262          * @retval kErrorFailed         Failed to start (e.g., it could not bind to the given UDP port).
263          */
264         Error Start(const char *aKeyString, uint32_t aTimeout, uint16_t aUdpPort);
265 
266         /**
267          * Stops the ephemeral key use and disconnects any established secure session using it.
268          *
269          * If there is no ephemeral key in use, calling this method has no effect.
270          */
271         void Stop(void);
272 
273         /**
274          * Gets the state of ephemeral key use and its session.
275          *
276          * @returns The `EmpheralKeyManager` state.
277          */
GetState(void) const278         State GetState(void) const { return mState; }
279 
280         /**
281          * Gets the UDP port used by ephemeral key DTLS secure transport.
282          *
283          * @returns  UDP port number.
284          */
GetUdpPort(void) const285         uint16_t GetUdpPort(void) const { return mDtlsTransport.GetUdpPort(); }
286 
287         /**
288          * Sets the callback.
289          *
290          * @param[in] aCallback   The callback function pointer.
291          * @param[in] aContext    The context associated and used with callback handler.
292          */
SetCallback(CallbackHandler aCallback,void * aContext)293         void SetCallback(CallbackHandler aCallback, void *aContext) { mCallback.Set(aCallback, aContext); }
294 
295         /**
296          * Converts a given `State` to human-readable string.
297          *
298          * @param[in] aState  The state to convert.
299          *
300          * @returns The string corresponding to @p aState.
301          */
302         static const char *StateToString(State aState);
303 
304     private:
305         static constexpr uint16_t kMaxConnectionAttempts = 10;
306 
307         static_assert(kMaxKeyLength <= Dtls::Transport::kPskMaxLength, "Max e-key len is larger than max PSK len");
308 
309         enum StopReason : uint8_t
310         {
311             kReasonLocalDisconnect,
312             kReasonPeerDisconnect,
313             kReasonSessionError,
314             kReasonMaxFailedAttempts,
315             kReasonTimeout,
316             kReasonUnknown,
317         };
318 
319         explicit EphemeralKeyManager(Instance &aInstance);
320 
321         void SetState(State aState);
322         void Stop(StopReason aReason);
323         void HandleTimer(void);
324         void HandleTask(void);
OwnsSession(CoapDtlsSession & aSession) const325         bool OwnsSession(CoapDtlsSession &aSession) const { return mCoapDtlsSession == &aSession; }
326         void HandleSessionConnected(void);
327         void HandleSessionDisconnected(SecureSession::ConnectEvent aEvent);
328         void HandleCommissionerPetitionAccepted(void);
329 
330         // Session or Transport callbacks
331         static SecureSession *HandleAcceptSession(void *aContext, const Ip6::MessageInfo &aMessageInfo);
332         CoapDtlsSession      *HandleAcceptSession(void);
333         static void           HandleRemoveSession(void *aContext, SecureSession &aSession);
334         void                  HandleRemoveSession(SecureSession &aSession);
335         static void           HandleTransportClosed(void *aContext);
336         void                  HandleTransportClosed(void);
337 
338 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
339         static const char *StopReasonToString(StopReason aReason);
340 #endif
341 
342         using TimeoutTimer = TimerMilliIn<EphemeralKeyManager, &EphemeralKeyManager::HandleTimer>;
343         using CallbackTask = TaskletIn<EphemeralKeyManager, &EphemeralKeyManager::HandleTask>;
344 
345         State                     mState;
346         Dtls::Transport           mDtlsTransport;
347         CoapDtlsSession          *mCoapDtlsSession;
348         TimeoutTimer              mTimer;
349         CallbackTask              mCallbackTask;
350         Callback<CallbackHandler> mCallback;
351     };
352 
353     /**
354      * Gets the `EphemeralKeyManager` instance.
355      *
356      * @returns A reference to the `EphemeralKeyManager`.
357      */
GetEphemeralKeyManager(void)358     EphemeralKeyManager &GetEphemeralKeyManager(void) { return mEphemeralKeyManager; }
359 
360 #endif // OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
361 
362     /**
363      * Gets the set of border agent counters.
364      *
365      * @returns The border agent counters.
366      */
GetCounters(void)367     const Counters &GetCounters(void) { return mCounters; }
368 
369 private:
370     static constexpr uint16_t kUdpPort          = OPENTHREAD_CONFIG_BORDER_AGENT_UDP_PORT;
371     static constexpr uint32_t kKeepAliveTimeout = 50 * 1000; // Timeout to reject a commissioner (in msec)
372 
373     class CoapDtlsSession : public Coap::SecureSession, public Heap::Allocatable<CoapDtlsSession>
374     {
375         friend Heap::Allocatable<CoapDtlsSession>;
376 
377     public:
378         Error    ForwardToCommissioner(Coap::Message &aForwardMessage, const Message &aMessage);
379         void     Cleanup(void);
IsActiveCommissioner(void) const380         bool     IsActiveCommissioner(void) const { return mIsActiveCommissioner; }
GetAllocationTime(void) const381         uint64_t GetAllocationTime(void) const { return mAllocationTime; }
382 
383     private:
384         class ForwardContext : public ot::LinkedListEntry<ForwardContext>,
385                                public Heap::Allocatable<ForwardContext>,
386                                private ot::NonCopyable
387         {
388             friend class Heap::Allocatable<ForwardContext>;
389 
390         public:
391             Error ToHeader(Coap::Message &aMessage, uint8_t aCode) const;
392 
393             CoapDtlsSession &mSession;
394             ForwardContext  *mNext;
395             uint16_t         mMessageId;
396             bool             mPetition : 1;
397             bool             mSeparate : 1;
398             uint8_t          mTokenLength : 4;
399             uint8_t          mType : 2;
400             uint8_t          mToken[Coap::Message::kMaxTokenLength];
401 
402         private:
403             ForwardContext(CoapDtlsSession &aSession, const Coap::Message &aMessage, bool aPetition, bool aSeparate);
404         };
405 
406         CoapDtlsSession(Instance &aInstance, Dtls::Transport &aDtlsTransport);
407 
408         void  HandleTmfCommissionerKeepAlive(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
409         void  HandleTmfRelayTx(Coap::Message &aMessage);
410         void  HandleTmfProxyTx(Coap::Message &aMessage);
411         void  HandleTmfDatasetGet(Coap::Message &aMessage, Uri aUri);
412         Error ForwardToLeader(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Uri aUri);
413         void  SendErrorMessage(const ForwardContext &aForwardContext, Error aError);
414         void  SendErrorMessage(const Coap::Message &aRequest, bool aSeparate, Error aError);
415 
416         static void HandleConnected(ConnectEvent aEvent, void *aContext);
417         void        HandleConnected(ConnectEvent aEvent);
418         static void HandleCoapResponse(void                *aContext,
419                                        otMessage           *aMessage,
420                                        const otMessageInfo *aMessageInfo,
421                                        otError              aResult);
422         void HandleCoapResponse(const ForwardContext &aForwardContext, const Coap::Message *aResponse, Error aResult);
423         static bool HandleUdpReceive(void *aContext, const otMessage *aMessage, const otMessageInfo *aMessageInfo);
424         bool        HandleUdpReceive(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
425         static bool HandleResource(CoapBase               &aCoapBase,
426                                    const char             *aUriPath,
427                                    Coap::Message          &aMessage,
428                                    const Ip6::MessageInfo &aMessageInfo);
429         bool        HandleResource(const char *aUriPath, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
430         static void HandleTimer(Timer &aTimer);
431         void        HandleTimer(void);
432 
433         bool                       mIsActiveCommissioner;
434         LinkedList<ForwardContext> mForwardContexts;
435         TimerMilliContext          mTimer;
436         Ip6::Udp::Receiver         mUdpReceiver;
437         Ip6::Netif::UnicastAddress mCommissionerAloc;
438         uint64_t                   mAllocationTime;
439     };
440 
441     class MeshCoPTxtEncoder : public InstanceLocator
442     {
443     public:
MeshCoPTxtEncoder(Instance & aInstance,MeshCoPServiceTxtData & aTxtData)444         MeshCoPTxtEncoder(Instance &aInstance, MeshCoPServiceTxtData &aTxtData)
445             : InstanceLocator(aInstance)
446             , mTxtData(aTxtData)
447             , mAppender(mTxtData.mData, sizeof(mTxtData.mData))
448         {
449         }
450 
451         enum : uint8_t
452         {
453             kConnectionModeDisabled = 0,
454             kConnectionModePskc     = 1,
455             kConnectionModePskd     = 2,
456             kConnectionModeVendor   = 3,
457             kConnectionModeX509     = 4,
458         };
459 
460         enum : uint8_t
461         {
462             kThreadIfStatusNotInitialized = 0,
463             kThreadIfStatusInitialized    = 1,
464             kThreadIfStatusActive         = 2,
465         };
466 
467         enum : uint8_t
468         {
469             kThreadRoleDisabledOrDetached = 0,
470             kThreadRoleChild              = 1,
471             kThreadRoleRouter             = 2,
472             kThreadRoleLeader             = 3,
473         };
474 
475         enum : uint8_t
476         {
477             kAvailabilityInfrequent = 0,
478             kAvailabilityHigh       = 1,
479         };
480 
481         struct StateBitmap
482         {
483             uint32_t mConnectionMode : 3;
484             uint32_t mThreadIfStatus : 2;
485             uint32_t mAvailability : 2;
486             uint32_t mBbrIsActive : 1;
487             uint32_t mBbrIsPrimary : 1;
488             uint32_t mThreadRole : 2;
489             uint32_t mEpskcSupported : 1;
490 
StateBitmapot::MeshCoP::BorderAgent::MeshCoPTxtEncoder::StateBitmap491             StateBitmap(void)
492                 : mConnectionMode(0)
493                 , mThreadIfStatus(0)
494                 , mAvailability(0)
495                 , mBbrIsActive(0)
496                 , mBbrIsPrimary(0)
497                 , mThreadRole(kThreadRoleDisabledOrDetached)
498                 , mEpskcSupported(0)
499             {
500             }
501 
ToUint32ot::MeshCoP::BorderAgent::MeshCoPTxtEncoder::StateBitmap502             uint32_t ToUint32(void) const
503             {
504                 uint32_t bitmap = 0;
505 
506                 bitmap |= mConnectionMode << 0;
507                 bitmap |= mThreadIfStatus << 3;
508                 bitmap |= mAvailability << 5;
509                 bitmap |= mBbrIsActive << 7;
510                 bitmap |= mBbrIsPrimary << 8;
511                 bitmap |= mThreadRole << 9;
512                 bitmap |= mEpskcSupported << 11;
513                 return bitmap;
514             }
515         };
516 
517         Error EncodeTxtData(void);
518 
519     private:
520         Error AppendTxtEntry(const char *aKey, const void *aValue, uint16_t aValueLength);
521 
AppendTxtEntry(const char * aKey,const ObjectType & aObject)522         template <typename ObjectType> Error AppendTxtEntry(const char *aKey, const ObjectType &aObject)
523         {
524             static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
525             static_assert(!TypeTraits::IsSame<ObjectType, NameData>::kValue, "ObjectType must not be `NameData`");
526 
527             return AppendTxtEntry(aKey, &aObject, sizeof(ObjectType));
528         }
529 
530 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
531         Error AppendBbrTxtEntry(StateBitmap aState);
532 #endif
533 #if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
534         Error AppendOmrTxtEntry(void);
535 #endif
536 
537         StateBitmap GetStateBitmap(void);
538 
539         MeshCoPServiceTxtData &mTxtData;
540         Appender               mAppender;
541     };
542 
543     void Start(void);
544     void Stop(void);
545     void HandleNotifierEvents(Events aEvents);
546 
547     template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
548 
549     static SecureSession *HandleAcceptSession(void *aContext, const Ip6::MessageInfo &aMessageInfo);
550     CoapDtlsSession      *HandleAcceptSession(void);
551     static void           HandleRemoveSession(void *aContext, SecureSession &aSession);
552     void                  HandleRemoveSession(SecureSession &aSession);
553     CoapDtlsSession      *FindActiveCommissionerSession(void);
554 
555     void HandleSessionConnected(CoapDtlsSession &aSession);
556     void HandleSessionDisconnected(CoapDtlsSession &aSession, CoapDtlsSession::ConnectEvent aEvent);
557     void HandleCommissionerPetitionAccepted(CoapDtlsSession &aSession);
558 
559     static Coap::Message::Code CoapCodeFromError(Error aError);
560 
561     void PostNotifyMeshCoPServiceChangedTask(void);
562     void NotifyMeshCoPServiceChanged(void);
563 
564     using NotifyMeshCoPServiceChangedTask = TaskletIn<BorderAgent, &BorderAgent::NotifyMeshCoPServiceChanged>;
565 
566     bool            mIsRunning;
567     Dtls::Transport mDtlsTransport;
568 #if OPENTHREAD_CONFIG_BORDER_AGENT_ID_ENABLE
569     Id   mId;
570     bool mIdInitialized;
571 #endif
572     Callback<MeshCoPServiceChangedCallback> mMeshCoPServiceChangedCallback;
573     NotifyMeshCoPServiceChangedTask         mNotifyMeshCoPServiceChangedTask;
574 #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
575     EphemeralKeyManager mEphemeralKeyManager;
576 #endif
577     Counters mCounters;
578 };
579 
580 DeclareTmfHandler(BorderAgent, kUriRelayRx);
581 
582 } // namespace MeshCoP
583 
584 DefineCoreType(otBorderAgentId, MeshCoP::BorderAgent::Id);
585 DefineCoreType(otBorderAgentSessionIterator, MeshCoP::BorderAgent::SessionIterator);
586 
587 #if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
588 DefineMapEnum(otBorderAgentEphemeralKeyState, MeshCoP::BorderAgent::EphemeralKeyManager::State);
589 #endif
590 
591 } // namespace ot
592 
593 #endif // OPENTHREAD_CONFIG_BORDER_AGENT_ENABLE
594 
595 #endif // BORDER_AGENT_HPP_
596