mirror of
https://github.com/espressif/openthread.git
synced 2026-08-17 07:59:51 +00:00
[meshcop] implement commissioning UDP proxy (#2926)
This commit is contained in:
@@ -641,6 +641,8 @@ typedef enum otMeshcopTlvType {
|
||||
OT_MESHCOP_TLV_VENDOR_SW_VERSION_TLV = 35, ///< meshcop Vendor SW Version TLV
|
||||
OT_MESHCOP_TLV_VENDOR_DATA_TLV = 36, ///< meshcop Vendor Data TLV
|
||||
OT_MESHCOP_TLV_VENDOR_STACK_VERSION_TLV = 37, ///< meshcop Vendor Stack Version TLV
|
||||
OT_MESHCOP_TLV_UDP_ENCAPSULATION_TLV = 48, ///< meshcop UDP encapsulation TLV
|
||||
OT_MESHCOP_TLV_IPV6_ADDRESS_TLV = 49, ///< meshcop IPv6 address TLV
|
||||
OT_MESHCOP_TLV_PENDINGTIMESTAMP = 51, ///< meshcop Pending Timestamp TLV
|
||||
OT_MESHCOP_TLV_DELAYTIMER = 52, ///< meshcop Delay Timer TLV
|
||||
OT_MESHCOP_TLV_CHANNELMASK = 53, ///< meshcop Channel Mask TLV
|
||||
|
||||
@@ -53,6 +53,26 @@ extern "C" {
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This callback allows OpenThread to provide specific handlers for certain UDP messages.
|
||||
*
|
||||
* @retval true The message is handled by this receiver and should not be further processed.
|
||||
* @retval false The message is not handled by this receiver.
|
||||
*
|
||||
*/
|
||||
typedef bool (*otUdpHandler)(void *aContext, const otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
/**
|
||||
* This structure represents a UDP receiver.
|
||||
*
|
||||
*/
|
||||
typedef struct otUdpReceiver
|
||||
{
|
||||
struct otUdpReceiver *mNext; ///< A pointer to the next UDP receiver (internal use only).
|
||||
otUdpHandler mHandler; ///< A function pointer to the receiver callback.
|
||||
void * mContext; ///< A pointer to application-specific context.
|
||||
} otUdpReceiver;
|
||||
|
||||
/**
|
||||
* This callback allows OpenThread to inform the application of a received UDP message.
|
||||
*
|
||||
|
||||
@@ -61,21 +61,46 @@ public:
|
||||
*
|
||||
* @param[in] aBorderAgent A reference to the border agent.
|
||||
* @param[in] aHeader A reference to the request header.
|
||||
* @param[in] aSeparate Whether this request should be responded separately.
|
||||
* @param[in] aPetition Whether this request is a petition.
|
||||
* @param[in] aSeparate Whether this original request expects separate response.
|
||||
*
|
||||
*/
|
||||
ForwardContext(BorderAgent &aBorderAgent, const Coap::Header &aHeader, bool aSeparate)
|
||||
ForwardContext(BorderAgent &aBorderAgent, const Coap::Header &aHeader, bool aPetition, bool aSeparate)
|
||||
: mBorderAgent(aBorderAgent)
|
||||
, mMessageId(aHeader.GetMessageId())
|
||||
, mPetition(aPetition)
|
||||
, mSeparate(aSeparate)
|
||||
, mType(aHeader.GetType() >> kTypeOffset)
|
||||
, mTokenLength(aHeader.GetTokenLength())
|
||||
, mType(aHeader.GetType() >> kTypeOffset)
|
||||
{
|
||||
memcpy(mToken, aHeader.GetToken(), mTokenLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns whether the request is a petition.
|
||||
*
|
||||
* @retval true This is a petition request.
|
||||
* @retval false This is not a petition request.
|
||||
*
|
||||
*/
|
||||
bool IsPetition(void) const { return mPetition; }
|
||||
|
||||
/**
|
||||
* This method returns the border agent sending this request.
|
||||
*
|
||||
* @returns A reference to the border agent sending this request.
|
||||
*
|
||||
*/
|
||||
BorderAgent &GetBorderAgent(void) { return mBorderAgent; }
|
||||
|
||||
/**
|
||||
* This method returns the message id of the original request.
|
||||
*
|
||||
* @returns A message id of the original request.
|
||||
*
|
||||
*/
|
||||
uint16_t GetMessageId(void) const { return mMessageId; }
|
||||
|
||||
/**
|
||||
* This method generate the response header according to the saved metadata.
|
||||
*
|
||||
@@ -105,11 +130,12 @@ private:
|
||||
};
|
||||
|
||||
BorderAgent &mBorderAgent;
|
||||
uint16_t mMessageId; ///< The CoAP Message ID
|
||||
bool mSeparate : 1;
|
||||
uint8_t mType : 2; ///< Type
|
||||
uint8_t mTokenLength : 4; ///< The CoAP Version, Type, and Token Length
|
||||
uint8_t mToken[OT_COAP_MAX_TOKEN_LENGTH];
|
||||
uint16_t mMessageId; ///< The CoAP Message ID of the original request.
|
||||
bool mPetition : 1; ///< Whether the forwarding request is leader petition.
|
||||
bool mSeparate : 1; ///< Whether the original request expects separate response.
|
||||
uint8_t mTokenLength : 4; ///< The CoAP Token Length of the original request.
|
||||
uint8_t mType : 2; ///< The CoAP Type of the original request.
|
||||
uint8_t mToken[OT_COAP_MAX_TOKEN_LENGTH]; ///< The CoAP Token of the original request.
|
||||
};
|
||||
|
||||
static Coap::Header::Code CoapCodeFromError(otError aError)
|
||||
@@ -166,29 +192,52 @@ void BorderAgent::HandleCoapResponse(void * aContext,
|
||||
ForwardContext &forwardContext = *static_cast<ForwardContext *>(aContext);
|
||||
BorderAgent & borderAgent = forwardContext.GetBorderAgent();
|
||||
ThreadNetif & netif = borderAgent.GetNetif();
|
||||
const Message * message = static_cast<const Message *>(aMessage);
|
||||
Coap::Header header;
|
||||
otError error;
|
||||
|
||||
OT_UNUSED_VARIABLE(aMessageInfo);
|
||||
otLogInfoMeshCoP(GetInstance(), "Got CoAP response[%s]", otThreadErrorToString(aResult));
|
||||
|
||||
if (aResult != OT_ERROR_NONE)
|
||||
SuccessOrExit(error = aResult);
|
||||
|
||||
if (forwardContext.IsPetition())
|
||||
{
|
||||
forwardContext.ToHeader(header, CoapCodeFromError(aResult));
|
||||
ExitNow(borderAgent.SendErrorMessage(header));
|
||||
}
|
||||
StateTlv stateTlv;
|
||||
|
||||
assert(aMessage != NULL);
|
||||
SuccessOrExit(error = Tlv::GetTlv(*message, Tlv::kState, sizeof(stateTlv), stateTlv));
|
||||
|
||||
if (stateTlv.GetState() == StateTlv::kAccept)
|
||||
{
|
||||
CommissionerSessionIdTlv sessionIdTlv;
|
||||
|
||||
SuccessOrExit(error =
|
||||
Tlv::GetTlv(*message, Tlv::kCommissionerSessionId, sizeof(sessionIdTlv), sessionIdTlv));
|
||||
|
||||
netif.GetMle().GetCommissionerAloc(borderAgent.mCommissionerAloc.GetAddress(),
|
||||
sessionIdTlv.GetCommissionerSessionId());
|
||||
netif.AddUnicastAddress(borderAgent.mCommissionerAloc);
|
||||
netif.GetIp6().GetUdp().AddReceiver(borderAgent.mProxyReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
forwardContext.ToHeader(header, static_cast<Coap::Header *>(aHeader)->GetCode());
|
||||
|
||||
if (static_cast<Message *>(aMessage)->GetLength() - static_cast<Message *>(aMessage)->GetOffset() > 0)
|
||||
if (message->GetLength() - message->GetOffset() > 0)
|
||||
{
|
||||
header.SetPayloadMarker();
|
||||
}
|
||||
|
||||
borderAgent.ForwardToCommissioner(header, *static_cast<Message *>(aMessage));
|
||||
SuccessOrExit(error = borderAgent.ForwardToCommissioner(header, *message));
|
||||
|
||||
exit:
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
otLogWarnMeshCoP(GetInstance(), "Commissioner request[%hu] failed: %s", forwardContext.GetMessageId(),
|
||||
otThreadErrorToString(aResult));
|
||||
forwardContext.ToHeader(header, CoapCodeFromError(error));
|
||||
borderAgent.SendErrorMessage(header);
|
||||
}
|
||||
|
||||
netif.GetInstance().GetHeap().Free(&forwardContext);
|
||||
}
|
||||
|
||||
@@ -200,7 +249,7 @@ void BorderAgent::HandleRequest<&BorderAgent::mCommissionerPetition>(void *
|
||||
{
|
||||
static_cast<BorderAgent *>(aContext)->ForwardToLeader(
|
||||
*static_cast<Coap::Header *>(aHeader), *static_cast<Message *>(aMessage),
|
||||
*static_cast<const Ip6::MessageInfo *>(aMessageInfo), OT_URI_PATH_LEADER_PETITION, true);
|
||||
*static_cast<const Ip6::MessageInfo *>(aMessageInfo), OT_URI_PATH_LEADER_PETITION, true, true);
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -236,6 +285,17 @@ void BorderAgent::HandleRequest<&BorderAgent::mRelayReceive>(void *
|
||||
*static_cast<Message *>(aMessage));
|
||||
}
|
||||
|
||||
template <>
|
||||
void BorderAgent::HandleRequest<&BorderAgent::mProxyTransmit>(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aMessageInfo);
|
||||
static_cast<BorderAgent *>(aContext)->HandleProxyTransmit(*static_cast<Coap::Header *>(aHeader),
|
||||
*static_cast<Message *>(aMessage));
|
||||
}
|
||||
|
||||
BorderAgent::BorderAgent(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mCommissionerPetition(OT_URI_PATH_COMMISSIONER_PETITION,
|
||||
@@ -252,11 +312,116 @@ BorderAgent::BorderAgent(Instance &aInstance)
|
||||
, mActiveSet(OT_URI_PATH_ACTIVE_SET, BorderAgent::HandleRequest<&BorderAgent::mActiveSet>, this)
|
||||
, mPendingGet(OT_URI_PATH_PENDING_GET, BorderAgent::HandleRequest<&BorderAgent::mPendingGet>, this)
|
||||
, mPendingSet(OT_URI_PATH_PENDING_SET, BorderAgent::HandleRequest<&BorderAgent::mPendingSet>, this)
|
||||
, mProxyTransmit(OT_URI_PATH_PROXY_TX, BorderAgent::HandleRequest<&BorderAgent::mProxyTransmit>, this)
|
||||
, mProxyReceiver(BorderAgent::HandleProxyReceive, this)
|
||||
, mTimer(aInstance, HandleTimeout, this)
|
||||
, mIsStarted(false)
|
||||
{
|
||||
}
|
||||
|
||||
void BorderAgent::HandleProxyTransmit(const Coap::Header &aHeader, const Message &aMessage)
|
||||
{
|
||||
Message * message = NULL;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
uint16_t offset;
|
||||
otError error;
|
||||
|
||||
OT_UNUSED_VARIABLE(aHeader);
|
||||
|
||||
{
|
||||
UdpEncapsulationTlv tlv;
|
||||
|
||||
SuccessOrExit(error = Tlv::GetOffset(aMessage, Tlv::kUdpEncapsulation, offset));
|
||||
aMessage.Read(offset, sizeof(tlv), &tlv);
|
||||
|
||||
VerifyOrExit((message = GetInstance().GetIp6().GetUdp().NewMessage(0)) != NULL, error = OT_ERROR_NO_BUFS);
|
||||
SuccessOrExit(error = message->SetLength(tlv.GetUdpLength()));
|
||||
aMessage.CopyTo(offset + sizeof(tlv), 0, tlv.GetUdpLength(), *message);
|
||||
|
||||
messageInfo.SetSockPort(tlv.GetSourcePort() != 0 ? tlv.GetSourcePort()
|
||||
: GetInstance().GetIp6().GetUdp().GetEphemeralPort());
|
||||
messageInfo.SetSockAddr(mCommissionerAloc.GetAddress());
|
||||
messageInfo.SetPeerPort(tlv.GetDestinationPort());
|
||||
}
|
||||
|
||||
{
|
||||
IPv6AddressTlv tlv;
|
||||
|
||||
SuccessOrExit(error = Tlv::Get(aMessage, Tlv::kIPv6Address, sizeof(tlv), tlv));
|
||||
messageInfo.SetPeerAddr(tlv.GetAddress());
|
||||
}
|
||||
|
||||
SuccessOrExit(error = GetInstance().GetIp6().GetUdp().SendDatagram(*message, messageInfo, Ip6::kProtoUdp));
|
||||
otLogInfoMeshCoP(GetInstance(), "Proxy transmit sent");
|
||||
|
||||
exit:
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
otLogWarnMeshCoP(GetInstance(), "Failed to send proxy stream: %s", otThreadErrorToString(error));
|
||||
|
||||
if (message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BorderAgent::HandleProxyReceive(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
Coap::Header header;
|
||||
otError error;
|
||||
Message * message = NULL;
|
||||
ThreadNetif &netif = GetNetif();
|
||||
|
||||
VerifyOrExit(aMessageInfo.GetSockAddr() == mCommissionerAloc.GetAddress(),
|
||||
error = OT_ERROR_DESTINATION_ADDRESS_FILTERED);
|
||||
|
||||
VerifyOrExit(aMessage.GetLength() > 0, error = OT_ERROR_NONE);
|
||||
|
||||
header.Init(OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_POST);
|
||||
header.AppendUriPathOptions(OT_URI_PATH_PROXY_RX);
|
||||
header.SetPayloadMarker();
|
||||
|
||||
VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoapSecure(), header)) != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
{
|
||||
UdpEncapsulationTlv tlv;
|
||||
uint16_t offset;
|
||||
uint16_t udpLength = aMessage.GetLength() - aMessage.GetOffset();
|
||||
|
||||
tlv.Init();
|
||||
tlv.SetSourcePort(aMessageInfo.GetPeerPort());
|
||||
tlv.SetDestinationPort(aMessageInfo.GetSockPort());
|
||||
tlv.SetUdpLength(udpLength);
|
||||
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
|
||||
|
||||
offset = message->GetLength();
|
||||
SuccessOrExit(error = message->SetLength(offset + udpLength));
|
||||
aMessage.CopyTo(aMessage.GetOffset(), offset, udpLength, *message);
|
||||
}
|
||||
|
||||
{
|
||||
IPv6AddressTlv tlv;
|
||||
|
||||
tlv.Init();
|
||||
tlv.SetAddress(aMessageInfo.GetPeerAddr());
|
||||
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = netif.GetCoapSecure().SendMessage(*message, netif.GetCoapSecure().GetPeerMessageInfo()));
|
||||
|
||||
otLogInfoMeshCoP(GetInstance(), "Sent to commissioner on %s", OT_URI_PATH_PROXY_RX);
|
||||
|
||||
exit:
|
||||
if (message != NULL && error != OT_ERROR_NONE)
|
||||
{
|
||||
otLogWarnMeshCoP(GetInstance(), "Failed notify commissioner on %s", OT_URI_PATH_PROXY_RX);
|
||||
message->Free();
|
||||
}
|
||||
|
||||
return error != OT_ERROR_DESTINATION_ADDRESS_FILTERED;
|
||||
}
|
||||
|
||||
void BorderAgent::HandleRelayReceive(const Coap::Header &aHeader, const Message &aMessage)
|
||||
{
|
||||
Coap::Header header;
|
||||
@@ -314,7 +479,7 @@ void BorderAgent::HandleKeepAlive(const Coap::Header & aHeader,
|
||||
{
|
||||
otError error;
|
||||
|
||||
error = ForwardToLeader(aHeader, aMessage, aMessageInfo, OT_URI_PATH_LEADER_KEEP_ALIVE, true);
|
||||
error = ForwardToLeader(aHeader, aMessage, aMessageInfo, OT_URI_PATH_LEADER_KEEP_ALIVE, false, true);
|
||||
|
||||
if (error == OT_ERROR_NONE)
|
||||
{
|
||||
@@ -375,6 +540,7 @@ otError BorderAgent::ForwardToLeader(const Coap::Header & aHeader,
|
||||
const Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const char * aPath,
|
||||
bool aPetition,
|
||||
bool aSeparate)
|
||||
{
|
||||
ThreadNetif & netif = GetNetif();
|
||||
@@ -393,7 +559,7 @@ otError BorderAgent::ForwardToLeader(const Coap::Header & aHeader,
|
||||
forwardContext = static_cast<ForwardContext *>(GetInstance().GetHeap().CAlloc(1, sizeof(ForwardContext)));
|
||||
VerifyOrExit(forwardContext != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
forwardContext = new (forwardContext) ForwardContext(*this, aHeader, aSeparate);
|
||||
forwardContext = new (forwardContext) ForwardContext(*this, aHeader, aPetition, aSeparate);
|
||||
|
||||
header.Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST);
|
||||
header.SetToken(Coap::Header::kDefaultTokenLength);
|
||||
@@ -465,7 +631,11 @@ void BorderAgent::HandleConnected(bool aConnected)
|
||||
}
|
||||
else
|
||||
{
|
||||
ThreadNetif &netif = GetNetif();
|
||||
|
||||
otLogInfoMeshCoP(GetInstance(), "Commissioner disconnected");
|
||||
netif.GetIp6().GetUdp().RemoveReceiver(mProxyReceiver);
|
||||
netif.RemoveUnicastAddress(mCommissionerAloc);
|
||||
mTimer.Start(kRestartDelay);
|
||||
}
|
||||
}
|
||||
@@ -503,6 +673,7 @@ otError BorderAgent::Start(void)
|
||||
coaps.AddResource(mCommissionerKeepAlive);
|
||||
coaps.AddResource(mCommissionerSet);
|
||||
coaps.AddResource(mCommissionerGet);
|
||||
coaps.AddResource(mProxyTransmit);
|
||||
coaps.AddResource(mRelayTransmit);
|
||||
|
||||
coap.AddResource(mRelayReceive);
|
||||
@@ -561,6 +732,7 @@ otError BorderAgent::Stop(void)
|
||||
coaps.RemoveResource(mActiveSet);
|
||||
coaps.RemoveResource(mPendingGet);
|
||||
coaps.RemoveResource(mPendingSet);
|
||||
coaps.RemoveResource(mProxyTransmit);
|
||||
coaps.RemoveResource(mRelayTransmit);
|
||||
|
||||
coap.RemoveResource(mRelayReceive);
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "coap/coap.hpp"
|
||||
#include "common/locator.hpp"
|
||||
#include "net/udp6.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
@@ -89,7 +90,7 @@ private:
|
||||
static_cast<BorderAgent *>(aContext)->ForwardToLeader(
|
||||
*static_cast<Coap::Header *>(aHeader), *static_cast<Message *>(aMessage),
|
||||
*static_cast<const Ip6::MessageInfo *>(aMessageInfo),
|
||||
(static_cast<BorderAgent *>(aContext)->*aResource).GetUriPath(), false);
|
||||
(static_cast<BorderAgent *>(aContext)->*aResource).GetUriPath(), false, false);
|
||||
}
|
||||
|
||||
static void HandleTimeout(Timer &aTimer);
|
||||
@@ -106,11 +107,19 @@ private:
|
||||
const Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const char * aPath,
|
||||
bool aPetition,
|
||||
bool aSeparate);
|
||||
otError ForwardToCommissioner(const Coap::Header &aHeader, const Message &aMessage);
|
||||
void HandleKeepAlive(const Coap::Header &aHeader, const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
void HandleRelayTransmit(const Coap::Header &aHeader, const Message &aMessage);
|
||||
void HandleRelayReceive(const Coap::Header &aHeader, const Message &aMessage);
|
||||
void HandleProxyTransmit(const Coap::Header &aHeader, const Message &aMessage);
|
||||
static bool HandleProxyReceive(void *aContext, const otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
return static_cast<BorderAgent *>(aContext)->HandleProxyReceive(
|
||||
*static_cast<const Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
}
|
||||
bool HandleProxyReceive(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -131,6 +140,10 @@ private:
|
||||
Coap::Resource mActiveSet;
|
||||
Coap::Resource mPendingGet;
|
||||
Coap::Resource mPendingSet;
|
||||
Coap::Resource mProxyTransmit;
|
||||
|
||||
Ip6::UdpReceiver mProxyReceiver; ///< The UDP receiver to handle proxy packets to Commissioner
|
||||
Ip6::NetifUnicastAddress mCommissionerAloc;
|
||||
|
||||
TimerMilli mTimer;
|
||||
bool mIsStarted;
|
||||
|
||||
@@ -105,21 +105,6 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
otError JoinerRouter::GetBorderAgentRloc(uint16_t &aRloc)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
BorderAgentLocatorTlv *borderAgentLocator;
|
||||
|
||||
borderAgentLocator = static_cast<BorderAgentLocatorTlv *>(
|
||||
GetNetif().GetNetworkDataLeader().GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));
|
||||
VerifyOrExit(borderAgentLocator != NULL, error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
aRloc = borderAgentLocator->GetBorderAgentLocator();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint16_t JoinerRouter::GetJoinerUdpPort(void)
|
||||
{
|
||||
uint16_t rval = OPENTHREAD_CONFIG_JOINER_UDP_PORT;
|
||||
@@ -167,7 +152,7 @@ void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a
|
||||
|
||||
otLogInfoMeshCoP(GetInstance(), "JoinerRouter::HandleUdpReceive");
|
||||
|
||||
SuccessOrExit(error = GetBorderAgentRloc(borderAgentRloc));
|
||||
SuccessOrExit(error = GetBorderAgentRloc(GetNetif(), borderAgentRloc));
|
||||
|
||||
header.Init(OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_POST);
|
||||
header.SetToken(Coap::Header::kDefaultTokenLength);
|
||||
|
||||
@@ -117,8 +117,6 @@ private:
|
||||
void SendDelayedJoinerEntrust(void);
|
||||
otError SendJoinerEntrust(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
otError GetBorderAgentRloc(uint16_t &aRloc);
|
||||
|
||||
Ip6::UdpSocket mSocket;
|
||||
Coap::Resource mRelayTransmit;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "crypto/sha256.hpp"
|
||||
#include "mac/mac_frame.hpp"
|
||||
#include "thread/thread_netif.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace MeshCoP {
|
||||
@@ -50,5 +51,20 @@ void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId)
|
||||
aJoinerId.SetLocal(true);
|
||||
}
|
||||
|
||||
otError GetBorderAgentRloc(ThreadNetif &aNetif, uint16_t &aRloc)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
BorderAgentLocatorTlv *borderAgentLocator;
|
||||
|
||||
borderAgentLocator = static_cast<BorderAgentLocatorTlv *>(
|
||||
aNetif.GetNetworkDataLeader().GetCommissioningDataSubTlv(Tlv::kBorderAgentLocator));
|
||||
VerifyOrExit(borderAgentLocator != NULL, error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
aRloc = borderAgentLocator->GetBorderAgentLocator();
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace MeshCoP
|
||||
} // namespace ot
|
||||
|
||||
@@ -67,6 +67,18 @@ inline Message *NewMeshCoPMessage(Coap::CoapBase &aCoap, const Coap::Header &aHe
|
||||
*/
|
||||
void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId);
|
||||
|
||||
/**
|
||||
* This function gets the border agent RLOC.
|
||||
*
|
||||
* @param[in] aNetif A reference to the thread interface.
|
||||
* @param[out] aRloc Border agent RLOC.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully got the Border Agent Rloc.
|
||||
* @retval OT_ERROR_NOT_FOUND Border agent is not available.
|
||||
*
|
||||
*/
|
||||
otError GetBorderAgentRloc(ThreadNetif &aNetIf, uint16_t &aRloc);
|
||||
|
||||
} // namespace MeshCoP
|
||||
|
||||
} // namespace ot
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "common/message.hpp"
|
||||
#include "common/tlvs.hpp"
|
||||
#include "meshcop/timestamp.hpp"
|
||||
#include "net/ip6_address.hpp"
|
||||
|
||||
using ot::Encoding::BigEndian::HostSwap16;
|
||||
using ot::Encoding::BigEndian::HostSwap32;
|
||||
@@ -95,6 +96,8 @@ public:
|
||||
kVendorSwVersion = OT_MESHCOP_TLV_VENDOR_SW_VERSION_TLV, ///< meshcop Vendor SW Version TLV
|
||||
kVendorData = OT_MESHCOP_TLV_VENDOR_DATA_TLV, ///< meshcop Vendor Data TLV
|
||||
kVendorStackVersion = OT_MESHCOP_TLV_VENDOR_STACK_VERSION_TLV, ///< meshcop Vendor Stack Version TLV
|
||||
kUdpEncapsulation = OT_MESHCOP_TLV_UDP_ENCAPSULATION_TLV, ///< meshcop UDP encapsulation TLV
|
||||
kIPv6Address = OT_MESHCOP_TLV_IPV6_ADDRESS_TLV, ///< meshcop IPv6 address TLV
|
||||
kPendingTimestamp = OT_MESHCOP_TLV_PENDINGTIMESTAMP, ///< Pending Timestamp TLV
|
||||
kDelayTimer = OT_MESHCOP_TLV_DELAYTIMER, ///< Delay Timer TLV
|
||||
kChannelMask = OT_MESHCOP_TLV_CHANNELMASK, ///< Channel Mask TLV
|
||||
@@ -178,6 +181,31 @@ public:
|
||||
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements extended MeshCoP TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class ExtendedTlv : public ot::ExtendedTlv
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method returns the Type value.
|
||||
*
|
||||
* @returns The Type value.
|
||||
*
|
||||
*/
|
||||
MeshCoP::Tlv::Type GetType(void) const { return static_cast<MeshCoP::Tlv::Type>(ot::ExtendedTlv::GetType()); }
|
||||
|
||||
/**
|
||||
* This method sets the Type value.
|
||||
*
|
||||
* @param[in] aType The Type value.
|
||||
*
|
||||
*/
|
||||
void SetType(MeshCoP::Tlv::Type aType) { ot::ExtendedTlv::SetType(static_cast<uint8_t>(aType)); }
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Channel TLV generation and parsing.
|
||||
*
|
||||
@@ -2175,6 +2203,124 @@ private:
|
||||
uint8_t mMinorMajor;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements IPv6 Address TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class IPv6AddressTlv : public Tlv
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
*/
|
||||
void Init(void)
|
||||
{
|
||||
SetType(kIPv6Address);
|
||||
SetLength(sizeof(mAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the IPv6 Address.
|
||||
*
|
||||
* @returns A reference to the IPv6 Address.
|
||||
*
|
||||
*/
|
||||
const Ip6::Address &GetAddress(void) const { return mAddress; }
|
||||
|
||||
/**
|
||||
* This method sets the IPv6 Address.
|
||||
*
|
||||
* @param[in] aAddress A reference to the IPv6 Address.
|
||||
*
|
||||
*/
|
||||
void SetAddress(const Ip6::Address &aAddress) { mAddress = aAddress; }
|
||||
|
||||
private:
|
||||
Ip6::Address mAddress;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements UDP Encapsulation TLV generation and parsing.
|
||||
*
|
||||
*/
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class UdpEncapsulationTlv : public ExtendedTlv
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the TLV.
|
||||
*
|
||||
*/
|
||||
void Init(void)
|
||||
{
|
||||
SetType(MeshCoP::Tlv::kUdpEncapsulation);
|
||||
SetLength(sizeof(*this) - sizeof(ExtendedTlv));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the TLV appears to be well-formed.
|
||||
*
|
||||
* @retval TRUE If the TLV appears to be well-formed.
|
||||
* @retval FALSE If the TLV does not appear to be well-formed.
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return GetLength() >= sizeof(*this) - sizeof(ExtendedTlv); }
|
||||
|
||||
/**
|
||||
* This method returns the source port.
|
||||
*
|
||||
* @returns The source port.
|
||||
*
|
||||
*/
|
||||
uint16_t GetSourcePort(void) const { return HostSwap16(mSourcePort); }
|
||||
|
||||
/**
|
||||
* This method updates the source port.
|
||||
*
|
||||
* @param[in] aSourcePort The source port.
|
||||
*
|
||||
*/
|
||||
void SetSourcePort(uint16_t aSourcePort) { mSourcePort = HostSwap16(aSourcePort); }
|
||||
|
||||
/**
|
||||
* This method returns the destination port.
|
||||
*
|
||||
* @returns The destination port.
|
||||
*
|
||||
*/
|
||||
uint16_t GetDestinationPort(void) const { return HostSwap16(mDestinationPort); }
|
||||
|
||||
/**
|
||||
* This method updates the destination port.
|
||||
*
|
||||
* @param[in] aDestinationPort The destination port.
|
||||
*
|
||||
*/
|
||||
void SetDestinationPort(uint16_t aDestinationPort) { mDestinationPort = HostSwap16(aDestinationPort); }
|
||||
|
||||
/**
|
||||
* This method returns the calculated UDP length.
|
||||
*
|
||||
* @returns The calculated UDP length.
|
||||
*
|
||||
*/
|
||||
uint16_t GetUdpLength(void) const { return GetLength() - sizeof(mSourcePort) - sizeof(mDestinationPort); }
|
||||
|
||||
/**
|
||||
* This method updates the UDP length.
|
||||
*
|
||||
* @param[in] aLength The length of UDP payload in bytes.
|
||||
*
|
||||
*/
|
||||
void SetUdpLength(uint16_t aLength) { SetLength(sizeof(mSourcePort) + sizeof(mDestinationPort) + aLength); }
|
||||
|
||||
private:
|
||||
uint16_t mSourcePort;
|
||||
uint16_t mDestinationPort;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This class implements Discovery Request TLV generation and parsing.
|
||||
*
|
||||
|
||||
@@ -135,10 +135,51 @@ exit:
|
||||
Udp::Udp(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mEphemeralPort(kDynamicPortMin)
|
||||
, mReceivers(NULL)
|
||||
, mSockets(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
otError Udp::AddReceiver(UdpReceiver &aReceiver)
|
||||
{
|
||||
for (UdpReceiver *cur = mReceivers; cur; cur = cur->GetNext())
|
||||
{
|
||||
if (cur == &aReceiver)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
aReceiver.SetNext(mReceivers);
|
||||
mReceivers = &aReceiver;
|
||||
|
||||
exit:
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError Udp::RemoveReceiver(UdpReceiver &aReceiver)
|
||||
{
|
||||
if (mReceivers == &aReceiver)
|
||||
{
|
||||
mReceivers = mReceivers->GetNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (UdpReceiver *handler = mReceivers; handler; handler = handler->GetNext())
|
||||
{
|
||||
if (handler->GetNext() == &aReceiver)
|
||||
{
|
||||
handler->SetNext(aReceiver.GetNext());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aReceiver.SetNext(NULL);
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError Udp::AddSocket(UdpSocket &aSocket)
|
||||
{
|
||||
for (UdpSocket *cur = mSockets; cur; cur = cur->GetNext())
|
||||
@@ -259,6 +300,11 @@ otError Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
|
||||
aMessageInfo.mPeerPort = udpHeader.GetSourcePort();
|
||||
aMessageInfo.mSockPort = udpHeader.GetDestinationPort();
|
||||
|
||||
for (UdpReceiver *receiver = mReceivers; receiver; receiver = receiver->GetNext())
|
||||
{
|
||||
VerifyOrExit(!receiver->HandleMessage(aMessage, aMessageInfo));
|
||||
}
|
||||
|
||||
HandlePayload(aMessage, aMessageInfo);
|
||||
|
||||
exit:
|
||||
|
||||
+56
-2
@@ -56,6 +56,39 @@ class Udp;
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements a UDP receiver.
|
||||
*
|
||||
*/
|
||||
class UdpReceiver : public otUdpReceiver
|
||||
{
|
||||
friend class Udp;
|
||||
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
* @param[in] aUdpHandler A pointer to the function to handle UDP message.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
UdpReceiver(otUdpHandler aHandler, void *aContext)
|
||||
{
|
||||
mNext = NULL;
|
||||
mHandler = aHandler;
|
||||
mContext = aContext;
|
||||
}
|
||||
|
||||
private:
|
||||
UdpReceiver *GetNext(void) { return static_cast<UdpReceiver *>(mNext); }
|
||||
void SetNext(UdpReceiver *aReceiver) { mNext = static_cast<otUdpReceiver *>(aReceiver); }
|
||||
|
||||
bool HandleMessage(Message &aMessage, const MessageInfo &aMessageInfo)
|
||||
{
|
||||
return mHandler(mContext, &aMessage, &aMessageInfo);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements a UDP/IPv6 socket.
|
||||
*
|
||||
@@ -178,6 +211,26 @@ public:
|
||||
*/
|
||||
explicit Udp(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* This method adds a UDP receiver.
|
||||
*
|
||||
* @param[in] aReceiver A reference to the UDP receiver.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully added the UDP receiver.
|
||||
*
|
||||
*/
|
||||
otError AddReceiver(UdpReceiver &aReceiver);
|
||||
|
||||
/**
|
||||
* This method removes a UDP receiver.
|
||||
*
|
||||
* @param[in] aReceiver A reference to the UDP receiver.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully removed the UDP receiver.
|
||||
*
|
||||
*/
|
||||
otError RemoveReceiver(UdpReceiver &aReceiver);
|
||||
|
||||
/**
|
||||
* This method adds a UDP socket.
|
||||
*
|
||||
@@ -283,8 +336,9 @@ private:
|
||||
kDynamicPortMin = 49152, ///< Service Name and Transport Protocol Port Number Registry
|
||||
kDynamicPortMax = 65535, ///< Service Name and Transport Protocol Port Number Registry
|
||||
};
|
||||
uint16_t mEphemeralPort;
|
||||
UdpSocket *mSockets;
|
||||
uint16_t mEphemeralPort;
|
||||
UdpReceiver *mReceivers;
|
||||
UdpSocket * mSockets;
|
||||
#if OPENTHREAD_ENABLE_UDP_PROXY
|
||||
void * mProxySenderContext;
|
||||
otUdpProxySender mProxySender;
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#include "common/logging.hpp"
|
||||
#include "common/owner-locator.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
#include "net/ip6.hpp"
|
||||
#include "net/tcp.hpp"
|
||||
#include "net/udp6.hpp"
|
||||
@@ -754,6 +755,10 @@ otError MeshForwarder::UpdateIp6RouteFtd(Ip6::Header &ip6Header)
|
||||
{
|
||||
mMeshDest = netif.GetMle().GetRloc16(netif.GetMle().GetLeaderId());
|
||||
}
|
||||
else if ((aloc16 >= Mle::kAloc16CommissionerStart) && (aloc16 <= Mle::kAloc16CommissionerEnd))
|
||||
{
|
||||
SuccessOrExit(error = MeshCoP::GetBorderAgentRloc(netif, mMeshDest));
|
||||
}
|
||||
|
||||
#if OPENTHREAD_ENABLE_DHCP6_SERVER || OPENTHREAD_ENABLE_DHCP6_CLIENT
|
||||
else if (aloc16 <= Mle::kAloc16DhcpAgentEnd)
|
||||
|
||||
@@ -981,17 +981,14 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Mle::GetLeaderAloc(Ip6::Address &aAddress) const
|
||||
otError Mle::GetAlocAddress(Ip6::Address &aAddress, uint16_t aAloc16) const
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = OT_ERROR_DETACHED);
|
||||
|
||||
memcpy(&aAddress, &mMeshLocal16.GetAddress(), 8);
|
||||
aAddress.mFields.m16[4] = HostSwap16(0x0000);
|
||||
aAddress.mFields.m16[5] = HostSwap16(0x00ff);
|
||||
aAddress.mFields.m16[6] = HostSwap16(0xfe00);
|
||||
aAddress.mFields.m16[7] = HostSwap16(kAloc16Leader);
|
||||
memcpy(&aAddress, &mMeshLocal16.GetAddress(), 14);
|
||||
aAddress.mFields.m16[7] = HostSwap16(aAloc16);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
|
||||
+32
-2
@@ -110,6 +110,7 @@ enum AlocAllocation
|
||||
kAloc16ServiceEnd = 0xfc2f,
|
||||
kAloc16CommissionerStart = 0xfc30,
|
||||
kAloc16CommissionerEnd = 0xfc37,
|
||||
kAloc16CommissionerMask = 0x0007,
|
||||
kAloc16NeighborDiscoveryAgentStart = 0xfc40,
|
||||
kAloc16NeighborDiscoveryAgentEnd = 0xfc4e,
|
||||
};
|
||||
@@ -855,7 +856,22 @@ public:
|
||||
* @retval OT_ERROR_DETACHED The Thread interface is not currently attached to a Thread Partition.
|
||||
*
|
||||
*/
|
||||
otError GetLeaderAloc(Ip6::Address &aAddress) const;
|
||||
otError GetLeaderAloc(Ip6::Address &aAddress) const { return GetAlocAddress(aAddress, kAloc16Leader); }
|
||||
|
||||
/**
|
||||
* This method computes the Commissioner's ALOC.
|
||||
*
|
||||
* @param[out] aAddress A reference to the Commissioner's ALOC.
|
||||
* @param[in] aSessionId Commissioner session id.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully retrieved the Commissioner's ALOC.
|
||||
* @retval OT_ERROR_DETACHED The Thread interface is not currently attached to a Thread Partition.
|
||||
*
|
||||
*/
|
||||
otError GetCommissionerAloc(Ip6::Address &aAddress, uint16_t aSessionId) const
|
||||
{
|
||||
return GetAlocAddress(aAddress, GetCommissionerAloc16FromId(aSessionId));
|
||||
}
|
||||
|
||||
#if OPENTHREAD_ENABLE_SERVICE
|
||||
/**
|
||||
@@ -950,7 +966,7 @@ public:
|
||||
/**
|
||||
* This method returns the Service Aloc corresponding to a Service ID.
|
||||
*
|
||||
* @param[in] aAloc16 The Servicer ID value.
|
||||
* @param[in] aServiceId The Service ID value.
|
||||
*
|
||||
* @returns The Service ALOC16 corresponding to given ID.
|
||||
*
|
||||
@@ -960,6 +976,19 @@ public:
|
||||
return static_cast<uint16_t>(aServiceId + kAloc16ServiceStart);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the Commissioner Aloc corresponding to a Commissioner Session ID.
|
||||
*
|
||||
* @param[in] aSessionId The Commissioner Session ID value.
|
||||
*
|
||||
* @returns The Commissioner ALOC16 corresponding to given ID.
|
||||
*
|
||||
*/
|
||||
static uint16_t GetCommissionerAloc16FromId(uint16_t aSessionId)
|
||||
{
|
||||
return static_cast<uint16_t>((aSessionId & kAloc16CommissionerMask) + kAloc16CommissionerStart);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the RLOC16 of a given Router ID.
|
||||
*
|
||||
@@ -1648,6 +1677,7 @@ private:
|
||||
bool IsBetterParent(uint16_t aRloc16, uint8_t aLinkQuality, uint8_t aLinkMargin, ConnectivityTlv &aConnectivityTlv);
|
||||
void ResetParentCandidate(void);
|
||||
|
||||
otError GetAlocAddress(Ip6::Address &aAddress, uint16_t aAloc16) const;
|
||||
#if OPENTHREAD_ENABLE_SERVICE
|
||||
/**
|
||||
* This method scans for network data from the leader and updates ip addresses assigned to this
|
||||
|
||||
@@ -148,6 +148,22 @@ namespace ot {
|
||||
*/
|
||||
#define OT_URI_PATH_ANNOUNCE_BEGIN "c/ab"
|
||||
|
||||
/**
|
||||
* @def OT_URI_PATH_PROXY_RX
|
||||
*
|
||||
* The URI Path for Proxy RX.
|
||||
*
|
||||
*/
|
||||
#define OT_URI_PATH_PROXY_RX "c/ur"
|
||||
|
||||
/**
|
||||
* @def OT_URI_PATH_PROXY_TX
|
||||
*
|
||||
* The URI Path for Proxy TX.
|
||||
*
|
||||
*/
|
||||
#define OT_URI_PATH_PROXY_TX "c/ut"
|
||||
|
||||
/**
|
||||
* @def OT_URI_PATH_RELAY_RX
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user