mirror of
https://github.com/espressif/openthread.git
synced 2026-07-29 15:17:47 +00:00
[meshcop] move border agent into core (#2771)
This commit moves the border agent service into OpenThread core. Border agent, commissioner, and joiner shares a single secure CoAP agent, because they will not be active at the same time. Other changes include: - Replaced TMF proxy with UDP proxy, which is more generalized. - Changed OT_ERROR_NONE string to "OK". - Defined a special interface id -1 to differentiate packets received by host side.
This commit is contained in:
+49
-16
@@ -659,36 +659,68 @@ AC_MSG_RESULT(${enable_builtin_mbedtls})
|
||||
AM_CONDITIONAL([OPENTHREAD_ENABLE_BUILTIN_MBEDTLS], [test "${enable_builtin_mbedtls}" = "yes"])
|
||||
|
||||
#
|
||||
# Thread TMF Proxy
|
||||
# Thread UDP Proxy
|
||||
#
|
||||
|
||||
AC_MSG_CHECKING([whether to enable TMF proxy])
|
||||
AC_ARG_ENABLE(tmf_proxy,
|
||||
[AS_HELP_STRING([--enable-tmf-proxy],[Enable TMF proxy support @<:@default=no@:>@.])],
|
||||
AC_MSG_CHECKING([whether to enable UDP proxy])
|
||||
AC_ARG_ENABLE(udp_proxy,
|
||||
[AS_HELP_STRING([--enable-udp-proxy], [Enable UDP proxy support @<:@default=no@:>@.])],
|
||||
[
|
||||
case "${enableval}" in
|
||||
|
||||
no|yes)
|
||||
enable_tmf_proxy=${enableval}
|
||||
enable_udp_proxy=${enableval}
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_ERROR([Invalid value ${enable_tmf_proxy} for --enable-tmf-proxy])
|
||||
AC_MSG_ERROR([Invalid value ${enable_udp_proxy} for --enable-udp-proxy])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[enable_tmf_proxy=no])
|
||||
[enable_udp_proxy=no])
|
||||
|
||||
if test "$enable_tmf_proxy" = "yes"; then
|
||||
OPENTHREAD_ENABLE_TMF_PROXY=1
|
||||
if test "$enable_udp_proxy" = "yes"; then
|
||||
OPENTHREAD_ENABLE_UDP_PROXY=1
|
||||
else
|
||||
OPENTHREAD_ENABLE_TMF_PROXY=0
|
||||
OPENTHREAD_ENABLE_UDP_PROXY=0
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT(${enable_tmf_proxy})
|
||||
AC_SUBST(OPENTHREAD_ENABLE_TMF_PROXY)
|
||||
AM_CONDITIONAL([OPENTHREAD_ENABLE_TMF_PROXY], [test "${enable_tmf_proxy}" = "yes"])
|
||||
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_TMF_PROXY],[${OPENTHREAD_ENABLE_TMF_PROXY}],[Define to 1 to enable the TMF proxy feature.])
|
||||
AC_MSG_RESULT(${enable_udp_proxy})
|
||||
AC_SUBST(OPENTHREAD_ENABLE_UDP_PROXY)
|
||||
AM_CONDITIONAL([OPENTHREAD_ENABLE_UDP_PROXY], [test "${enable_udp_proxy}" = "yes"])
|
||||
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_UDP_PROXY], [${OPENTHREAD_ENABLE_UDP_PROXY}], [Define to 1 to enable the UDP proxy feature.])
|
||||
|
||||
#
|
||||
# Thread Border Agent
|
||||
#
|
||||
|
||||
AC_MSG_CHECKING([whether to enable border agent])
|
||||
AC_ARG_ENABLE(border_agent,
|
||||
[AS_HELP_STRING([--enable-border-agent], [Enable border agent support @<:@default=no@:>@.])],
|
||||
[
|
||||
case "${enableval}" in
|
||||
|
||||
no|yes)
|
||||
enable_border_agent=${enableval}
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_ERROR([Invalid value ${enable_border_agent} for --enable-border-agent])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[enable_border_agent=no])
|
||||
|
||||
if test "${enable_border_agent}" = "yes"; then
|
||||
OPENTHREAD_ENABLE_BORDER_AGENT=1
|
||||
else
|
||||
OPENTHREAD_ENABLE_BORDER_AGENT=0
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT(${enable_border_agent})
|
||||
AC_SUBST(OPENTHREAD_ENABLE_BORDER_AGENT)
|
||||
AM_CONDITIONAL([OPENTHREAD_ENABLE_BORDER_AGENT], [test "${enable_border_agent}" = "yes"])
|
||||
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_BORDER_AGENT], [${OPENTHREAD_ENABLE_BORDER_AGENT}], [Define to 1 to enable the border agent feature.])
|
||||
|
||||
#
|
||||
# Thread Network Diagnostic for MTD
|
||||
@@ -786,7 +818,7 @@ AC_SUBST(OPENTHREAD_ENABLE_JOINER)
|
||||
AM_CONDITIONAL([OPENTHREAD_ENABLE_JOINER], [test "${enable_joiner}" = "yes"])
|
||||
AC_DEFINE_UNQUOTED([OPENTHREAD_ENABLE_JOINER],[${OPENTHREAD_ENABLE_JOINER}],[Define to 1 to enable the joiner role.])
|
||||
|
||||
if test "${enable_commissioner}" = "yes" -o "${enable_joiner}" = "yes"; then
|
||||
if test "${enable_commissioner}" = "yes" -o "${enable_joiner}" = "yes" -o "${enable_border_agent}" = "yes"; then
|
||||
enable_dtls="yes"
|
||||
OPENTHREAD_ENABLE_DTLS=1
|
||||
else
|
||||
@@ -1703,7 +1735,7 @@ AC_MSG_NOTICE([
|
||||
OpenThread Multiple Instances support : ${enable_multiple_instances}
|
||||
OpenThread MTD Network Diagnostic support : ${enable_mtd_network_diagnostic}
|
||||
OpenThread builtin mbedtls support : ${enable_builtin_mbedtls}
|
||||
OpenThread TMF Proxy support : ${enable_tmf_proxy}
|
||||
OpenThread UDP Proxy support : ${enable_udp_proxy}
|
||||
OpenThread Commissioner support : ${enable_commissioner}
|
||||
OpenThread Joiner support : ${enable_joiner}
|
||||
OpenThread DTLS support : ${enable_dtls}
|
||||
@@ -1720,6 +1752,7 @@ AC_MSG_NOTICE([
|
||||
OpenThread DNS Client support : ${enable_dns_client}
|
||||
OpenThread Application CoAP support : ${enable_application_coap}
|
||||
OpenThread Raw Link-Layer support : ${enable_raw_link_api}
|
||||
OpenThread Border Agent support : ${enable_border_agent}
|
||||
OpenThread Border Router support : ${enable_border_router}
|
||||
OpenThread Service support : ${enable_service}
|
||||
OpenThread examples : ${OPENTHREAD_EXAMPLES}
|
||||
|
||||
@@ -46,6 +46,7 @@ BuildJobs ?= 10
|
||||
|
||||
configure_OPTIONS = \
|
||||
--enable-application-coap \
|
||||
--enable-border-agent \
|
||||
--enable-border-router \
|
||||
--enable-cert-log \
|
||||
--enable-child-supervision \
|
||||
@@ -63,7 +64,7 @@ configure_OPTIONS = \
|
||||
--enable-ncp-app=all \
|
||||
--enable-raw-link-api \
|
||||
--enable-service \
|
||||
--enable-tmf-proxy \
|
||||
--enable-udp-proxy \
|
||||
--with-examples=posix \
|
||||
--with-ncp-bus=uart \
|
||||
$(NULL)
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
ifeq ($(BORDER_AGENT),1)
|
||||
configure_OPTIONS += --enable-border-agent
|
||||
endif
|
||||
|
||||
ifeq ($(BORDER_ROUTER),1)
|
||||
configure_OPTIONS += --enable-border-router
|
||||
endif
|
||||
@@ -95,8 +99,8 @@ ifeq ($(SERVICE),1)
|
||||
configure_OPTIONS += --enable-service
|
||||
endif
|
||||
|
||||
ifeq ($(TMF_PROXY),1)
|
||||
configure_OPTIONS += --enable-tmf-proxy
|
||||
ifeq ($(UDP_PROXY),1)
|
||||
configure_OPTIONS += --enable-udp-proxy
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG_UART),1)
|
||||
|
||||
@@ -3440,7 +3440,7 @@ otThreadErrorToString(
|
||||
switch (aError)
|
||||
{
|
||||
case OT_ERROR_NONE:
|
||||
retval = "None";
|
||||
retval = "OK";
|
||||
break;
|
||||
|
||||
case OT_ERROR_FAILED:
|
||||
|
||||
@@ -78,7 +78,6 @@ openthread_headers = \
|
||||
tasklet.h \
|
||||
thread.h \
|
||||
thread_ftd.h \
|
||||
tmf_proxy.h \
|
||||
types.h \
|
||||
udp.h \
|
||||
$(NULL)
|
||||
|
||||
@@ -59,6 +59,8 @@ extern "C" {
|
||||
|
||||
#define OT_DEFAULT_COAP_PORT 5683 ///< Default CoAP port, as specified in RFC 7252
|
||||
|
||||
#define OT_COAP_MAX_TOKEN_LENGTH 8 ///< Max token length as specified (RFC 7252).
|
||||
|
||||
/**
|
||||
* CoAP Type values.
|
||||
*
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file includes the OpenThread API for TMF Proxy feature.
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_TMF_PROXY_H_
|
||||
#define OPENTHREAD_TMF_PROXY_H_
|
||||
|
||||
#include <openthread/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup api-tmf-proxy
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions for TMF proxy feature.
|
||||
*
|
||||
* The functions in this module are available when tmf-proxy feature (`OPENTHREAD_ENABLE_TMF_PROXY`) is enabled.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This function pointer is called when a TMF packet for host is received.
|
||||
*
|
||||
* @param[in] aMessage A pointer to the CoAP Message.
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
*
|
||||
*/
|
||||
typedef void (*otTmfProxyStreamHandler)(otMessage *aMessage, uint16_t aLocator, uint16_t aPort, void *aContext);
|
||||
|
||||
/**
|
||||
* Start the TMF proxy.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aHandler A pointer to a function called to deliver TMF packet to host.
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started the TMF proxy.
|
||||
* @retval OT_ERROR_ALREADY Border agent proxy has been started before.
|
||||
*
|
||||
*/
|
||||
otError otTmfProxyStart(otInstance *aInstance, otTmfProxyStreamHandler aHandler, void *aContext);
|
||||
|
||||
/**
|
||||
* Stop the TMF proxy.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully stopped the TMF proxy.
|
||||
* @retval OT_ERROR_ALREADY Border agent proxy is already stopped.
|
||||
*
|
||||
*/
|
||||
otError otTmfProxyStop(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* Send packet through TMF proxy.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aMessage A pointer to the CoAP Message.
|
||||
* @param[in] aLocator Rloc of destination.
|
||||
* @param[in] aPort Port of destination.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully send the message.
|
||||
* @retval OT_ERROR_INVALID_STATE Border agent proxy is not started.
|
||||
*
|
||||
* @warning No matter the call success or fail, the message is freed.
|
||||
*
|
||||
*/
|
||||
otError otTmfProxySend(otInstance *aInstance, otMessage *aMessage, uint16_t aLocator, uint16_t aPort);
|
||||
|
||||
/**
|
||||
* Get the TMF proxy status (enabled/disabled)
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
*
|
||||
* @returns The TMF proxy status (true if enabled, false otherwise).
|
||||
*/
|
||||
bool otTmfProxyIsEnabled(otInstance *aInstance);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_TMF_PROXY_H_
|
||||
@@ -1117,7 +1117,8 @@ typedef struct otNetifMulticastAddress
|
||||
*
|
||||
*/
|
||||
typedef enum otNetifInterfaceId {
|
||||
OT_NETIF_INTERFACE_ID_THREAD = 1, ///< The Thread Network interface ID.
|
||||
OT_NETIF_INTERFACE_ID_HOST = -1, ///< The interface ID telling packets received by host side interfaces.
|
||||
OT_NETIF_INTERFACE_ID_THREAD = 1, ///< The Thread Network interface ID.
|
||||
} otNetifInterfaceId;
|
||||
|
||||
/**
|
||||
|
||||
@@ -173,6 +173,67 @@ otError otUdpConnect(otUdpSocket *aSocket, otSockAddr *aSockName);
|
||||
*/
|
||||
otError otUdpSend(otUdpSocket *aSocket, otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup api-udp-proxy
|
||||
*
|
||||
* @brief
|
||||
* This module includes functions for UDP proxy feature.
|
||||
*
|
||||
* The functions in this module are available when udp-proxy feature (`OPENTHREAD_ENABLE_UDP_PROXY`) is enabled.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This function pointer delivers the UDP packet to host and host should send the packet through its own network stack.
|
||||
*
|
||||
* @param[in] aMessage A pointer to the UDP Message.
|
||||
* @param[in] aPeerPort The destination UDP port.
|
||||
* @param[in] aPeerAddr A pointer to the destination IPv6 address.
|
||||
* @param[in] aSockPort The source UDP port.
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
*
|
||||
*/
|
||||
typedef void (*otUdpProxySender)(otMessage * aMessage,
|
||||
uint16_t aPeerPort,
|
||||
otIp6Address *aPeerAddr,
|
||||
uint16_t aSockPort,
|
||||
void * aContext);
|
||||
|
||||
/**
|
||||
* Set UDP proxy callback to deliever UDP packets to host.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aSender A pointer to a function called to deliver UDP packet to host.
|
||||
* @param[in] aContext A pointer to application-specific context.
|
||||
*
|
||||
*/
|
||||
void otUdpProxySetSender(otInstance *aInstance, otUdpProxySender aSender, void *aContext);
|
||||
|
||||
/**
|
||||
* Handle a UDP packet received from host.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aMessage A pointer to the UDP Message.
|
||||
* @param[in] aPeerPort The source UDP port.
|
||||
* @param[in] aPeerAddr A pointer to the source address.
|
||||
* @param[in] aSockPort The destination UDP port.
|
||||
*
|
||||
* @warning No matter the call success or fail, the message is freed.
|
||||
*
|
||||
*/
|
||||
void otUdpProxyReceive(otInstance * aInstance,
|
||||
otMessage * aMessage,
|
||||
uint16_t aPeerPort,
|
||||
const otIp6Address *aPeerAddr,
|
||||
uint16_t aSockPort);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -119,7 +119,6 @@ SOURCES_COMMON = \
|
||||
api/tasklet_api.cpp \
|
||||
api/thread_api.cpp \
|
||||
api/thread_ftd_api.cpp \
|
||||
api/tmf_proxy_api.cpp \
|
||||
api/udp_api.cpp \
|
||||
coap/coap.cpp \
|
||||
coap/coap_header.cpp \
|
||||
@@ -146,6 +145,7 @@ SOURCES_COMMON = \
|
||||
mac/mac_filter.cpp \
|
||||
mac/mac_frame.cpp \
|
||||
meshcop/announce_begin_client.cpp \
|
||||
meshcop/border_agent.cpp \
|
||||
meshcop/commissioner.cpp \
|
||||
meshcop/dataset.cpp \
|
||||
meshcop/dataset_local.cpp \
|
||||
@@ -195,7 +195,6 @@ SOURCES_COMMON = \
|
||||
thread/router_table.cpp \
|
||||
thread/src_match_controller.cpp \
|
||||
thread/thread_netif.cpp \
|
||||
thread/tmf_proxy.cpp \
|
||||
thread/time_sync_service.cpp \
|
||||
thread/topology.cpp \
|
||||
utils/channel_manager.cpp \
|
||||
@@ -268,6 +267,7 @@ HEADERS_COMMON = \
|
||||
mac/mac_filter.hpp \
|
||||
mac/mac_frame.hpp \
|
||||
meshcop/announce_begin_client.hpp \
|
||||
meshcop/border_agent.hpp \
|
||||
meshcop/commissioner.hpp \
|
||||
meshcop/dataset.hpp \
|
||||
meshcop/dataset_local.hpp \
|
||||
@@ -327,7 +327,6 @@ HEADERS_COMMON = \
|
||||
thread/thread_netif.hpp \
|
||||
thread/thread_tlvs.hpp \
|
||||
thread/thread_uri_paths.hpp \
|
||||
thread/tmf_proxy.hpp \
|
||||
thread/time_sync_service.hpp \
|
||||
thread/topology.hpp \
|
||||
utils/channel_manager.hpp \
|
||||
|
||||
@@ -46,11 +46,13 @@ otError otCommissionerStart(otInstance *aInstance)
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_ENABLE_COMMISSIONER
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
error = instance.GetThreadNetif().GetCommissioner().Start();
|
||||
#else
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
#if OPENTHREAD_ENABLE_BORDER_AGENT
|
||||
SuccessOrExit(error = instance.GetBorderAgent().Stop());
|
||||
#endif
|
||||
|
||||
SuccessOrExit(error = instance.GetThreadNetif().GetCommissioner().Start());
|
||||
exit:
|
||||
#endif
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -61,11 +63,13 @@ otError otCommissionerStop(otInstance *aInstance)
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_ENABLE_COMMISSIONER
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
error = instance.GetThreadNetif().GetCommissioner().Stop();
|
||||
#else
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
SuccessOrExit(error = instance.GetThreadNetif().GetCommissioner().Stop());
|
||||
#if OPENTHREAD_ENABLE_BORDER_AGENT
|
||||
SuccessOrExit(error = instance.GetBorderAgent().Start());
|
||||
#endif
|
||||
|
||||
exit:
|
||||
#endif
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the OpenThread TMF proxy API.
|
||||
*/
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <openthread/tmf_proxy.h>
|
||||
|
||||
#include "common/instance.hpp"
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_ENABLE_TMF_PROXY
|
||||
|
||||
using namespace ot;
|
||||
|
||||
otError otTmfProxyStart(otInstance *aInstance, otTmfProxyStreamHandler aTmfProxyCallback, void *aContext)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.GetThreadNetif().GetTmfProxy().Start(aTmfProxyCallback, aContext);
|
||||
}
|
||||
|
||||
otError otTmfProxyStop(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.GetThreadNetif().GetTmfProxy().Stop();
|
||||
}
|
||||
|
||||
otError otTmfProxySend(otInstance *aInstance, otMessage *aMessage, uint16_t aLocator, uint16_t aPort)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.GetThreadNetif().GetTmfProxy().Send(*static_cast<ot::Message *>(aMessage), aLocator, aPort);
|
||||
}
|
||||
|
||||
bool otTmfProxyIsEnabled(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
|
||||
return instance.GetThreadNetif().GetTmfProxy().IsEnabled();
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_FTD && OPENTHREAD_ENABLE_TMF_PROXY
|
||||
@@ -102,3 +102,36 @@ otError otUdpSend(otUdpSocket *aSocket, otMessage *aMessage, const otMessageInfo
|
||||
Ip6::UdpSocket &socket = *static_cast<Ip6::UdpSocket *>(aSocket);
|
||||
return socket.SendTo(*static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
}
|
||||
|
||||
#if OPENTHREAD_ENABLE_UDP_PROXY
|
||||
void otUdpProxySetSender(otInstance *aInstance, otUdpProxySender aSender, void *aContext)
|
||||
{
|
||||
Instance &instance = *static_cast<Instance *>(aInstance);
|
||||
Ip6::Ip6 &ip6 = instance.Get<Ip6::Ip6>();
|
||||
|
||||
ip6.GetUdp().SetProxySender(aSender, aContext);
|
||||
}
|
||||
|
||||
void otUdpProxyReceive(otInstance * aInstance,
|
||||
otMessage * aMessage,
|
||||
uint16_t aPeerPort,
|
||||
const otIp6Address *aPeerAddr,
|
||||
uint16_t aSockPort)
|
||||
{
|
||||
Ip6::MessageInfo messageInfo;
|
||||
Instance & instance = *static_cast<Instance *>(aInstance);
|
||||
Ip6::Ip6 & ip6 = instance.Get<Ip6::Ip6>();
|
||||
|
||||
assert(aMessage != NULL && aPeerAddr != NULL);
|
||||
|
||||
messageInfo.SetSockAddr(instance.GetThreadNetif().GetMle().GetMeshLocal16());
|
||||
messageInfo.SetSockPort(aSockPort);
|
||||
messageInfo.SetPeerAddr(*static_cast<const ot::Ip6::Address *>(aPeerAddr));
|
||||
messageInfo.SetPeerPort(aPeerPort);
|
||||
messageInfo.SetInterfaceId(OT_NETIF_INTERFACE_ID_HOST);
|
||||
|
||||
ip6.GetUdp().HandlePayload(*static_cast<ot::Message *>(aMessage), messageInfo);
|
||||
|
||||
static_cast<ot::Message *>(aMessage)->Free();
|
||||
}
|
||||
#endif // OPENTHREAD_ENABLE_UDP_PROXY
|
||||
|
||||
@@ -229,6 +229,14 @@ public:
|
||||
*/
|
||||
Resource *GetNext(void) const { return static_cast<Resource *>(mNext); };
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the Uri-Path.
|
||||
*
|
||||
* @returns A Pointer to the Uri-Path.
|
||||
*
|
||||
*/
|
||||
const char *GetUriPath(void) const { return mUriPath; };
|
||||
|
||||
private:
|
||||
void HandleRequest(Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
|
||||
{
|
||||
@@ -584,7 +592,7 @@ public:
|
||||
* @retval OT_ERROR_INVALID_ARGS The @p aRequestHeader header is not of confirmable type.
|
||||
*
|
||||
*/
|
||||
otError SendAck(Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo)
|
||||
otError SendAck(const Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
return SendEmptyMessage(OT_COAP_TYPE_ACKNOWLEDGMENT, aRequestHeader, aMessageInfo);
|
||||
};
|
||||
|
||||
@@ -83,7 +83,7 @@ otError Header::FromMessage(const Message &aMessage, uint16_t aMetadataSize)
|
||||
VerifyOrExit(GetVersion() == 1);
|
||||
|
||||
tokenLength = GetTokenLength();
|
||||
VerifyOrExit(tokenLength <= kMaxTokenLength && (mHeaderLength + tokenLength) <= length);
|
||||
VerifyOrExit(tokenLength <= OT_COAP_MAX_TOKEN_LENGTH && (mHeaderLength + tokenLength) <= length);
|
||||
aMessage.Read(offset, tokenLength, mHeader.mBytes + mHeaderLength);
|
||||
mHeaderLength += tokenLength;
|
||||
offset += tokenLength;
|
||||
@@ -416,9 +416,9 @@ exit:
|
||||
|
||||
void Header::SetToken(uint8_t aTokenLength)
|
||||
{
|
||||
uint8_t token[kMaxTokenLength] = {0};
|
||||
uint8_t token[OT_COAP_MAX_TOKEN_LENGTH] = {0};
|
||||
|
||||
assert(aTokenLength <= kMaxTokenLength);
|
||||
assert(aTokenLength <= sizeof(token));
|
||||
|
||||
Random::FillBuffer(token, aTokenLength);
|
||||
|
||||
|
||||
@@ -480,7 +480,6 @@ private:
|
||||
kTokenLengthMask = 0x0f, ///< Token Length mask as specified (RFC 7252).
|
||||
kTokenLengthOffset = 0, ///< Token Length offset as specified (RFC 7252).
|
||||
kTokenOffset = 4, ///< Token offset as specified (RFC 7252).
|
||||
kMaxTokenLength = 8, ///< Max token length as specified (RFC 7252).
|
||||
|
||||
kMaxOptionHeaderSize = 5, ///< Maximum size of an Option header
|
||||
|
||||
|
||||
@@ -62,6 +62,8 @@ otError CoapSecure::Start(uint16_t aPort, TransportCallback aCallback, void *aCo
|
||||
otError error = OT_ERROR_NONE;
|
||||
mTransportCallback = aCallback;
|
||||
mTransportContext = aContext;
|
||||
mConnectedCallback = NULL;
|
||||
mConnectedContext = NULL;
|
||||
|
||||
// Passing mTransportCallback means that we do not want to use socket
|
||||
// to transmit/receive messages, so do not open it in that case.
|
||||
@@ -73,6 +75,12 @@ otError CoapSecure::Start(uint16_t aPort, TransportCallback aCallback, void *aCo
|
||||
return error;
|
||||
}
|
||||
|
||||
void CoapSecure::SetConnectedCallback(ConnectedCallback aCallback, void *aContext)
|
||||
{
|
||||
mConnectedCallback = aCallback;
|
||||
mConnectedContext = aContext;
|
||||
}
|
||||
|
||||
otError CoapSecure::Stop(void)
|
||||
{
|
||||
if (IsConnectionActive())
|
||||
|
||||
@@ -86,6 +86,15 @@ public:
|
||||
*/
|
||||
otError Start(uint16_t aPort, TransportCallback aCallback = NULL, void *aContext = NULL);
|
||||
|
||||
/**
|
||||
* This method sets connected callback of this secure CoAP agent.
|
||||
*
|
||||
* @param[in] aCallback A pointer to a function to get called when connection state changes.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
void SetConnectedCallback(ConnectedCallback aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* This method stops the secure CoAP agent.
|
||||
*
|
||||
@@ -201,6 +210,14 @@ public:
|
||||
*/
|
||||
virtual void Receive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This method returns the DTLS session's peer address.
|
||||
*
|
||||
* @return DTLS session's message info.
|
||||
*
|
||||
*/
|
||||
const Ip6::MessageInfo &GetPeerMessageInfo(void) const { return mPeerAddress; }
|
||||
|
||||
private:
|
||||
virtual otError Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
|
||||
@@ -64,6 +64,9 @@ Instance::Instance(void)
|
||||
, mSettings(*this)
|
||||
, mIp6(*this)
|
||||
, mThreadNetif(*this)
|
||||
#if OPENTHREAD_ENABLE_BORDER_AGENT
|
||||
, mBorderAgent(*this)
|
||||
#endif
|
||||
#if OPENTHREAD_ENABLE_APPLICATION_COAP
|
||||
, mApplicationCoap(*this)
|
||||
#endif
|
||||
@@ -422,6 +425,13 @@ template <> Utils::ChannelManager &Instance::Get(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_ENABLE_BORDER_AGENT
|
||||
template <> MeshCoP::BorderAgent &Instance::Get(void)
|
||||
{
|
||||
return mBorderAgent;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_ENABLE_ANNOUNCE_SENDER
|
||||
template <> AnnounceSender &Instance::Get(void)
|
||||
{
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#endif
|
||||
#include "common/notifier.hpp"
|
||||
#include "common/settings.hpp"
|
||||
#include "meshcop/border_agent.hpp"
|
||||
#include "net/ip6.hpp"
|
||||
#include "thread/announce_sender.hpp"
|
||||
#include "thread/link_quality.hpp"
|
||||
@@ -364,6 +365,10 @@ public:
|
||||
*
|
||||
*/
|
||||
MessagePool &GetMessagePool(void) { return mMessagePool; }
|
||||
|
||||
#if OPENTHREAD_ENABLE_BORDER_AGENT
|
||||
MeshCoP::BorderAgent &GetBorderAgent(void) { return mBorderAgent; }
|
||||
#endif
|
||||
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
|
||||
/**
|
||||
@@ -419,6 +424,9 @@ private:
|
||||
|
||||
Ip6::Ip6 mIp6;
|
||||
ThreadNetif mThreadNetif;
|
||||
#if OPENTHREAD_ENABLE_BORDER_AGENT
|
||||
MeshCoP::BorderAgent mBorderAgent;
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_ENABLE_APPLICATION_COAP
|
||||
Coap::ApplicationCoap mApplicationCoap;
|
||||
|
||||
@@ -180,7 +180,7 @@ const char *otThreadErrorToString(otError aError)
|
||||
switch (aError)
|
||||
{
|
||||
case OT_ERROR_NONE:
|
||||
retval = "None";
|
||||
retval = "OK";
|
||||
break;
|
||||
|
||||
case OT_ERROR_FAILED:
|
||||
|
||||
@@ -0,0 +1,556 @@
|
||||
/*
|
||||
* Copyright (c) 2018, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the BorderAgent service.
|
||||
*/
|
||||
|
||||
#define WPP_NAME "border_agent.tmh"
|
||||
|
||||
#include "border_agent.hpp"
|
||||
|
||||
#include <openthread/types.h>
|
||||
|
||||
#include "coap/coap_header.hpp"
|
||||
#include "common/instance.hpp"
|
||||
#include "common/logging.hpp"
|
||||
#include "common/new.hpp"
|
||||
#include "common/owner-locator.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
#include "meshcop/meshcop_tlvs.hpp"
|
||||
#include "thread/thread_netif.hpp"
|
||||
#include "thread/thread_tlvs.hpp"
|
||||
#include "thread/thread_uri_paths.hpp"
|
||||
|
||||
#if OPENTHREAD_ENABLE_BORDER_AGENT
|
||||
|
||||
namespace ot {
|
||||
namespace MeshCoP {
|
||||
|
||||
class ForwardContext
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes a forward context.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
*/
|
||||
ForwardContext(BorderAgent &aBorderAgent, const Coap::Header &aHeader, bool aSeparate)
|
||||
: mBorderAgent(aBorderAgent)
|
||||
, mMessageId(aHeader.GetMessageId())
|
||||
, mSeparate(aSeparate)
|
||||
, mType(aHeader.GetType() >> kTypeOffset)
|
||||
, mTokenLength(aHeader.GetTokenLength())
|
||||
{
|
||||
memcpy(mToken, aHeader.GetToken(), mTokenLength);
|
||||
}
|
||||
|
||||
BorderAgent &GetBorderAgent(void) { return mBorderAgent; }
|
||||
|
||||
/**
|
||||
* This method generate the response header according to the saved metadata.
|
||||
*
|
||||
* @param[out] aHeader A refernce to the response header.
|
||||
* @param[in] aCode The response code to fill in the response header.
|
||||
*
|
||||
*/
|
||||
void ToHeader(Coap::Header &aHeader, Coap::Header::Code aCode)
|
||||
{
|
||||
if (mType == (OT_COAP_TYPE_NON_CONFIRMABLE >> kTypeOffset) || mSeparate)
|
||||
{
|
||||
aHeader.Init(OT_COAP_TYPE_NON_CONFIRMABLE, aCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
aHeader.Init(OT_COAP_TYPE_ACKNOWLEDGMENT, aCode);
|
||||
}
|
||||
|
||||
aHeader.SetMessageId(mSeparate ? 0 : mMessageId);
|
||||
aHeader.SetToken(mToken, mTokenLength);
|
||||
}
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kTypeOffset = 4, ///< The type offset in the first byte of coap header
|
||||
};
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
static Coap::Header::Code CoapCodeFromError(otError aError)
|
||||
{
|
||||
switch (aError)
|
||||
{
|
||||
case OT_ERROR_NONE:
|
||||
return OT_COAP_CODE_CHANGED;
|
||||
|
||||
case OT_ERROR_PARSE:
|
||||
return OT_COAP_CODE_BAD_REQUEST;
|
||||
|
||||
default:
|
||||
return OT_COAP_CODE_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void BorderAgent::SendErrorMessage(const Coap::Header &aHeader)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message * message = NULL;
|
||||
ThreadNetif &netif = GetNetif();
|
||||
|
||||
VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoapSecure(), aHeader)) != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
SuccessOrExit(error = netif.GetCoapSecure().SendMessage(*message, netif.GetCoapSecure().GetPeerMessageInfo()));
|
||||
|
||||
exit:
|
||||
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
if (message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
|
||||
otLogWarnMeshCoP(GetInstance(), "Failed to send CoAP message: %s", otThreadErrorToString(error));
|
||||
}
|
||||
}
|
||||
|
||||
void BorderAgent::HandleCoapResponse(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
otError aResult)
|
||||
{
|
||||
ForwardContext &forwardContext = *static_cast<ForwardContext *>(aContext);
|
||||
BorderAgent & borderAgent = forwardContext.GetBorderAgent();
|
||||
ThreadNetif & netif = borderAgent.GetNetif();
|
||||
Coap::Header header;
|
||||
|
||||
OT_UNUSED_VARIABLE(aMessageInfo);
|
||||
otLogInfoMeshCoP(GetInstance(), "Got CoAP response[%s]", otThreadErrorToString(aResult));
|
||||
|
||||
if (aResult != OT_ERROR_NONE)
|
||||
{
|
||||
forwardContext.ToHeader(header, CoapCodeFromError(aResult));
|
||||
ExitNow(borderAgent.SendErrorMessage(header));
|
||||
}
|
||||
|
||||
assert(aMessage != NULL);
|
||||
|
||||
forwardContext.ToHeader(header, static_cast<Coap::Header *>(aHeader)->GetCode());
|
||||
|
||||
if (static_cast<Message *>(aMessage)->GetLength() - static_cast<Message *>(aMessage)->GetOffset() > 0)
|
||||
{
|
||||
header.SetPayloadMarker();
|
||||
}
|
||||
|
||||
borderAgent.ForwardToCommissioner(header, *static_cast<Message *>(aMessage));
|
||||
|
||||
exit:
|
||||
netif.GetInstance().GetHeap().Free(&forwardContext);
|
||||
}
|
||||
|
||||
template <>
|
||||
void BorderAgent::HandleRequest<&BorderAgent::mCommissionerPetition>(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
template <>
|
||||
void BorderAgent::HandleRequest<&BorderAgent::mCommissionerKeepAlive>(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
static_cast<BorderAgent *>(aContext)->ForwardToLeader(
|
||||
*static_cast<Coap::Header *>(aHeader), *static_cast<Message *>(aMessage),
|
||||
*static_cast<const Ip6::MessageInfo *>(aMessageInfo), OT_URI_PATH_LEADER_KEEP_ALIVE, true);
|
||||
}
|
||||
|
||||
template <>
|
||||
void BorderAgent::HandleRequest<&BorderAgent::mRelayTransmit>(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aMessageInfo);
|
||||
static_cast<BorderAgent *>(aContext)->HandleRelayTransmit(*static_cast<Coap::Header *>(aHeader),
|
||||
*static_cast<Message *>(aMessage));
|
||||
}
|
||||
|
||||
template <>
|
||||
void BorderAgent::HandleRequest<&BorderAgent::mRelayReceive>(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aMessageInfo);
|
||||
static_cast<BorderAgent *>(aContext)->HandleRelayReceive(*static_cast<Coap::Header *>(aHeader),
|
||||
*static_cast<Message *>(aMessage));
|
||||
}
|
||||
|
||||
BorderAgent::BorderAgent(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mCommissionerPetition(OT_URI_PATH_COMMISSIONER_PETITION,
|
||||
BorderAgent::HandleRequest<&BorderAgent::mCommissionerPetition>,
|
||||
this)
|
||||
, mCommissionerKeepAlive(OT_URI_PATH_COMMISSIONER_KEEP_ALIVE,
|
||||
BorderAgent::HandleRequest<&BorderAgent::mCommissionerKeepAlive>,
|
||||
this)
|
||||
, mRelayTransmit(OT_URI_PATH_RELAY_TX, BorderAgent::HandleRequest<&BorderAgent::mRelayTransmit>, this)
|
||||
, mRelayReceive(OT_URI_PATH_RELAY_RX, BorderAgent::HandleRequest<&BorderAgent::mRelayReceive>, this)
|
||||
, mCommissionerGet(OT_URI_PATH_COMMISSIONER_GET, BorderAgent::HandleRequest<&BorderAgent::mCommissionerGet>, this)
|
||||
, mCommissionerSet(OT_URI_PATH_COMMISSIONER_SET, BorderAgent::HandleRequest<&BorderAgent::mCommissionerSet>, this)
|
||||
, mActiveGet(OT_URI_PATH_ACTIVE_GET, BorderAgent::HandleRequest<&BorderAgent::mActiveGet>, this)
|
||||
, 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)
|
||||
, mTimer(aInstance, HandleTimeout, this)
|
||||
, mIsStarted(false)
|
||||
{
|
||||
}
|
||||
|
||||
void BorderAgent::HandleRelayReceive(const Coap::Header &aHeader, const Message &aMessage)
|
||||
{
|
||||
Coap::Header header;
|
||||
|
||||
VerifyOrExit(aHeader.GetType() == OT_COAP_TYPE_NON_CONFIRMABLE && aHeader.GetCode() == OT_COAP_CODE_POST);
|
||||
|
||||
header.Init(OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_POST);
|
||||
header.AppendUriPathOptions(OT_URI_PATH_RELAY_RX);
|
||||
|
||||
if (aMessage.GetLength() - aMessage.GetOffset() > 0)
|
||||
{
|
||||
header.SetPayloadMarker();
|
||||
}
|
||||
|
||||
SuccessOrExit(ForwardToCommissioner(header, aMessage));
|
||||
otLogInfoMeshCoP(GetInstance(), "Sent to leader on %s", OT_URI_PATH_RELAY_RX);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
otError BorderAgent::ForwardToCommissioner(const Coap::Header &aHeader, const Message &aMessage)
|
||||
{
|
||||
ThreadNetif &netif = GetNetif();
|
||||
otError error = OT_ERROR_NONE;
|
||||
Message * message = NULL;
|
||||
uint16_t offset = 0;
|
||||
|
||||
VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoapSecure(), aHeader)) != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
offset = message->GetLength();
|
||||
SuccessOrExit(error = message->SetLength(offset + aMessage.GetLength() - aMessage.GetOffset()));
|
||||
aMessage.CopyTo(aMessage.GetOffset(), offset, aMessage.GetLength() - aMessage.GetOffset(), *message);
|
||||
|
||||
SuccessOrExit(error = netif.GetCoapSecure().SendMessage(*message, netif.GetCoapSecure().GetPeerMessageInfo()));
|
||||
|
||||
otLogInfoMeshCoP(GetInstance(), "Sent to commissioner");
|
||||
|
||||
exit:
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
otLogWarnMeshCoP(GetInstance(), "Failed to send to commissioner: %s", otThreadErrorToString(error));
|
||||
if (message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void BorderAgent::HandleRelayTransmit(const Coap::Header &aHeader, const Message &aMessage)
|
||||
{
|
||||
ThreadNetif & netif = GetNetif();
|
||||
otError error = OT_ERROR_NONE;
|
||||
JoinerRouterLocatorTlv joinerRouterRloc;
|
||||
Message * message = NULL;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
Coap::Header header;
|
||||
uint16_t offset = 0;
|
||||
|
||||
VerifyOrExit(aHeader.GetType() == OT_COAP_TYPE_NON_CONFIRMABLE && aHeader.GetCode() == OT_COAP_CODE_POST);
|
||||
|
||||
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kJoinerRouterLocator, sizeof(joinerRouterRloc), joinerRouterRloc));
|
||||
VerifyOrExit(joinerRouterRloc.IsValid(), error = OT_ERROR_PARSE);
|
||||
|
||||
header.Init(OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_POST);
|
||||
header.SetToken(Coap::Header::kDefaultTokenLength);
|
||||
header.AppendUriPathOptions(OT_URI_PATH_RELAY_TX);
|
||||
header.SetPayloadMarker();
|
||||
|
||||
VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
offset = message->GetLength();
|
||||
SuccessOrExit(error = message->SetLength(offset + aMessage.GetLength() - aMessage.GetOffset()));
|
||||
aMessage.CopyTo(aMessage.GetOffset(), offset, aMessage.GetLength() - aMessage.GetOffset(), *message);
|
||||
|
||||
messageInfo.SetSockPort(kCoapUdpPort);
|
||||
messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16());
|
||||
messageInfo.SetPeerPort(kCoapUdpPort);
|
||||
messageInfo.SetPeerAddr(netif.GetMle().GetMeshLocal16());
|
||||
messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(joinerRouterRloc.GetJoinerRouterLocator());
|
||||
|
||||
SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo));
|
||||
|
||||
otLogInfoMeshCoP(borderAgent->GetInstance(), "Sent to joiner router request on %s", OT_URI_PATH_RELAY_TX);
|
||||
|
||||
exit:
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
otLogWarnMeshCoP(borderAgent->GetInstance(),
|
||||
"Failed to sent to joiner router request " OT_URI_PATH_RELAY_TX " %s",
|
||||
otThreadErrorToString(error));
|
||||
if (message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BorderAgent::ForwardToLeader(const Coap::Header & aHeader,
|
||||
const Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const char * aPath,
|
||||
bool aSeparate)
|
||||
{
|
||||
ThreadNetif & netif = GetNetif();
|
||||
otError error = OT_ERROR_NONE;
|
||||
ForwardContext * forwardContext = NULL;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
Coap::Header header;
|
||||
Message * message = NULL;
|
||||
uint16_t offset = 0;
|
||||
|
||||
if (aSeparate)
|
||||
{
|
||||
SuccessOrExit(error = netif.GetCoapSecure().SendAck(aHeader, aMessageInfo));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
header.Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST);
|
||||
header.SetToken(Coap::Header::kDefaultTokenLength);
|
||||
header.AppendUriPathOptions(aPath);
|
||||
|
||||
// Payload of c/cg may be empty
|
||||
if (aMessage.GetLength() - aMessage.GetOffset() > 0)
|
||||
{
|
||||
header.SetPayloadMarker();
|
||||
}
|
||||
|
||||
VerifyOrExit((message = NewMeshCoPMessage(netif.GetCoap(), header)) != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
offset = message->GetLength();
|
||||
SuccessOrExit(error = message->SetLength(offset + aMessage.GetLength() - aMessage.GetOffset()));
|
||||
aMessage.CopyTo(aMessage.GetOffset(), offset, aMessage.GetLength() - aMessage.GetOffset(), *message);
|
||||
|
||||
SuccessOrExit(netif.GetMle().GetLeaderAloc(messageInfo.GetPeerAddr()));
|
||||
messageInfo.SetPeerPort(kCoapUdpPort);
|
||||
messageInfo.SetSockAddr(netif.GetMle().GetMeshLocal16());
|
||||
messageInfo.SetSockPort(kCoapUdpPort);
|
||||
|
||||
SuccessOrExit(error = netif.GetCoap().SendMessage(*message, messageInfo, HandleCoapResponse, forwardContext));
|
||||
|
||||
// HandleCoapResponse is responsible to free this forward context.
|
||||
forwardContext = NULL;
|
||||
|
||||
otLogInfoMeshCoP(GetInstance(), "Forwarded request to leader on %s", aPath);
|
||||
|
||||
exit:
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
otLogWarnMeshCoP(GetInstance(), "Failed to forward to leader: %s", otThreadErrorToString(error));
|
||||
if (forwardContext != NULL)
|
||||
{
|
||||
GetInstance().GetHeap().Free(forwardContext);
|
||||
}
|
||||
|
||||
if (message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
|
||||
if (aHeader.GetType() == OT_COAP_TYPE_NON_CONFIRMABLE || aSeparate)
|
||||
{
|
||||
header.Init(OT_COAP_TYPE_NON_CONFIRMABLE, CoapCodeFromError(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
header.Init(OT_COAP_TYPE_ACKNOWLEDGMENT, CoapCodeFromError(error));
|
||||
}
|
||||
|
||||
header.SetMessageId(aSeparate ? 0 : aHeader.GetMessageId());
|
||||
header.SetToken(aHeader.GetToken(), aHeader.GetTokenLength());
|
||||
|
||||
SendErrorMessage(header);
|
||||
}
|
||||
}
|
||||
|
||||
void BorderAgent::HandleConnected(bool aConnected)
|
||||
{
|
||||
if (aConnected)
|
||||
{
|
||||
otLogInfoMeshCoP(GetInstance(), "Commissioner connected");
|
||||
mTimer.Start(kKeepAliveTimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
otLogInfoMeshCoP(GetInstance(), "Commissioner disconnected");
|
||||
mTimer.Start(kRestartDelay);
|
||||
}
|
||||
}
|
||||
|
||||
otError BorderAgent::StartCoaps(void)
|
||||
{
|
||||
ThreadNetif & netif = GetNetif();
|
||||
Coap::CoapSecure &coaps = netif.GetCoapSecure();
|
||||
otError error;
|
||||
|
||||
SuccessOrExit(error = coaps.Start(kBorderAgentUdpPort));
|
||||
SuccessOrExit(error = coaps.SetPsk(netif.GetKeyManager().GetPSKc(), OT_PSKC_MAX_SIZE));
|
||||
coaps.SetConnectedCallback(HandleConnected, this);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError BorderAgent::Start(void)
|
||||
{
|
||||
otError error;
|
||||
ThreadNetif & netif = GetNetif();
|
||||
Coap::CoapSecure &coaps = netif.GetCoapSecure();
|
||||
Coap::Coap & coap = netif.GetCoap();
|
||||
|
||||
VerifyOrExit(!mIsStarted, error = OT_ERROR_ALREADY);
|
||||
|
||||
SuccessOrExit(error = StartCoaps());
|
||||
|
||||
coaps.AddResource(mActiveGet);
|
||||
coaps.AddResource(mActiveSet);
|
||||
coaps.AddResource(mPendingGet);
|
||||
coaps.AddResource(mPendingSet);
|
||||
coaps.AddResource(mCommissionerPetition);
|
||||
coaps.AddResource(mCommissionerKeepAlive);
|
||||
coaps.AddResource(mCommissionerSet);
|
||||
coaps.AddResource(mCommissionerGet);
|
||||
coaps.AddResource(mRelayTransmit);
|
||||
|
||||
coap.AddResource(mRelayReceive);
|
||||
|
||||
mIsStarted = true;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void BorderAgent::HandleTimeout(Timer &aTimer)
|
||||
{
|
||||
aTimer.GetOwner<BorderAgent>().HandleTimeout();
|
||||
}
|
||||
|
||||
void BorderAgent::HandleTimeout(void)
|
||||
{
|
||||
ThreadNetif & netif = GetNetif();
|
||||
Coap::CoapSecure &coaps = netif.GetCoapSecure();
|
||||
otError error;
|
||||
|
||||
if (coaps.IsConnected())
|
||||
{
|
||||
error = coaps.Stop();
|
||||
otLogWarnMeshCoP(GetInstance(), "Reset commissioner session: %s", otThreadErrorToString(error));
|
||||
}
|
||||
else if (!coaps.IsConnectionActive())
|
||||
{
|
||||
error = StartCoaps();
|
||||
otLogWarnMeshCoP(GetInstance(), "Restart border agent secure CoAP service: %s", otThreadErrorToString(error));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
OT_UNUSED_VARIABLE(error);
|
||||
}
|
||||
|
||||
otError BorderAgent::Stop(void)
|
||||
{
|
||||
otError error;
|
||||
ThreadNetif & netif = GetNetif();
|
||||
Coap::CoapSecure &coaps = netif.GetCoapSecure();
|
||||
Coap::Coap & coap = netif.GetCoap();
|
||||
|
||||
VerifyOrExit(mIsStarted, error = OT_ERROR_ALREADY);
|
||||
|
||||
mTimer.Stop();
|
||||
|
||||
coaps.RemoveResource(mCommissionerPetition);
|
||||
coaps.RemoveResource(mCommissionerKeepAlive);
|
||||
coaps.RemoveResource(mCommissionerSet);
|
||||
coaps.RemoveResource(mCommissionerGet);
|
||||
coaps.RemoveResource(mActiveGet);
|
||||
coaps.RemoveResource(mActiveSet);
|
||||
coaps.RemoveResource(mPendingGet);
|
||||
coaps.RemoveResource(mPendingSet);
|
||||
coaps.RemoveResource(mRelayTransmit);
|
||||
|
||||
coap.RemoveResource(mRelayReceive);
|
||||
|
||||
error = coaps.Stop();
|
||||
assert(error == OT_ERROR_NONE);
|
||||
|
||||
mIsStarted = false;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace MeshCoP
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_ENABLE_BORDER_AGENT
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2018, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for the BorderAgent role.
|
||||
*/
|
||||
|
||||
#ifndef BORDER_AGENT_HPP_
|
||||
#define BORDER_AGENT_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include "coap/coap.hpp"
|
||||
#include "common/locator.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
class ThreadNetif;
|
||||
|
||||
namespace MeshCoP {
|
||||
|
||||
class BorderAgent : public InstanceLocator
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the BorderAgent object.
|
||||
*
|
||||
* @param[in] aInstance A reference to the OpenThread instance.
|
||||
*
|
||||
*/
|
||||
explicit BorderAgent(Instance &aInstance);
|
||||
|
||||
/**
|
||||
* This method starts the BorderAgent service.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started the BorderAgent service.
|
||||
*
|
||||
*/
|
||||
otError Start(void);
|
||||
|
||||
/**
|
||||
* This method stops the BorderAgent service.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully stopped the BorderAgent service.
|
||||
*
|
||||
*/
|
||||
otError Stop(void);
|
||||
|
||||
private:
|
||||
static void HandleConnected(bool aConnected, void *aContext)
|
||||
{
|
||||
static_cast<BorderAgent *>(aContext)->HandleConnected(aConnected);
|
||||
}
|
||||
void HandleConnected(bool aConnected);
|
||||
otError StartCoaps(void);
|
||||
|
||||
template <Coap::Resource BorderAgent::*aResource>
|
||||
static void HandleRequest(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
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 void HandleTimeout(Timer &aTimer);
|
||||
void HandleTimeout(void);
|
||||
|
||||
static void HandleCoapResponse(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
otError aResult);
|
||||
|
||||
void SendErrorMessage(const Coap::Header &aHeader);
|
||||
void ForwardToLeader(const Coap::Header & aHeader,
|
||||
const Message & aMessage,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const char * aPath,
|
||||
bool aSeparate);
|
||||
otError ForwardToCommissioner(const Coap::Header &aHeader, const Message &aMessage);
|
||||
void HandleRelayTransmit(const Coap::Header &aHeader, const Message &aMessage);
|
||||
void HandleRelayReceive(const Coap::Header &aHeader, const Message &aMessage);
|
||||
|
||||
enum
|
||||
{
|
||||
kBorderAgentUdpPort = 49191, ///< UDP port of border agent service.
|
||||
kKeepAliveTimeout = 50 * 1000, ///< Timeout to reject a commissioner.
|
||||
kRestartDelay = 1 * 1000, ///< Delay to restart border agent service.
|
||||
};
|
||||
|
||||
Ip6::MessageInfo mMessageInfo;
|
||||
|
||||
Coap::Resource mCommissionerPetition;
|
||||
Coap::Resource mCommissionerKeepAlive;
|
||||
Coap::Resource mRelayTransmit;
|
||||
Coap::Resource mRelayReceive;
|
||||
Coap::Resource mCommissionerGet;
|
||||
Coap::Resource mCommissionerSet;
|
||||
Coap::Resource mActiveGet;
|
||||
Coap::Resource mActiveSet;
|
||||
Coap::Resource mPendingGet;
|
||||
Coap::Resource mPendingSet;
|
||||
|
||||
TimerMilli mTimer;
|
||||
bool mIsStarted;
|
||||
};
|
||||
|
||||
} // namespace MeshCoP
|
||||
} // namespace ot
|
||||
|
||||
#endif // BORDER_AGENT_HPP_
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
enum
|
||||
{
|
||||
kPskMaxLength = 32,
|
||||
kApplicationDataMaxLength = 128,
|
||||
kApplicationDataMaxLength = 512,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -119,8 +119,7 @@ otError Joiner::Start(const char * aPSKd,
|
||||
error = netif.GetCoapSecure().Start(OPENTHREAD_CONFIG_JOINER_UDP_PORT);
|
||||
SuccessOrExit(error);
|
||||
|
||||
error = netif.GetCoapSecure().GetDtls().SetPsk(reinterpret_cast<const uint8_t *>(aPSKd),
|
||||
static_cast<uint8_t>(strlen(aPSKd)));
|
||||
error = netif.GetCoapSecure().SetPsk(reinterpret_cast<const uint8_t *>(aPSKd), static_cast<uint8_t>(strlen(aPSKd)));
|
||||
SuccessOrExit(error);
|
||||
|
||||
error = netif.GetCoapSecure().GetDtls().mProvisioningUrl.SetProvisioningUrl(aProvisioningUrl);
|
||||
|
||||
+39
-14
@@ -99,7 +99,6 @@ otError UdpSocket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
MessageInfo messageInfoLocal;
|
||||
UdpHeader udpHeader;
|
||||
|
||||
messageInfoLocal = aMessageInfo;
|
||||
|
||||
@@ -112,6 +111,7 @@ otError UdpSocket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo)
|
||||
{
|
||||
GetSockName().mPort = static_cast<Udp *>(mTransport)->GetEphemeralPort();
|
||||
}
|
||||
messageInfoLocal.SetSockPort(GetSockName().mPort);
|
||||
|
||||
if (messageInfoLocal.GetPeerAddr().IsUnspecified())
|
||||
{
|
||||
@@ -126,13 +126,6 @@ otError UdpSocket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo)
|
||||
messageInfoLocal.mPeerPort = GetPeerName().mPort;
|
||||
}
|
||||
|
||||
udpHeader.SetSourcePort(GetSockName().mPort);
|
||||
udpHeader.SetDestinationPort(messageInfoLocal.mPeerPort);
|
||||
udpHeader.SetLength(sizeof(udpHeader) + aMessage.GetLength());
|
||||
udpHeader.SetChecksum(0);
|
||||
|
||||
SuccessOrExit(error = aMessage.Prepend(&udpHeader, sizeof(udpHeader)));
|
||||
aMessage.SetOffset(0);
|
||||
SuccessOrExit(error = static_cast<Udp *>(mTransport)->SendDatagram(aMessage, messageInfoLocal, kProtoUdp));
|
||||
|
||||
exit:
|
||||
@@ -209,7 +202,34 @@ Message *Udp::NewMessage(uint16_t aReserved)
|
||||
|
||||
otError Udp::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, IpProto aIpProto)
|
||||
{
|
||||
return GetIp6().SendDatagram(aMessage, aMessageInfo, aIpProto);
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
#if OPENTHREAD_ENABLE_UDP_PROXY
|
||||
if (aMessageInfo.GetInterfaceId() == OT_NETIF_INTERFACE_ID_HOST)
|
||||
{
|
||||
VerifyOrExit(mProxySender != NULL, error = OT_ERROR_NO_ROUTE);
|
||||
mProxySender(&aMessage, aMessageInfo.mPeerPort, &aMessageInfo.GetPeerAddr(), aMessageInfo.mSockPort,
|
||||
mProxySenderContext);
|
||||
// message is consumed by the callback
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
UdpHeader udpHeader;
|
||||
|
||||
udpHeader.SetSourcePort(aMessageInfo.mSockPort);
|
||||
udpHeader.SetDestinationPort(aMessageInfo.mPeerPort);
|
||||
udpHeader.SetLength(sizeof(udpHeader) + aMessage.GetLength());
|
||||
udpHeader.SetChecksum(0);
|
||||
|
||||
SuccessOrExit(error = aMessage.Prepend(&udpHeader, sizeof(udpHeader)));
|
||||
aMessage.SetOffset(0);
|
||||
|
||||
error = GetIp6().SendDatagram(aMessage, aMessageInfo, aIpProto);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
|
||||
@@ -239,10 +259,18 @@ otError Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
|
||||
aMessageInfo.mPeerPort = udpHeader.GetSourcePort();
|
||||
aMessageInfo.mSockPort = udpHeader.GetDestinationPort();
|
||||
|
||||
HandlePayload(aMessage, aMessageInfo);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Udp::HandlePayload(Message &aMessage, MessageInfo &aMessageInfo)
|
||||
{
|
||||
// find socket
|
||||
for (UdpSocket *socket = mSockets; socket; socket = socket->GetNext())
|
||||
{
|
||||
if (socket->GetSockName().mPort != udpHeader.GetDestinationPort())
|
||||
if (socket->GetSockName().mPort != aMessageInfo.GetSockPort())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -261,7 +289,7 @@ otError Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
|
||||
// verify source if connected socket
|
||||
if (socket->GetPeerName().mPort != 0)
|
||||
{
|
||||
if (socket->GetPeerName().mPort != udpHeader.GetSourcePort())
|
||||
if (socket->GetPeerName().mPort != aMessageInfo.GetPeerPort())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -275,9 +303,6 @@ otError Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
|
||||
|
||||
socket->HandleUdpReceive(aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Udp::UpdateChecksum(Message &aMessage, uint16_t aChecksum)
|
||||
|
||||
@@ -241,6 +241,15 @@ public:
|
||||
*/
|
||||
otError HandleMessage(Message &aMessage, MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This method handles a received UDP message with offset set to the payload.
|
||||
*
|
||||
* @param[in] aMessage A reference to the UDP message to process.
|
||||
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
|
||||
*
|
||||
*/
|
||||
void HandlePayload(Message &aMessage, MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* This method updates the UDP checksum.
|
||||
*
|
||||
@@ -253,6 +262,21 @@ public:
|
||||
*/
|
||||
otError UpdateChecksum(Message &aMessage, uint16_t aPseudoHeaderChecksum);
|
||||
|
||||
#if OPENTHREAD_ENABLE_UDP_PROXY
|
||||
/**
|
||||
* This method sets the proxy sender.
|
||||
*
|
||||
* @param[in] aSender A function pointer to send the proxy UDP packet.
|
||||
* @param[in] aContext A pointer to arbitrary context information.
|
||||
*
|
||||
*/
|
||||
void SetProxySender(otUdpProxySender aSender, void *aContext)
|
||||
{
|
||||
mProxySender = aSender;
|
||||
mProxySenderContext = aContext;
|
||||
}
|
||||
#endif // OPENTHREAD_ENABLE_UDP_PROXY
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
@@ -261,6 +285,10 @@ private:
|
||||
};
|
||||
uint16_t mEphemeralPort;
|
||||
UdpSocket *mSockets;
|
||||
#if OPENTHREAD_ENABLE_UDP_PROXY
|
||||
void * mProxySenderContext;
|
||||
otUdpProxySender mProxySender;
|
||||
#endif
|
||||
};
|
||||
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
|
||||
@@ -96,7 +96,7 @@ void KeyManager::Stop(void)
|
||||
mKeyRotationTimer.Stop();
|
||||
}
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
#if OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
const uint8_t *KeyManager::GetPSKc(void) const
|
||||
{
|
||||
return mPSKc;
|
||||
@@ -111,7 +111,7 @@ void KeyManager::SetPSKc(const uint8_t *aPSKc)
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
|
||||
const otMasterKey &KeyManager::GetMasterKey(void) const
|
||||
{
|
||||
|
||||
@@ -359,7 +359,7 @@ private:
|
||||
bool mKeySwitchGuardEnabled;
|
||||
TimerMilli mKeyRotationTimer;
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
#if OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
uint8_t mPSKc[kMaxKeyLength];
|
||||
#endif
|
||||
uint8_t mKek[kMaxKeyLength];
|
||||
|
||||
@@ -302,6 +302,17 @@ void Mle::SetRole(otDeviceRole aRole)
|
||||
|
||||
mRole = aRole;
|
||||
GetNotifier().Signal(OT_CHANGED_THREAD_ROLE);
|
||||
#if OPENTHREAD_ENABLE_BORDER_AGENT
|
||||
// Start border agent
|
||||
if (aRole == OT_DEVICE_ROLE_ROUTER || aRole == OT_DEVICE_ROLE_LEADER || aRole == OT_DEVICE_ROLE_CHILD)
|
||||
{
|
||||
SuccessOrExit(GetInstance().GetBorderAgent().Start());
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(GetInstance().GetBorderAgent().Stop());
|
||||
}
|
||||
#endif
|
||||
|
||||
exit:
|
||||
return;
|
||||
|
||||
@@ -90,9 +90,6 @@ ThreadNetif::ThreadNetif(Instance &aInstance)
|
||||
, mJamDetector(aInstance)
|
||||
#endif // OPENTHREAD_ENABLE_JAM_DETECTTION
|
||||
#if OPENTHREAD_FTD
|
||||
#if OPENTHREAD_ENABLE_TMF_PROXY
|
||||
, mTmfProxy(mMleRouter.GetMeshLocal16(), mCoap)
|
||||
#endif // OPENTHREAD_ENABLE_TMF_PROXY
|
||||
, mJoinerRouter(aInstance)
|
||||
, mLeader(aInstance)
|
||||
, mAddressResolver(aInstance)
|
||||
|
||||
@@ -42,10 +42,6 @@
|
||||
#include "coap/coap_secure.hpp"
|
||||
#include "mac/mac.hpp"
|
||||
|
||||
#if OPENTHREAD_ENABLE_TMF_PROXY && OPENTHREAD_FTD
|
||||
#include "thread/tmf_proxy.hpp"
|
||||
#endif // OPENTHREAD_ENABLE_TMF_PROXY && OPENTHREAD_FTD
|
||||
|
||||
#if OPENTHREAD_ENABLE_COMMISSIONER && OPENTHREAD_FTD
|
||||
#include "meshcop/commissioner.hpp"
|
||||
#endif // OPENTHREAD_ENABLE_COMMISSIONER && OPENTHREAD_FTD
|
||||
@@ -371,16 +367,6 @@ public:
|
||||
Utils::JamDetector &GetJamDetector(void) { return mJamDetector; }
|
||||
#endif // OPENTHREAD_ENABLE_JAM_DETECTION
|
||||
|
||||
#if OPENTHREAD_ENABLE_TMF_PROXY && OPENTHREAD_FTD
|
||||
/**
|
||||
* This method returns the TMF proxy object.
|
||||
*
|
||||
* @returns Reference to the TMF proxy object.
|
||||
*
|
||||
*/
|
||||
TmfProxy &GetTmfProxy(void) { return mTmfProxy; }
|
||||
#endif // OPENTHREAD_ENABLE_TMF_PROXY && OPENTHREAD_FTD
|
||||
|
||||
/**
|
||||
* This method returns a reference to the child supervisor object.
|
||||
*
|
||||
@@ -479,10 +465,6 @@ private:
|
||||
Utils::JamDetector mJamDetector;
|
||||
#endif // OPENTHREAD_ENABLE_JAM_DETECTION
|
||||
|
||||
#if OPENTHREAD_ENABLE_TMF_PROXY && OPENTHREAD_FTD
|
||||
TmfProxy mTmfProxy;
|
||||
#endif // OPENTHREAD_ENABLE_TMF_PROXY && OPENTHREAD_FTD
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
MeshCoP::JoinerRouter mJoinerRouter;
|
||||
MeshCoP::Leader mLeader;
|
||||
|
||||
@@ -220,6 +220,22 @@ namespace ot {
|
||||
*/
|
||||
#define OT_URI_PATH_COMMISSIONER_GET "c/cg"
|
||||
|
||||
/**
|
||||
* @def OT_URI_PATH_COMMISSIONER_KEEP_ALIVE
|
||||
*
|
||||
* The URI Path for Commissioner Keep Alive.
|
||||
*
|
||||
*/
|
||||
#define OT_URI_PATH_COMMISSIONER_KEEP_ALIVE "c/ca"
|
||||
|
||||
/**
|
||||
* @def OT_URI_PATH_COMMISSIONER_PETITION
|
||||
*
|
||||
* The URI Path for Commissioner Petition.
|
||||
*
|
||||
*/
|
||||
#define OT_URI_PATH_COMMISSIONER_PETITION "c/cp"
|
||||
|
||||
/**
|
||||
* @def OT_URI_PATH_COMMISSIONER_SET
|
||||
*
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the TMF proxy.
|
||||
*/
|
||||
|
||||
#define WPP_NAME "tmf_proxy.tmh"
|
||||
|
||||
#include "tmf_proxy.hpp"
|
||||
|
||||
#include <openthread/types.h>
|
||||
|
||||
#include "coap/coap_header.hpp"
|
||||
#include "common/instance.hpp"
|
||||
#include "net/ip6_address.hpp"
|
||||
#include "thread/thread_tlvs.hpp"
|
||||
#include "thread/thread_uri_paths.hpp"
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_ENABLE_TMF_PROXY
|
||||
|
||||
namespace ot {
|
||||
|
||||
TmfProxy::TmfProxy(const Ip6::Address &aMeshLocal16, Coap::Coap &aCoap)
|
||||
: mRelayReceive(OT_URI_PATH_RELAY_RX, &TmfProxy::HandleRelayReceive, this)
|
||||
, mStreamHandler(NULL)
|
||||
, mContext(NULL)
|
||||
, mMeshLocal16(aMeshLocal16)
|
||||
, mCoap(aCoap)
|
||||
{
|
||||
}
|
||||
|
||||
otError TmfProxy::Start(otTmfProxyStreamHandler aStreamHandler, void *aContext)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(!mStreamHandler, error = OT_ERROR_ALREADY);
|
||||
|
||||
mCoap.AddResource(mRelayReceive);
|
||||
mStreamHandler = aStreamHandler;
|
||||
mContext = aContext;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError TmfProxy::Stop(void)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(mStreamHandler != NULL, error = OT_ERROR_ALREADY);
|
||||
|
||||
mCoap.RemoveResource(mRelayReceive);
|
||||
|
||||
mStreamHandler = NULL;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
bool TmfProxy::IsEnabled(void) const
|
||||
{
|
||||
return mStreamHandler != NULL;
|
||||
}
|
||||
|
||||
void TmfProxy::HandleRelayReceive(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
static_cast<TmfProxy *>(aContext)->DeliverMessage(*static_cast<Coap::Header *>(aHeader),
|
||||
*static_cast<Message *>(aMessage),
|
||||
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
}
|
||||
|
||||
void TmfProxy::HandleResponse(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
otError aResult)
|
||||
{
|
||||
VerifyOrExit(aResult == OT_ERROR_NONE);
|
||||
|
||||
static_cast<TmfProxy *>(aContext)->DeliverMessage(*static_cast<Coap::Header *>(aHeader),
|
||||
*static_cast<Message *>(aMessage),
|
||||
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void TmfProxy::DeliverMessage(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint16_t rloc;
|
||||
uint16_t port;
|
||||
Message *message = NULL;
|
||||
|
||||
VerifyOrExit(mStreamHandler != NULL, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
VerifyOrExit((message = aMessage.Clone()) != NULL, error = OT_ERROR_NO_BUFS);
|
||||
message->RemoveHeader(message->GetOffset() - aHeader.GetLength());
|
||||
|
||||
rloc = HostSwap16(aMessageInfo.GetPeerAddr().mFields.m16[7]);
|
||||
port = aMessageInfo.GetPeerPort();
|
||||
mStreamHandler(message, rloc, port, mContext);
|
||||
|
||||
exit:
|
||||
|
||||
if (error != OT_ERROR_NONE && message != NULL)
|
||||
{
|
||||
message->Free();
|
||||
}
|
||||
}
|
||||
|
||||
otError TmfProxy::Send(Message &aMessage, uint16_t aLocator, uint16_t aPort)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
Ip6::MessageInfo messageInfo;
|
||||
|
||||
VerifyOrExit(mStreamHandler != NULL, error = OT_ERROR_INVALID_STATE);
|
||||
|
||||
messageInfo.SetSockAddr(mMeshLocal16);
|
||||
messageInfo.SetPeerAddr(mMeshLocal16);
|
||||
messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(aLocator);
|
||||
messageInfo.SetPeerPort(aPort);
|
||||
|
||||
if (aPort == kCoapUdpPort)
|
||||
{
|
||||
// this is request to server, send with client
|
||||
error = mCoap.SendMessage(aMessage, messageInfo, TmfProxy::HandleResponse, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = mCoap.SendMessage(aMessage, messageInfo);
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
aMessage.Free();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_FTD && OPENTHREAD_ENABLE_TMF_PROXY
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for TMF proxy.
|
||||
*/
|
||||
|
||||
#ifndef TMF_PROXY_HPP_
|
||||
#define TMF_PROXY_HPP_
|
||||
|
||||
#include "openthread-core-config.h"
|
||||
|
||||
#include <openthread/tmf_proxy.h>
|
||||
|
||||
#include "coap/coap.hpp"
|
||||
|
||||
namespace ot {
|
||||
|
||||
class TmfProxy
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This constructor initializes the TMF proxy.
|
||||
*
|
||||
* @param[in] aMeshLocal16 A reference to the Mesh Local Routing Locator.
|
||||
* @param[in] aCoap A reference to the Management CoAP Service.
|
||||
*
|
||||
*/
|
||||
TmfProxy(const Ip6::Address &aMeshLocal16, Coap::Coap &aCoap);
|
||||
|
||||
/**
|
||||
* This method enables the TMF proxy service.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully started the service.
|
||||
* @retval OT_ERROR_ALREADY The service already started.
|
||||
*
|
||||
*/
|
||||
otError Start(otTmfProxyStreamHandler aStreamHandler, void *aContext);
|
||||
|
||||
/**
|
||||
* This method disables the TMF proxy service.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully stopped the TMF proxy service.
|
||||
* @retval OT_ERROR_ALREADY The service already stopped.
|
||||
*
|
||||
*/
|
||||
otError Stop(void);
|
||||
|
||||
/**
|
||||
* This method sends the message into the thread network.
|
||||
*
|
||||
* @param[in] aMessage A reference to the message to send.
|
||||
* @param[in] aLocator The destination's RLOC16 or ALOC16.
|
||||
* @param[in] aPort The destination port.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully send the message.
|
||||
* @retval OT_ERROR_INVALID_STATE Border agent proxy is not started.
|
||||
*
|
||||
* @warning No matter the call success or fail, the message is freed.
|
||||
*
|
||||
*/
|
||||
otError Send(Message &aMessage, uint16_t aLocator, uint16_t aPort);
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the TMF proxy service is enabled.
|
||||
*
|
||||
* @retval TRUE If the service is enabled.
|
||||
* @retval FALSE If the service is disabled.
|
||||
*
|
||||
*/
|
||||
bool IsEnabled(void) const;
|
||||
|
||||
private:
|
||||
static void HandleRelayReceive(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo);
|
||||
|
||||
static void HandleResponse(void * aContext,
|
||||
otCoapHeader * aHeader,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
otError aResult);
|
||||
|
||||
void DeliverMessage(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
|
||||
Coap::Resource mRelayReceive;
|
||||
otTmfProxyStreamHandler mStreamHandler;
|
||||
void * mContext;
|
||||
|
||||
const Ip6::Address &mMeshLocal16;
|
||||
Coap::Coap & mCoap;
|
||||
};
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // TMF_PROXY_HPP_
|
||||
@@ -251,6 +251,9 @@ NcpBase::NcpBase(Instance *aInstance)
|
||||
otSetStateChangedCallback(mInstance, &NcpBase::HandleStateChanged, this);
|
||||
otIp6SetReceiveCallback(mInstance, &NcpBase::HandleDatagramFromStack, this);
|
||||
otIp6SetReceiveFilterEnabled(mInstance, true);
|
||||
#if OPENTHREAD_ENABLE_UDP_PROXY
|
||||
otUdpProxySetSender(mInstance, &NcpBase::HandleUdpProxyStream, this);
|
||||
#endif
|
||||
otLinkSetPcapCallback(mInstance, &NcpBase::HandleRawFrame, static_cast<void *>(this));
|
||||
otIcmp6SetEchoMode(mInstance, OT_ICMP6_ECHO_HANDLER_DISABLED);
|
||||
#if OPENTHREAD_FTD
|
||||
@@ -1640,8 +1643,8 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CAPS>(void)
|
||||
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_NEST_LEGACY_INTERFACE));
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_ENABLE_TMF_PROXY
|
||||
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_TMF_PROXY));
|
||||
#if OPENTHREAD_ENABLE_UDP_PROXY
|
||||
SuccessOrExit(error = mEncoder.WriteUintPacked(SPINEL_CAP_THREAD_UDP_PROXY));
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
|
||||
@@ -293,13 +293,16 @@ protected:
|
||||
otError DecodeOperationalDataset(otOperationalDataset &aDataset, const uint8_t **aTlvs, uint8_t *aTlvsLength);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_ENABLE_UDP_PROXY
|
||||
static void HandleUdpProxyStream(otMessage * aMessage,
|
||||
uint16_t aPeerPort,
|
||||
otIp6Address *aPeerAddr,
|
||||
uint16_t aSockPort,
|
||||
void * aContext);
|
||||
void HandleUdpProxyStream(otMessage *aMessage, uint16_t aPeerPort, otIp6Address &aPeerAddr, uint16_t aPort);
|
||||
#endif // OPENTHREAD_ENABLE_UDP_PROXY
|
||||
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_ENABLE_TMF_PROXY
|
||||
static void HandleTmfProxyStream(otMessage *aMessage, uint16_t aLocator, uint16_t aPort, void *aContext);
|
||||
void HandleTmfProxyStream(otMessage *aMessage, uint16_t aLocator, uint16_t aPort);
|
||||
#endif // OPENTHREAD_FTD && OPENTHREAD_ENABLE_TMF_PROXY
|
||||
|
||||
otError CommandHandler_NOOP(uint8_t aHeader);
|
||||
otError CommandHandler_RESET(uint8_t aHeader);
|
||||
// Combined command handler for `VALUE_GET`, `VALUE_SET`, `VALUE_INSERT` and `VALUE_REMOVE`.
|
||||
|
||||
@@ -44,10 +44,6 @@
|
||||
#include <openthread/thread_ftd.h>
|
||||
#include <openthread/platform/misc.h>
|
||||
|
||||
#if OPENTHREAD_ENABLE_TMF_PROXY
|
||||
#include <openthread/tmf_proxy.h>
|
||||
#endif
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "common/debug.hpp"
|
||||
#include "common/instance.hpp"
|
||||
@@ -548,107 +544,6 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_ENABLE_TMF_PROXY
|
||||
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_TMF_PROXY_ENABLED>(void)
|
||||
{
|
||||
return mEncoder.WriteBool(otTmfProxyIsEnabled(mInstance));
|
||||
}
|
||||
|
||||
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_TMF_PROXY_STREAM>(void)
|
||||
{
|
||||
const uint8_t *framePtr = NULL;
|
||||
uint16_t frameLen = 0;
|
||||
uint16_t locator;
|
||||
uint16_t port;
|
||||
otMessage * message;
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
// THREAD_TMF_PROXY_STREAM requires layer 2 security.
|
||||
message = otIp6NewMessage(mInstance, true);
|
||||
VerifyOrExit(message != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
SuccessOrExit(error = mDecoder.ReadDataWithLen(framePtr, frameLen));
|
||||
SuccessOrExit(error = mDecoder.ReadUint16(locator));
|
||||
SuccessOrExit(error = mDecoder.ReadUint16(port));
|
||||
|
||||
SuccessOrExit(error = otMessageAppend(message, framePtr, static_cast<uint16_t>(frameLen)));
|
||||
|
||||
error = otTmfProxySend(mInstance, message, locator, port);
|
||||
|
||||
// `otTmfProxySend()` takes ownership of `message` (in both success
|
||||
// or failure cases). `message` is set to NULL so it is not freed at
|
||||
// exit.
|
||||
message = NULL;
|
||||
|
||||
exit:
|
||||
if (message != NULL)
|
||||
{
|
||||
otMessageFree(message);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_TMF_PROXY_ENABLED>(void)
|
||||
{
|
||||
bool enabled;
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
SuccessOrExit(error = mDecoder.ReadBool(enabled));
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
error = otTmfProxyStart(mInstance, &NcpBase::HandleTmfProxyStream, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = otTmfProxyStop(mInstance);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void NcpBase::HandleTmfProxyStream(otMessage *aMessage, uint16_t aLocator, uint16_t aPort, void *aContext)
|
||||
{
|
||||
static_cast<NcpBase *>(aContext)->HandleTmfProxyStream(aMessage, aLocator, aPort);
|
||||
}
|
||||
|
||||
void NcpBase::HandleTmfProxyStream(otMessage *aMessage, uint16_t aLocator, uint16_t aPort)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint16_t length = otMessageGetLength(aMessage);
|
||||
uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
|
||||
|
||||
SuccessOrExit(error = mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_THREAD_TMF_PROXY_STREAM));
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(length));
|
||||
SuccessOrExit(error = mEncoder.WriteMessage(aMessage));
|
||||
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(aLocator));
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(aPort));
|
||||
SuccessOrExit(error = mEncoder.EndFrame());
|
||||
|
||||
// The `aMessage` is owned by the outbound frame and NCP buffer
|
||||
// after frame was finished/ended successfully. It will be freed
|
||||
// when the frame is successfully sent and removed.
|
||||
|
||||
aMessage = NULL;
|
||||
|
||||
exit:
|
||||
|
||||
if (aMessage != NULL)
|
||||
{
|
||||
otMessageFree(aMessage);
|
||||
}
|
||||
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
mChangedPropsSet.AddLastStatus(SPINEL_STATUS_DROPPED);
|
||||
mUpdateChangedPropsTask.Post();
|
||||
}
|
||||
}
|
||||
#endif // OPENTHREAD_ENABLE_TMF_PROXY
|
||||
|
||||
otError NcpBase::DecodeOperationalDataset(otOperationalDataset &aDataset, const uint8_t **aTlvs, uint8_t *aTlvsLength)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
@@ -2928,6 +2928,82 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_ENABLE_UDP_PROXY
|
||||
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_UDP_PROXY_STREAM>(void)
|
||||
{
|
||||
const uint8_t * framePtr = NULL;
|
||||
uint16_t frameLen = 0;
|
||||
const otIp6Address *peerAddr;
|
||||
uint16_t peerPort;
|
||||
uint16_t sockPort;
|
||||
otMessage * message;
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
message = otIp6NewMessage(mInstance, false);
|
||||
VerifyOrExit(message != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
SuccessOrExit(error = mDecoder.ReadDataWithLen(framePtr, frameLen));
|
||||
SuccessOrExit(error = mDecoder.ReadUint16(peerPort));
|
||||
SuccessOrExit(error = mDecoder.ReadIp6Address(peerAddr));
|
||||
SuccessOrExit(error = mDecoder.ReadUint16(sockPort));
|
||||
|
||||
SuccessOrExit(error = otMessageAppend(message, framePtr, static_cast<uint16_t>(frameLen)));
|
||||
|
||||
otUdpProxyReceive(mInstance, message, peerPort, peerAddr, sockPort);
|
||||
|
||||
// `otUdpProxyReceive()` takes ownership of `message` (in both success
|
||||
// or failure cases). `message` is set to NULL so it is not freed at
|
||||
// exit.
|
||||
message = NULL;
|
||||
|
||||
exit:
|
||||
if (message != NULL)
|
||||
{
|
||||
otMessageFree(message);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void NcpBase::HandleUdpProxyStream(otMessage * aMessage,
|
||||
uint16_t aPeerPort,
|
||||
otIp6Address *aPeerAddr,
|
||||
uint16_t aSockPort,
|
||||
void * aContext)
|
||||
{
|
||||
static_cast<NcpBase *>(aContext)->HandleUdpProxyStream(aMessage, aPeerPort, *aPeerAddr, aSockPort);
|
||||
}
|
||||
|
||||
void NcpBase::HandleUdpProxyStream(otMessage *aMessage, uint16_t aPeerPort, otIp6Address &aPeerAddr, uint16_t aPort)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint16_t length = otMessageGetLength(aMessage);
|
||||
uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
|
||||
|
||||
SuccessOrExit(error = mEncoder.BeginFrame(header, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_THREAD_UDP_PROXY_STREAM));
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(length));
|
||||
SuccessOrExit(error = mEncoder.WriteMessage(aMessage));
|
||||
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(aPeerPort));
|
||||
SuccessOrExit(error = mEncoder.WriteIp6Address(aPeerAddr));
|
||||
SuccessOrExit(error = mEncoder.WriteUint16(aPort));
|
||||
SuccessOrExit(error = mEncoder.EndFrame());
|
||||
|
||||
// The `aMessage` is owned by the outbound frame and NCP buffer
|
||||
// after frame was finished/ended successfully. It will be freed
|
||||
// when the frame is successfully sent and removed.
|
||||
|
||||
aMessage = NULL;
|
||||
|
||||
exit:
|
||||
|
||||
if (aMessage != NULL)
|
||||
{
|
||||
otMessageFree(aMessage);
|
||||
}
|
||||
}
|
||||
#endif // OPENTHREAD_ENABLE_UDP_PROXY
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MARK: Property/Status Changed
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -1493,6 +1493,10 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
|
||||
ret = "PROP_THREAD_TMF_PROXY_STREAM";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_THREAD_UDP_PROXY_STREAM:
|
||||
ret = "PROP_THREAD_UDP_PROXY_STREAM";
|
||||
break;
|
||||
|
||||
case SPINEL_PROP_THREAD_DISCOVERY_SCAN_JOINER_FLAG:
|
||||
ret = "PROP_THREAD_DISCOVERY_SCAN_JOINER_FLAG";
|
||||
break;
|
||||
@@ -2254,6 +2258,10 @@ const char *spinel_capability_to_cstr(unsigned int capability)
|
||||
ret = "CAP_THREAD_TMF_PROXY";
|
||||
break;
|
||||
|
||||
case SPINEL_CAP_THREAD_UDP_PROXY:
|
||||
ret = "CAP_THREAD_UDP_PROXY";
|
||||
break;
|
||||
|
||||
case SPINEL_CAP_NEST_LEGACY_INTERFACE:
|
||||
ret = "CAP_NEST_LEGACY_INTERFACE";
|
||||
break;
|
||||
|
||||
@@ -458,6 +458,7 @@ enum
|
||||
SPINEL_CAP_THREAD__BEGIN = 1024,
|
||||
SPINEL_CAP_THREAD_COMMISSIONER = (SPINEL_CAP_THREAD__BEGIN + 0),
|
||||
SPINEL_CAP_THREAD_TMF_PROXY = (SPINEL_CAP_THREAD__BEGIN + 1),
|
||||
SPINEL_CAP_THREAD_UDP_PROXY = (SPINEL_CAP_THREAD__BEGIN + 2),
|
||||
SPINEL_CAP_THREAD__END = 1152,
|
||||
|
||||
SPINEL_CAP_NEST__BEGIN = 15296,
|
||||
@@ -1394,6 +1395,19 @@ typedef enum {
|
||||
*/
|
||||
SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE = SPINEL_PROP_THREAD_EXT__BEGIN + 35,
|
||||
|
||||
/// Thread UDP proxy stream
|
||||
/** Format `dS6S`
|
||||
*
|
||||
* This property helps exchange UDP packets with host.
|
||||
*
|
||||
* `d`: UDP payload
|
||||
* `S`: Remote UDP port
|
||||
* `6`: Remote IPv6 address
|
||||
* `S`: Local UDP port
|
||||
*
|
||||
*/
|
||||
SPINEL_PROP_THREAD_UDP_PROXY_STREAM = SPINEL_PROP_THREAD_EXT__BEGIN + 36,
|
||||
|
||||
SPINEL_PROP_THREAD_EXT__END = 0x1600,
|
||||
|
||||
SPINEL_PROP_IPV6__BEGIN = 0x60,
|
||||
|
||||
Reference in New Issue
Block a user