Secure CoAP Client and Server (#949)

* Secure CoAP client && server implemntation.

* Joiner && Commissioner refactoring to support secure CoAP.
This commit is contained in:
Robert Lubos
2016-11-14 18:15:38 +08:00
committed by Jonathan Hui
parent 2bc79217d2
commit 49144266e4
23 changed files with 1386 additions and 484 deletions
+6
View File
@@ -54,9 +54,12 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\core\coap\coap_base.cpp" />
<ClCompile Include="..\..\src\core\coap\coap_client.cpp" />
<ClCompile Include="..\..\src\core\coap\coap_header.cpp" />
<ClCompile Include="..\..\src\core\coap\coap_server.cpp" />
<ClCompile Include="..\..\src\core\coap\secure_coap_client.cpp" />
<ClCompile Include="..\..\src\core\coap\secure_coap_server.cpp" />
<ClCompile Include="..\..\src\core\common\crc16.cpp" />
<ClCompile Include="..\..\src\core\common\logging.cpp" />
<ClCompile Include="..\..\src\core\common\message.cpp" />
@@ -116,9 +119,12 @@
<ClCompile Include="..\..\src\core\utils\jam_detector.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\core\coap\coap_base.hpp" />
<ClInclude Include="..\..\src\core\coap\coap_client.hpp" />
<ClInclude Include="..\..\src\core\coap\coap_header.hpp" />
<ClInclude Include="..\..\src\core\coap\coap_server.hpp" />
<ClInclude Include="..\..\src\core\coap\secure_coap_client.hpp" />
<ClInclude Include="..\..\src\core\coap\secure_coap_server.hpp" />
<ClInclude Include="..\..\src\core\common\code_utils.hpp" />
<ClInclude Include="..\..\src\core\common\crc16.hpp" />
<ClInclude Include="..\..\src\core\common\debug.hpp" />
@@ -57,6 +57,9 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\core\coap\coap_base.cpp">
<Filter>Source Files\coap</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\coap\coap_client.cpp">
<Filter>Source Files\coap</Filter>
</ClCompile>
@@ -66,6 +69,12 @@
<ClCompile Include="..\..\src\core\coap\coap_server.cpp">
<Filter>Source Files\coap</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\coap\secure_coap_client.cpp">
<Filter>Source Files\coap</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\coap\secure_coap_server.cpp">
<Filter>Source Files\coap</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\common\logging.cpp">
<Filter>Source Files\common</Filter>
</ClCompile>
@@ -245,6 +254,9 @@
<ClInclude Include="..\..\src\core\openthread-core-config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\coap\coap_base.hpp">
<Filter>Header Files\coap</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\coap\coap_client.hpp">
<Filter>Header Files\coap</Filter>
</ClInclude>
@@ -254,6 +266,12 @@
<ClInclude Include="..\..\src\core\coap\coap_server.hpp">
<Filter>Header Files\coap</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\coap\secure_coap_client.hpp">
<Filter>Header Files\coap</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\coap\secure_coap_server.hpp">
<Filter>Header Files\coap</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\common\code_utils.hpp">
<Filter>Header Files\common</Filter>
</ClInclude>
@@ -64,9 +64,12 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\core\coap\coap_base.cpp" />
<ClCompile Include="..\..\src\core\coap\coap_client.cpp" />
<ClCompile Include="..\..\src\core\coap\coap_header.cpp" />
<ClCompile Include="..\..\src\core\coap\coap_server.cpp" />
<ClCompile Include="..\..\src\core\coap\secure_coap_client.cpp" />
<ClCompile Include="..\..\src\core\coap\secure_coap_server.cpp" />
<ClCompile Include="..\..\src\core\common\crc16.cpp" />
<ClCompile Include="..\..\src\core\common\logging.cpp" />
<ClCompile Include="..\..\src\core\common\message.cpp" />
@@ -129,9 +132,12 @@
<ClInclude Include="..\..\include\openthread.h" />
<ClInclude Include="..\..\include\openthread-types.h" />
<ClInclude Include="..\..\include\openthread-windows-config.h" />
<ClInclude Include="..\..\src\core\coap\coap_base.hpp" />
<ClInclude Include="..\..\src\core\coap\coap_client.hpp" />
<ClInclude Include="..\..\src\core\coap\coap_header.hpp" />
<ClInclude Include="..\..\src\core\coap\coap_server.hpp" />
<ClInclude Include="..\..\src\core\coap\secure_coap_client.hpp" />
<ClInclude Include="..\..\src\core\coap\secure_coap_server.hpp" />
<ClInclude Include="..\..\src\core\common\code_utils.hpp" />
<ClInclude Include="..\..\src\core\common\crc16.hpp" />
<ClInclude Include="..\..\src\core\common\debug.hpp" />
@@ -57,6 +57,9 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\core\coap\coap_base.cpp">
<Filter>Source Files\coap</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\coap\coap_client.cpp">
<Filter>Source Files\coap</Filter>
</ClCompile>
@@ -66,6 +69,12 @@
<ClCompile Include="..\..\src\core\coap\coap_server.cpp">
<Filter>Source Files\coap</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\coap\secure_coap_client.cpp">
<Filter>Source Files\coap</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\coap\secure_coap_server.cpp">
<Filter>Source Files\coap</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\common\logging.cpp">
<Filter>Source Files\common</Filter>
</ClCompile>
@@ -233,6 +242,9 @@
<ClInclude Include="..\..\src\core\openthread-core-config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\coap\coap_base.hpp">
<Filter>Header Files\coap</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\coap\coap_client.hpp">
<Filter>Header Files\coap</Filter>
</ClInclude>
@@ -242,6 +254,12 @@
<ClInclude Include="..\..\src\core\coap\coap_server.hpp">
<Filter>Header Files\coap</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\coap\secure_coap_client.hpp">
<Filter>Header Files\coap</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\coap\secure_coap_server.hpp">
<Filter>Header Files\coap</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\common\code_utils.hpp">
<Filter>Header Files\common</Filter>
</ClInclude>
+6
View File
@@ -37,6 +37,7 @@ libopenthread_a_CPPFLAGS = \
libopenthread_a_SOURCES = \
openthread.cpp \
coap/coap_base.cpp \
coap/coap_client.cpp \
coap/coap_header.cpp \
coap/coap_server.cpp \
@@ -92,6 +93,7 @@ libopenthread_a_SOURCES = \
if OPENTHREAD_ENABLE_COMMISSIONER
libopenthread_a_SOURCES += \
coap/secure_coap_server.cpp \
meshcop/announce_begin_client.cpp \
meshcop/commissioner.cpp \
meshcop/energy_scan_client.cpp \
@@ -107,6 +109,7 @@ endif # OPENTHREAD_ENABLE_JOINER
if OPENTHREAD_ENABLE_DTLS
libopenthread_a_SOURCES += \
coap/secure_coap_client.cpp \
meshcop/dtls.cpp \
$(NULL)
endif # OPENTHREAD_ENABLE_DTLS
@@ -133,9 +136,12 @@ noinst_HEADERS = \
openthread-core-config.h \
openthread-core-default-config.h \
openthread-instance.h \
coap/coap_base.hpp \
coap/coap_client.hpp \
coap/coap_header.hpp \
coap/coap_server.hpp \
coap/secure_coap_client.hpp \
coap/secure_coap_server.hpp \
common/code_utils.hpp \
common/crc16.hpp \
common/debug.hpp \
+78
View File
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2016, 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.
*/
#include <common/code_utils.hpp>
#include <coap/coap_base.hpp>
/**
* @file
* This file contains common code base for CoAP client and server.
*/
namespace Thread {
namespace Coap {
Message *CoapBase::NewMessage(const Header &aHeader)
{
Message *message = NULL;
// Ensure that header has minimum required length.
VerifyOrExit(aHeader.GetLength() >= Header::kMinHeaderLength, ;);
VerifyOrExit((message = mSocket.NewMessage(aHeader.GetLength())) != NULL, ;);
message->Prepend(aHeader.GetBytes(), aHeader.GetLength());
message->SetOffset(0);
exit:
return message;
}
ThreadError CoapBase::Start(const Ip6::SockAddr &aSockAddr)
{
ThreadError error;
SuccessOrExit(error = mSocket.Open(&CoapBase::HandleUdpReceive, this));
SuccessOrExit(error = mSocket.Bind(aSockAddr));
exit:
return error;
}
ThreadError CoapBase::Stop(void)
{
return mSocket.Close();
}
void CoapBase::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
{
static_cast<CoapBase *>(aContext)->mReceiver(aContext, *static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
} // namespace Coap
} // namespace Thread
+127
View File
@@ -0,0 +1,127 @@
/*
* Copyright (c) 2016, 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.
*/
#ifndef COAP_BASE_HPP_
#define COAP_BASE_HPP_
#include <openthread-types.h>
#include <coap/coap_header.hpp>
#include <common/message.hpp>
#include <net/netif.hpp>
#include <net/udp6.hpp>
/**
* @file
* This file contains common code base for CoAP client and server.
*/
namespace Thread {
namespace Coap {
/**
* @addtogroup core-coap
*
* @{
*
*/
/**
* This class implements a common code base for CoAP client/server.
*
*/
class CoapBase
{
public:
/**
* This function pointer is called when CoAP client/server wants to send a message.
*
* @param[in] aContext A pointer to arbitrary context information.
* @param[in] aMessage A reference to the message to send.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
*/
typedef ThreadError(* SenderFunction)(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
/**
* This function pointer is called when CoAP client/server receives a message.
*
* @param[in] aContext A pointer to arbitrary context information.
* @param[in] aMessage A reference to the received message.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
*/
typedef void (* ReceiverFunction)(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
/**
* This constructor initializes the object.
*
* @param[in] aUdp A reference to the UDP object.
* @param[in] aSender A pointer to a function for sending messages.
* @param[in] aReceiver A pointer to a function for handling received messages.
*
*/
CoapBase(Ip6::Udp &aUdp, SenderFunction aSender, ReceiverFunction aReceiver):
mSocket(aUdp),
mSender(aSender),
mReceiver(aReceiver) {};
/**
* This method creates a new message with a CoAP header.
*
* @param[in] aHeader A reference to a CoAP header that is used to create the message.
*
* @returns A pointer to the message or NULL if failed to allocate message.
*
*/
Message *NewMessage(const Header &aHeader);
/**
* This method returns a port number used by CoAP client.
*
* @returns A port number.
*
*/
uint16_t GetPort(void) { return mSocket.GetSockName().mPort; };
protected:
ThreadError Start(const Ip6::SockAddr &aSockAddr);
ThreadError Stop(void);
Ip6::UdpSocket mSocket;
SenderFunction mSender;
ReceiverFunction mReceiver;
private:
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
};
} // namespace Coap
} // namespace Thread
#endif // COAP_BASE_HPP_
+12 -29
View File
@@ -32,6 +32,7 @@
#include <common/debug.hpp>
#include <common/code_utils.hpp>
#include <net/ip6.hpp>
#include <net/udp6.hpp>
#include <platform/random.h>
/**
@@ -42,8 +43,8 @@
namespace Thread {
namespace Coap {
Client::Client(Ip6::Netif &aNetif):
mSocket(aNetif.GetIp6().mUdp),
Client::Client(Ip6::Netif &aNetif, SenderFunction aSender, ReceiverFunction aReceiver):
CoapBase(aNetif.GetIp6().mUdp, aSender, aReceiver),
mRetransmissionTimer(aNetif.GetIp6().mTimerScheduler, &Client::HandleRetransmissionTimer, this)
{
mMessageId = static_cast<uint16_t>(otPlatRandomGet());
@@ -51,7 +52,10 @@ Client::Client(Ip6::Netif &aNetif):
ThreadError Client::Start()
{
return mSocket.Open(&Client::HandleUdpReceive, this);
Ip6::SockAddr addr;
addr.mPort = static_cast<Ip6::Udp *>(mSocket.mTransport)->GetEphemeralPort();
return CoapBase::Start(addr);
}
ThreadError Client::Stop()
@@ -70,22 +74,7 @@ ThreadError Client::Stop()
FinalizeCoapTransaction(*messageToRemove, requestMetadata, NULL, NULL, kThreadError_Abort);
}
return mSocket.Close();
}
Message *Client::NewMessage(const Header &aHeader)
{
Message *message = NULL;
// Ensure that header has minimum required length.
VerifyOrExit(aHeader.GetLength() >= Header::kMinHeaderLength, ;);
VerifyOrExit((message = mSocket.NewMessage(aHeader.GetLength())) != NULL, ;);
message->Prepend(aHeader.GetBytes(), aHeader.GetLength());
message->SetOffset(0);
exit:
return message;
return CoapBase::Stop();
}
ThreadError Client::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo,
@@ -124,7 +113,7 @@ ThreadError Client::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMess
error = kThreadError_NoBufs);
}
SuccessOrExit(error = mSocket.SendTo(aMessage, aMessageInfo));
SuccessOrExit(error = mSender(this, aMessage, aMessageInfo));
exit:
@@ -206,7 +195,7 @@ ThreadError Client::SendCopy(const Message &aMessage, const Ip6::MessageInfo &aM
error = kThreadError_NoBufs);
// Send the copy.
SuccessOrExit(error = mSocket.SendTo(*messageCopy, aMessageInfo));
SuccessOrExit(error = mSender(this, *messageCopy, aMessageInfo));
exit:
@@ -233,7 +222,7 @@ void Client::SendEmptyMessage(const Ip6::Address &aAddress, uint16_t aPort, uint
messageInfo.SetPeerAddr(aAddress);
messageInfo.SetPeerPort(aPort);
SuccessOrExit(error = mSocket.SendTo(*message, messageInfo));
SuccessOrExit(error = mSender(this, *message, messageInfo));
exit:
@@ -364,13 +353,7 @@ void Client::FinalizeCoapTransaction(Message &aRequest, const RequestMetadata &a
}
}
void Client::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
{
static_cast<Client *>(aContext)->HandleUdpReceive(*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
void Client::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
void Client::ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
Header responseHeader;
Header requestHeader;
+16 -16
View File
@@ -31,6 +31,7 @@
#include <openthread-types.h>
#include <openthread-coap.h>
#include <coap/coap_base.hpp>
#include <coap/coap_header.hpp>
#include <common/message.hpp>
#include <common/timer.hpp>
@@ -184,17 +185,19 @@ private:
* This class implements CoAP client.
*
*/
class Client
class Client : public CoapBase
{
public:
/**
* This constructor initializes the object.
*
* @param[in] aNetif A reference to the network interface that CoAP client should be assigned to.
* @param[in] aNetif A reference to the network interface that CoAP client should be assigned to.
* @param[in] aSender A pointer to a function for sending messages.
* @param[in] aReceiver A pointer to a function for handling received messages.
*
*/
Client(Ip6::Netif &aNetif);
Client(Ip6::Netif &aNetif, SenderFunction aSender = &Client::Send, ReceiverFunction aReceiver = &Client::Receive);
/**
* This method starts the CoAP client.
@@ -212,16 +215,6 @@ public:
*/
ThreadError Stop(void);
/**
* This method creates a new message with a CoAP header.
*
* @param[in] aHeader A reference to a CoAP header that is used to create the message.
*
* @returns A pointer to the message or NULL if failed to allocate message.
*
*/
Message *NewMessage(const Header &aHeader);
/**
* This method sends a CoAP message.
*
@@ -249,6 +242,9 @@ public:
*/
const MessageQueue &GetRequestMessages(void) const { return mPendingRequests; }
protected:
void ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
private:
Message *CopyAndEnqueueMessage(const Message &aMessage, uint16_t aCopyLength,
const RequestMetadata &aRequestMetadata);
@@ -270,10 +266,14 @@ private:
static void HandleRetransmissionTimer(void *aContext);
void HandleRetransmissionTimer(void);
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static ThreadError Send(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) {
return (static_cast<Client *>(aContext))->mSocket.SendTo(aMessage, aMessageInfo);
}
static void Receive(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) {
(static_cast<Client *>(aContext))->ProcessReceivedMessage(aMessage, aMessageInfo);
}
Ip6::UdpSocket mSocket;
MessageQueue mPendingRequests;
uint16_t mMessageId;
Timer mRetransmissionTimer;
+12 -23
View File
@@ -37,8 +37,8 @@
namespace Thread {
namespace Coap {
Server::Server(Ip6::Udp &aUdp, uint16_t aPort):
mSocket(aUdp)
Server::Server(Ip6::Udp &aUdp, uint16_t aPort, SenderFunction aSender, ReceiverFunction aReceiver):
CoapBase(aUdp, aSender, aReceiver)
{
mPort = aPort;
mResources = NULL;
@@ -46,20 +46,15 @@ Server::Server(Ip6::Udp &aUdp, uint16_t aPort):
ThreadError Server::Start()
{
ThreadError error;
Ip6::SockAddr sockaddr;
sockaddr.mPort = mPort;
SuccessOrExit(error = mSocket.Open(&Server::HandleUdpReceive, this));
SuccessOrExit(error = mSocket.Bind(sockaddr));
exit:
return error;
return CoapBase::Start(sockaddr);
}
ThreadError Server::Stop()
{
return mSocket.Close();
return CoapBase::Stop();
}
ThreadError Server::AddResource(Resource &aResource)
@@ -100,13 +95,17 @@ exit:
aResource.mNext = NULL;
}
void Server::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
Message *Server::NewMessage(uint16_t aReserved)
{
static_cast<Server *>(aContext)->HandleUdpReceive(*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
return mSocket.NewMessage(aReserved);
}
void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
ThreadError Server::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return mSender(this, aMessage, aMessageInfo);
}
void Server::ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
Header header;
char uriPath[Resource::kMaxReceivedUriPath] = "";
@@ -159,15 +158,5 @@ exit:
{}
}
Message *Server::NewMessage(uint16_t aReserved)
{
return mSocket.NewMessage(aReserved);
}
ThreadError Server::SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return mSocket.SendTo(aMessage, aMessageInfo);
}
} // namespace Coap
} // namespace Thread
+28 -7
View File
@@ -34,6 +34,7 @@
#ifndef COAP_SERVER_HPP_
#define COAP_SERVER_HPP_
#include <coap/coap_base.hpp>
#include <coap/coap_header.hpp>
#include <common/message.hpp>
#include <net/udp6.hpp>
@@ -103,17 +104,20 @@ private:
* This class implements the CoAP server.
*
*/
class Server
class Server : public CoapBase
{
public:
/**
* This constructor initializes the object.
*
* @param[in] aUdp A reference to the UDP object.
* @param[in] aPort The port to listen on.
* @param[in] aUdp A reference to the UDP object.
* @param[in] aPort The port to listen on.
* @param[in] aSender A pointer to a function for sending messages.
* @param[in] aReceiver A pointer to a function for handling received messages.
*
*/
Server(Ip6::Udp &aUdp, uint16_t aPort);
Server(Ip6::Udp &aUdp, uint16_t aPort, SenderFunction aSender = &Server::Send,
ReceiverFunction aReceiver = &Server::Receive);
/**
* This method starts the CoAP server.
@@ -160,6 +164,16 @@ public:
*/
Message *NewMessage(uint16_t aReserved);
/**
* This method creates a new message with a CoAP header.
*
* @param[in] aHeader A reference to a CoAP header that is used to create the message.
*
* @returns A pointer to the message or NULL if failed to allocate message.
*
*/
Message *NewMessage(const Header &aHeader) { return CoapBase::NewMessage(aHeader); };
/**
* This method sends a CoAP response from the server.
*
@@ -172,11 +186,18 @@ public:
*/
ThreadError SendMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
protected:
void ProcessReceivedMessage(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
private:
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static ThreadError Send(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) {
return (static_cast<Server *>(aContext))->mSocket.SendTo(aMessage, aMessageInfo);
}
static void Receive(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) {
(static_cast<Server *>(aContext))->ProcessReceivedMessage(aMessage, aMessageInfo);
}
Ip6::UdpSocket mSocket;
uint16_t mPort;
Resource *mResources;
};
+237
View File
@@ -0,0 +1,237 @@
/*
* Copyright (c) 2016, 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.
*/
#define WPP_NAME "secure_coap_client.tmh"
#include <coap/secure_coap_client.hpp>
#include <common/logging.hpp>
#include <meshcop/dtls.hpp>
#include <thread/thread_netif.hpp>
/**
* @file
* This file implements the secure CoAP client.
*/
namespace Thread {
namespace Coap {
SecureClient::SecureClient(ThreadNetif &aNetif):
Client(aNetif, &SecureClient::Send, &SecureClient::Receive),
mConnectedCallback(NULL),
mContext(NULL),
mNetif(aNetif),
mTransmitMessage(NULL),
mTransmitTask(aNetif.GetIp6().mTaskletScheduler, &SecureClient::HandleUdpTransmit, this)
{
}
ThreadError SecureClient::Stop(void)
{
if (IsConnectionActive())
{
Disconnect();
}
if (mTransmitMessage != NULL)
{
mTransmitMessage->Free();
mTransmitMessage = NULL;
}
return Client::Stop();
}
ThreadError SecureClient::Connect(const Ip6::MessageInfo &aMessageInfo, ConnectedCallback aCallback, void *aContext)
{
mPeerAddress = aMessageInfo;
mConnectedCallback = aCallback;
mContext = aContext;
return mNetif.GetDtls().Start(true, &SecureClient::HandleDtlsReceive, &SecureClient::HandleDtlsSend, this);
}
bool SecureClient::IsConnectionActive(void)
{
return mNetif.GetDtls().IsStarted();
};
bool SecureClient::IsConnected(void)
{
return mNetif.GetDtls().IsConnected();
};
ThreadError SecureClient::Disconnect(void)
{
return mNetif.GetDtls().Stop();
}
MeshCoP::Dtls &SecureClient::GetDtls(void)
{
return mNetif.GetDtls();
};
ThreadError SecureClient::SendMessage(Message &aMessage, otCoapResponseHandler aHandler, void *aContext)
{
ThreadError error = kThreadError_None;
otLogFuncEntry();
VerifyOrExit(IsConnected(), error = kThreadError_InvalidState);
error = Client::SendMessage(aMessage, mPeerAddress, aHandler, aContext);
exit:
otLogFuncExitErr(error);
return error;
}
ThreadError SecureClient::Send(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return static_cast<SecureClient *>(aContext)->Send(aMessage, aMessageInfo);
}
ThreadError SecureClient::Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
(void)aMessageInfo;
return mNetif.GetDtls().Send(aMessage, aMessage.GetLength());
}
void SecureClient::Receive(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return static_cast<SecureClient *>(aContext)->Receive(aMessage, aMessageInfo);
}
void SecureClient::Receive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
otLogFuncEntry();
VerifyOrExit((mPeerAddress.GetPeerAddr() == aMessageInfo.GetPeerAddr()) &&
(mPeerAddress.GetPeerPort() == aMessageInfo.GetPeerPort()), ;);
mNetif.GetDtls().Receive(aMessage, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset());
if ((IsConnected()) && (mConnectedCallback != NULL))
{
mConnectedCallback(mContext);
mConnectedCallback = NULL;
mContext = NULL;
}
exit:
otLogFuncExit();
}
void SecureClient::HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength)
{
return static_cast<SecureClient *>(aContext)->HandleDtlsReceive(aBuf, aLength);
}
void SecureClient::HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength)
{
Message *message = NULL;
otLogFuncEntry();
VerifyOrExit((message = mNetif.GetIp6().mMessagePool.New(Message::kTypeIp6, 0)) != NULL, ;);
SuccessOrExit(message->Append(aBuf, aLength));
ProcessReceivedMessage(*message, mPeerAddress);
exit:
if (message != NULL)
{
message->Free();
}
otLogFuncExit();
}
ThreadError SecureClient::HandleDtlsSend(void *aContext, const uint8_t *aBuf, uint16_t aLength)
{
return static_cast<SecureClient *>(aContext)->HandleDtlsSend(aBuf, aLength);
}
ThreadError SecureClient::HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength)
{
ThreadError error = kThreadError_None;
otLogFuncEntry();
if (mTransmitMessage == NULL)
{
VerifyOrExit((mTransmitMessage = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
mTransmitMessage->SetLinkSecurityEnabled(false);
}
VerifyOrExit(mTransmitMessage->Append(aBuf, aLength) == kThreadError_None, error = kThreadError_NoBufs);
mTransmitTask.Post();
exit:
if (error != kThreadError_None && mTransmitMessage != NULL)
{
mTransmitMessage->Free();
}
otLogFuncExitErr(error);
return error;
}
void SecureClient::HandleUdpTransmit(void *aContext)
{
return static_cast<SecureClient *>(aContext)->HandleUdpTransmit();
}
void SecureClient::HandleUdpTransmit(void)
{
ThreadError error = kThreadError_None;
otLogFuncEntry();
VerifyOrExit(mTransmitMessage != NULL, error = kThreadError_NoBufs);
SuccessOrExit(error = mSocket.SendTo(*mTransmitMessage, mPeerAddress));
exit:
if (error != kThreadError_None && mTransmitMessage != NULL)
{
mTransmitMessage->Free();
}
mTransmitMessage = NULL;
otLogFuncExit();
}
} // namespace Coap
} // namespace Thread
+163
View File
@@ -0,0 +1,163 @@
/*
* Copyright (c) 2016, 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.
*/
#ifndef SECURE_COAP_CLIENT_HPP_
#define SECURE_COAP_CLIENT_HPP_
#include <coap/coap_client.hpp>
#include <meshcop/dtls.hpp>
/**
* @file
* This file includes definitions for the secure CoAP client.
*/
namespace Thread {
class ThreadNetif;
namespace Coap {
class SecureClient: public Client
{
public:
/**
* This function pointer is called once DTLS connection is established.
*
* @param[in] aContext A pointer to arbitrary context information.
*
*/
typedef void (*ConnectedCallback)(void *aContext);
/**
* This constructor initializes the object.
*
* @param[in] aNetif A reference to the network interface that secure CoAP client should be assigned to.
*
*/
SecureClient(ThreadNetif &aNetif);
/**
* This method stops the secure CoAP client.
*
* @retval kThreadError_None Successfully stopped the secure CoAP client.
*
*/
ThreadError Stop(void);
/**
* This method initializes DTLS session with a peer.
*
* @param[in] aMessageInfo A reference to an address of the peer.
* @param[in] aCallback A pointer to a function that will be called once DTLS connection is established.
*
* @retval kThreadError_None Successfully started DTLS connection.
*
*/
ThreadError Connect(const Ip6::MessageInfo &aMessageInfo, ConnectedCallback aCallback, void *aContext);
/**
* This method indicates whether or not the DTLS session is active.
*
* @retval TRUE If DTLS session is active.
* @retval FALSE If DTLS session is not active.
*
*/
bool IsConnectionActive(void);
/**
* This method indicates whether or not the DTLS session is connected.
*
* @retval TRUE The DTLS session is connected.
* @retval FALSE The DTLS session is not connected.
*
*/
bool IsConnected(void);
/**
* This method stops the DTLS connection.
*
* @retval kThreadError_None Successfully stopped the DTLS connection.
*
*/
ThreadError Disconnect(void);
/**
* This method returns a reference to the DTLS object.
*
* @returns A reference to the DTLS object.
*
*/
MeshCoP::Dtls &GetDtls(void);
/**
* This method sends a CoAP message over secure DTLS connection.
*
* If a response for a request is expected, respective function and context information should be provided.
* If no response is expected, these arguments should be NULL pointers.
* If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message.
*
* @param[in] aMessage A reference to the message to send.
* @param[in] aHandler A function pointer that shall be called on response reception or time-out.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval kThreadError_None Successfully sent CoAP message.
* @retval kThreadError_NoBufs Failed to allocate retransmission data.
* @retvak kThreadError_InvalidState DTLS connection was not initialized.
*
*/
ThreadError SendMessage(Message &aMessage, otCoapResponseHandler aHandler = NULL, void *aContext = NULL);
private:
static ThreadError Send(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
ThreadError Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void Receive(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void Receive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength);
void HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength);
static ThreadError HandleDtlsSend(void *aContext, const uint8_t *aBuf, uint16_t aLength);
ThreadError HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength);
static void HandleUdpTransmit(void *aContext);
void HandleUdpTransmit(void);
Ip6::MessageInfo mPeerAddress;
ConnectedCallback mConnectedCallback;
void *mContext;
ThreadNetif &mNetif;
Message *mTransmitMessage;
Tasklet mTransmitTask;
};
} // namespace Coap
} // namespace Thread
#endif // SECURE_COAP_CLIENT_HPP_
+237
View File
@@ -0,0 +1,237 @@
/*
* Copyright (c) 2016, 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.
*/
#define WPP_NAME "secure_coap_server.tmh"
#include <coap/secure_coap_server.hpp>
#include <common/logging.hpp>
#include <meshcop/dtls.hpp>
#include <thread/thread_netif.hpp>
/**
* @file
* This file implements the secure CoAP server.
*/
namespace Thread {
namespace Coap {
SecureServer::SecureServer(ThreadNetif &aNetif, uint16_t aPort):
Server(aNetif.GetIp6().mUdp, aPort, &SecureServer::Send, &SecureServer::Receive),
mTransmitCallback(NULL),
mContext(NULL),
mNetif(aNetif),
mTransmitMessage(NULL),
mTransmitTask(aNetif.GetIp6().mTaskletScheduler, &SecureServer::HandleUdpTransmit, this)
{
}
ThreadError SecureServer::Start(TransportCallback aCallback, void *aContext)
{
ThreadError error = kThreadError_None;
mTransmitCallback = aCallback;
mContext = aContext;
// Passing mTransmitCallback means that we do not want to use socket
// to transmit/receive messages, so do not open it in that case.
if (mTransmitCallback == NULL)
{
error = Server::Start();
}
return error;
}
ThreadError SecureServer::Stop()
{
if (mNetif.GetDtls().IsStarted())
{
mNetif.GetDtls().Stop();
}
if (mTransmitMessage != NULL)
{
mTransmitMessage->Free();
mTransmitMessage = NULL;
}
mTransmitCallback = NULL;
mContext = NULL;
otLogFuncExit();
return Server::Stop();
}
bool SecureServer::IsConnectionActive(void)
{
return mNetif.GetDtls().IsStarted();
};
ThreadError SecureServer::Send(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return static_cast<SecureServer *>(aContext)->Send(aMessage, aMessageInfo);
}
ThreadError SecureServer::Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
(void)aMessageInfo;
return mNetif.GetDtls().Send(aMessage, aMessage.GetLength());
}
void SecureServer::Receive(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
return static_cast<SecureServer *>(aContext)->Receive(aMessage, aMessageInfo);
}
void SecureServer::Receive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
otLogFuncEntry();
if (!mNetif.GetDtls().IsStarted())
{
mPeerAddress.SetPeerAddr(aMessageInfo.GetPeerAddr());
mPeerAddress.SetPeerPort(aMessageInfo.GetPeerPort());
mNetif.GetDtls().Start(false, HandleDtlsReceive, HandleDtlsSend, this);
}
else
{
// Once DTLS session is started, communicate only with a peer.
VerifyOrExit((mPeerAddress.GetPeerAddr() == aMessageInfo.GetPeerAddr()) &&
(mPeerAddress.GetPeerPort() == aMessageInfo.GetPeerPort()), ;);
}
mNetif.GetDtls().SetClientId(mPeerAddress.GetPeerAddr().mFields.m8,
sizeof(mPeerAddress.GetPeerAddr().mFields));
mNetif.GetDtls().Receive(aMessage, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset());
exit:
otLogFuncExit();
}
ThreadError SecureServer::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
{
return mNetif.GetDtls().SetPsk(aPsk, aPskLength);
}
void SecureServer::HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength)
{
return static_cast<SecureServer *>(aContext)->HandleDtlsReceive(aBuf, aLength);
}
void SecureServer::HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength)
{
Message *message;
otLogFuncEntry();
VerifyOrExit((message = mNetif.GetIp6().mMessagePool.New(Message::kTypeIp6, 0)) != NULL, ;);
SuccessOrExit(message->Append(aBuf, aLength));
ProcessReceivedMessage(*message, mPeerAddress);
exit:
if (message != NULL)
{
message->Free();
}
otLogFuncExit();
}
ThreadError SecureServer::HandleDtlsSend(void *aContext, const uint8_t *aBuf, uint16_t aLength)
{
return static_cast<SecureServer *>(aContext)->HandleDtlsSend(aBuf, aLength);
}
ThreadError SecureServer::HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength)
{
ThreadError error = kThreadError_None;
otLogFuncEntry();
if (mTransmitMessage == NULL)
{
VerifyOrExit((mTransmitMessage = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
mTransmitMessage->SetLinkSecurityEnabled(false);
}
VerifyOrExit(mTransmitMessage->Append(aBuf, aLength) == kThreadError_None, error = kThreadError_NoBufs);
mTransmitTask.Post();
exit:
if (error != kThreadError_None && mTransmitMessage != NULL)
{
mTransmitMessage->Free();
}
otLogFuncExitErr(error);
return error;
}
void SecureServer::HandleUdpTransmit(void *aContext)
{
return static_cast<SecureServer *>(aContext)->HandleUdpTransmit();
}
void SecureServer::HandleUdpTransmit(void)
{
ThreadError error = kThreadError_None;
otLogFuncEntry();
VerifyOrExit(mTransmitMessage != NULL, error = kThreadError_NoBufs);
if (mTransmitCallback)
{
SuccessOrExit(error = mTransmitCallback(mContext, *mTransmitMessage, mPeerAddress));
}
else
{
SuccessOrExit(error = mSocket.SendTo(*mTransmitMessage, mPeerAddress));
}
exit:
if (error != kThreadError_None && mTransmitMessage != NULL)
{
mTransmitMessage->Free();
}
mTransmitMessage = NULL;
otLogFuncExit();
}
} // namespace Coap
} // namespace Thread
+143
View File
@@ -0,0 +1,143 @@
/*
* Copyright (c) 2016, 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.
*/
#ifndef SECURE_COAP_SERVER_HPP_
#define SECURE_COAP_SERVER_HPP_
#include "coap/coap_server.hpp"
/**
* @file
* This file includes definitions for the secure CoAP server.
*/
namespace Thread {
class ThreadNetif;
namespace Coap {
class SecureServer : public Server
{
public:
/**
* This function pointer is called when secure CoAP server want to send encrypted message.
*
* @param[in] aContext A pointer to arbitrary context information.
* @param[in] aMessage A reference to the message to send.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
*/
typedef ThreadError(*TransportCallback)(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
/**
* This constructor initializes the object.
*
* @param[in] aNetif A reference to the network interface that secure CoAP server should be assigned to.
* @param[in] aPort The port to listen on.
*
*/
SecureServer(ThreadNetif &aNetif, uint16_t aPort);
/**
* This method starts the secure CoAP server.
*
* @param[in] aCallback A pointer to a function for sending messages. If NULL, the message is sent directly to server socket.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval kThreadError_None Successfully started the CoAP server.
*
*/
ThreadError Start(TransportCallback aCallback = NULL, void *aContext = NULL);
/**
* This method stops the secure CoAP server.
*
* @retval kThreadError_None Successfully stopped the CoAP server.
*
*/
ThreadError Stop(void);
/**
* This method indicates whether or not the DTLS session is active.
*
* @retval TRUE If DTLS session is active.
* @retval FALSE If DTLS session is not active.
*
*/
bool IsConnectionActive(void);
/**
* This method is used to pass messages to the secure CoAP server.
* It can be used when messages are received other way that via server's socket.
*
* @param[in] aMessage A reference to the received message.
* @param[in] aMessageInfo A reference to the message info associated with @p aMessage.
*
*/
void Receive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
/**
* This method sets the PSK.
*
* @param[in] aPSK A pointer to the PSK.
* @param[in] aPskLenght A PSK length.
*
* @retval kThreadError_None Successfully set the PSK.
* @retval kThreadError_InvalidArgs The PSK is invalid.
*
*/
ThreadError SetPsk(const uint8_t *aPsk, uint8_t aPskLength);
private:
static ThreadError Send(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
ThreadError Send(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void Receive(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength);
void HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength);
static ThreadError HandleDtlsSend(void *aContext, const uint8_t *aBuf, uint16_t aLength);
ThreadError HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength);
static void HandleUdpTransmit(void *aContext);
void HandleUdpTransmit(void);
Ip6::MessageInfo mPeerAddress;
TransportCallback mTransmitCallback;
void *mContext;
ThreadNetif &mNetif;
Message *mTransmitMessage;
Tasklet mTransmitTask;
};
} // namespace Coap
} // namespace Thread
#endif // SECURE_COAP_SERVER_HPP_
+147 -203
View File
@@ -65,17 +65,19 @@ Commissioner::Commissioner(ThreadNetif &aThreadNetif):
mPanIdQuery(aThreadNetif),
mState(kStateDisabled),
mTimer(aThreadNetif.GetIp6().mTimerScheduler, HandleTimer, this),
mTransmitTask(aThreadNetif.GetIp6().mTaskletScheduler, &Commissioner::HandleUdpTransmit, this),
mSendKek(false),
mRelayReceive(OPENTHREAD_URI_RELAY_RX, &Commissioner::HandleRelayReceive, this),
mDatasetChanged(OPENTHREAD_URI_DATASET_CHANGED, &Commissioner::HandleDatasetChanged, this),
mJoinerFinalize(OPENTHREAD_URI_JOINER_FINALIZE, &Commissioner::HandleJoinerFinalize, this),
mCoapServer(aThreadNetif.GetCoapServer()),
mCoapClient(aThreadNetif.GetCoapClient()),
mSecureCoapServer(aThreadNetif.GetSecureCoapServer()),
mNetif(aThreadNetif)
{
memset(mJoiners, 0, sizeof(mJoiners));
mCoapServer.AddResource(mRelayReceive);
mCoapServer.AddResource(mDatasetChanged);
mSecureCoapServer.AddResource(mJoinerFinalize);
}
ThreadError Commissioner::Start(void)
@@ -85,8 +87,11 @@ ThreadError Commissioner::Start(void)
otLogFuncEntry();
VerifyOrExit(mState == kStateDisabled, error = kThreadError_InvalidState);
SuccessOrExit(error = mSecureCoapServer.Start(SendRelayTransmit, this));
mState = kStatePetition;
mTransmitAttempts = 0;
mSendKek = false;
SendPetition();
@@ -102,8 +107,11 @@ ThreadError Commissioner::Stop(void)
otLogFuncEntry();
VerifyOrExit(mState != kStateDisabled, error = kThreadError_InvalidState);
mSecureCoapServer.Stop();
mState = kStateDisabled;
mTransmitAttempts = 0;
mSendKek = false;
mTimer.Stop();
@@ -640,8 +648,10 @@ void Commissioner::HandleRelayReceive(Coap::Header &aHeader, Message &aMessage,
JoinerUdpPortTlv joinerPort;
JoinerIidTlv joinerIid;
JoinerRouterLocatorTlv joinerRloc;
Ip6::MessageInfo joinerMessageInfo;
uint16_t offset;
uint16_t length;
bool enableJoiner = false;
otLogFuncEntry();
@@ -659,14 +669,14 @@ void Commissioner::HandleRelayReceive(Coap::Header &aHeader, Message &aMessage,
SuccessOrExit(error = Tlv::GetValueOffset(aMessage, Tlv::kJoinerDtlsEncapsulation, offset, length));
memcpy(mJoinerIid, joinerIid.GetIid(), sizeof(mJoinerIid));
mJoinerPort = joinerPort.GetUdpPort();
mJoinerRloc = joinerRloc.GetJoinerRouterLocator();
otLogInfoMeshCoP("Received relay receive for %llX, rloc:%x", HostSwap64(mJoinerIid64), mJoinerRloc);
if (!mNetif.GetDtls().IsStarted())
if (!mSecureCoapServer.IsConnectionActive())
{
memcpy(mJoinerIid, joinerIid.GetIid(), sizeof(mJoinerIid));
mJoinerPort = joinerPort.GetUdpPort();
mJoinerRloc = joinerRloc.GetJoinerRouterLocator();
otLogInfoMeshCoP("Received relay receive for %llX, rloc:%x", HostSwap64(mJoinerIid64), mJoinerRloc);
mJoinerIid[0] ^= 0x2;
for (size_t i = 0; i < sizeof(mJoiners) / sizeof(mJoiners[0]); i++)
@@ -678,21 +688,32 @@ void Commissioner::HandleRelayReceive(Coap::Header &aHeader, Message &aMessage,
if (mJoiners[i].mAny || !memcmp(&mJoiners[i].mExtAddress, mJoinerIid, sizeof(mJoiners[i].mExtAddress)))
{
SuccessOrExit(error = mNetif.GetDtls().SetPsk(reinterpret_cast<const uint8_t *>(mJoiners[i].mPsk),
static_cast<uint8_t>(strlen(mJoiners[i].mPsk))));
SuccessOrExit(error = mNetif.GetDtls().Start(false, HandleDtlsReceive, HandleDtlsSend, this));
SuccessOrExit(error = mSecureCoapServer.SetPsk(reinterpret_cast<const uint8_t *>(mJoiners[i].mPsk),
static_cast<uint8_t>(strlen(mJoiners[i].mPsk))));
otLogInfoMeshCoP("found joiner, starting new session");
enableJoiner = true;
break;
}
}
mJoinerIid[0] ^= 0x2;
}
else
{
enableJoiner = (memcmp(mJoinerIid, joinerIid.GetIid(), sizeof(mJoinerIid)) == 0);
}
VerifyOrExit(mNetif.GetDtls().IsStarted() && memcmp(mJoinerIid, joinerIid.GetIid(), sizeof(mJoinerIid)) == 0,);
VerifyOrExit(enableJoiner, ;);
SuccessOrExit(error = mNetif.GetDtls().SetClientId(mJoinerIid, sizeof(mJoinerIid)));
mNetif.GetDtls().Receive(aMessage, offset, length);
aMessage.SetOffset(offset);
SuccessOrExit(error = aMessage.SetLength(offset + length));
joinerMessageInfo.SetPeerAddr(mNetif.GetMle().GetMeshLocal64());
joinerMessageInfo.GetPeerAddr().SetIid(mJoinerIid);
joinerMessageInfo.SetPeerPort(mJoinerPort);
mSecureCoapServer.Receive(aMessage, joinerMessageInfo);
exit:
(void)aMessageInfo;
@@ -728,10 +749,10 @@ void Commissioner::SendDatasetChangedResponse(const Coap::Header &aRequestHeader
otLogFuncEntry();
VerifyOrExit((message = mCoapServer.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
responseHeader.Init(kCoapTypeAcknowledgment, kCoapResponseChanged);
responseHeader.SetMessageId(aRequestHeader.GetMessageId());
responseHeader.SetToken(aRequestHeader.GetToken(), aRequestHeader.GetTokenLength());
responseHeader.SetDefaultResponseHeader(aRequestHeader);
responseHeader.SetPayloadMarker();
SuccessOrExit(error = message->Append(responseHeader.GetBytes(), responseHeader.GetLength()));
SuccessOrExit(error = mCoapServer.SendMessage(*message, aMessageInfo));
@@ -747,177 +768,22 @@ exit:
otLogFuncExit();
}
ThreadError Commissioner::HandleDtlsSend(void *aContext, const uint8_t *aBuf, uint16_t aLength)
void Commissioner::HandleJoinerFinalize(void *aContext, Coap::Header &aHeader,
Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
otLogInfoMeshCoP("Commissioner::HandleDtlsTransmit");
return static_cast<Commissioner *>(aContext)->HandleDtlsSend(aBuf, aLength);
static_cast<Commissioner *>(aContext)->HandleJoinerFinalize(aHeader, aMessage, aMessageInfo);
}
ThreadError Commissioner::HandleDtlsSend(const unsigned char *aBuf, uint16_t aLength)
void Commissioner::HandleJoinerFinalize(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
ThreadError error = kThreadError_None;
otLogFuncEntry();
if (mTransmitMessage == NULL)
{
Coap::Header header;
JoinerUdpPortTlv udpPort;
JoinerIidTlv iid;
JoinerRouterLocatorTlv rloc;
ExtendedTlv tlv;
header.Init(kCoapTypeNonConfirmable, kCoapRequestPost);
header.AppendUriPathOptions(OPENTHREAD_URI_RELAY_TX);
header.SetPayloadMarker();
VerifyOrExit((mTransmitMessage = mCoapClient.NewMessage(header)) != NULL, error = kThreadError_NoBufs);
udpPort.Init();
udpPort.SetUdpPort(mJoinerPort);
SuccessOrExit(error = mTransmitMessage->Append(&udpPort, sizeof(udpPort)));
iid.Init();
iid.SetIid(mJoinerIid);
SuccessOrExit(error = mTransmitMessage->Append(&iid, sizeof(iid)));
rloc.Init();
rloc.SetJoinerRouterLocator(mJoinerRloc);
SuccessOrExit(error = mTransmitMessage->Append(&rloc, sizeof(rloc)));
if (mSendKek)
{
JoinerRouterKekTlv kek;
kek.Init();
kek.SetKek(mNetif.GetKeyManager().GetKek());
SuccessOrExit(error = mTransmitMessage->Append(&kek, sizeof(kek)));
}
mTransmitMessage->SetOffset(mTransmitMessage->GetLength());
tlv.SetType(Tlv::kJoinerDtlsEncapsulation);
tlv.SetLength(0);
SuccessOrExit(error = mTransmitMessage->Append(&tlv, sizeof(tlv)));
}
VerifyOrExit(mTransmitMessage->Append(aBuf, aLength) == kThreadError_None, error = kThreadError_NoBufs);
mTransmitTask.Post();
exit:
if (error != kThreadError_None && mTransmitMessage != NULL)
{
mTransmitMessage->Free();
}
otLogFuncExitErr(error);
return error;
}
void Commissioner::HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength)
{
otLogInfoMeshCoP("Commissioner::HandleDtlsReceive");
static_cast<Commissioner *>(aContext)->HandleDtlsReceive(aBuf, aLength);
}
void Commissioner::HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength)
{
otLogFuncEntry();
ReceiveJoinerFinalize(aBuf, aLength);
otLogFuncExit();
}
void Commissioner::HandleUdpTransmit(void *aContext)
{
otLogInfoMeshCoP("Commissioner::HandleUdpTransmit");
static_cast<Commissioner *>(aContext)->HandleUdpTransmit();
}
void Commissioner::HandleUdpTransmit(void)
{
ThreadError error = kThreadError_None;
Ip6::MessageInfo messageInfo;
ExtendedTlv tlv;
otLogFuncEntry();
VerifyOrExit(mTransmitMessage != NULL, error = kThreadError_NoBufs);
tlv.SetType(Tlv::kJoinerDtlsEncapsulation);
tlv.SetLength(mTransmitMessage->GetLength() - mTransmitMessage->GetOffset() - sizeof(tlv));
mTransmitMessage->Write(mTransmitMessage->GetOffset(), sizeof(tlv), &tlv);
mTransmitMessage->SetOffset(0);
messageInfo.SetPeerAddr(mNetif.GetMle().GetMeshLocal16());
messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(mJoinerRloc);
messageInfo.SetPeerPort(kCoapUdpPort);
messageInfo.SetInterfaceId(mNetif.GetInterfaceId());
SuccessOrExit(error = mCoapClient.SendMessage(*mTransmitMessage, messageInfo));
exit:
if (error != kThreadError_None && mTransmitMessage != NULL)
{
mTransmitMessage->Free();
}
mTransmitMessage = NULL;
otLogFuncExit();
}
void Commissioner::ReceiveJoinerFinalize(uint8_t *buf, uint16_t length)
{
Message *message = NULL;
Coap::Header header;
char uriPath[Coap::Resource::kMaxReceivedUriPath] = "";
char *curUriPath = uriPath;
const Coap::Header::Option *coapOption;
(void)aMessageInfo;
StateTlv::State state = StateTlv::kAccept;
ProvisioningUrlTlv provisioningUrl;
otLogFuncEntry();
otLogInfoMeshCoP("receive joiner finalize");
otLogInfoMeshCoP("received joiner finalize");
VerifyOrExit((message = mNetif.GetIp6().mMessagePool.New(Message::kTypeIp6, 0)) != NULL, ;);
SuccessOrExit(message->Append(buf, length));
SuccessOrExit(header.FromMessage(*message));
SuccessOrExit(message->SetOffset(header.GetLength()));
coapOption = header.GetCurrentOption();
while (coapOption != NULL)
{
switch (coapOption->mNumber)
{
case kCoapOptionUriPath:
if (curUriPath != uriPath)
{
*curUriPath++ = '/';
}
VerifyOrExit(coapOption->mLength < sizeof(uriPath) - static_cast<size_t>(curUriPath + 1 - uriPath), ;);
memcpy(curUriPath, coapOption->mValue, coapOption->mLength);
curUriPath += coapOption->mLength;
break;
case kCoapOptionContentFormat:
break;
default:
ExitNow();
}
coapOption = header.GetNextOption();
}
curUriPath[0] = '\0';
VerifyOrExit(strcmp(uriPath, OPENTHREAD_URI_JOINER_FINALIZE) == 0,);
if (Tlv::GetTlv(*message, Tlv::kProvisioningUrl, sizeof(provisioningUrl), provisioningUrl) == kThreadError_None)
if (Tlv::GetTlv(aMessage, Tlv::kProvisioningUrl, sizeof(provisioningUrl), provisioningUrl) == kThreadError_None)
{
if (provisioningUrl.GetLength() != mNetif.GetDtls().mProvisioningUrl.GetLength() ||
memcmp(provisioningUrl.GetProvisioningUrl(), mNetif.GetDtls().mProvisioningUrl.GetProvisioningUrl(),
@@ -927,47 +793,125 @@ void Commissioner::ReceiveJoinerFinalize(uint8_t *buf, uint16_t length)
}
}
otDumpCertMeshCoP("[THCI] direction=recv | type=JOIN_FIN.req |", buf + header.GetLength(), length - header.GetLength());
otLogCertMeshCoP("[THCI] direction=recv | type=JOIN_FIN.req");
SendJoinFinalizeResponse(header, state);
SendJoinFinalizeResponse(aHeader, state);
otLogFuncExit();
}
void Commissioner::SendJoinFinalizeResponse(const Coap::Header &aRequestHeader, StateTlv::State aState)
{
ThreadError error = kThreadError_None;
Coap::Header responseHeader;
Ip6::MessageInfo joinerMessageInfo;
MeshCoP::StateTlv stateTlv;
Message *message;
otLogFuncEntry();
responseHeader.SetDefaultResponseHeader(aRequestHeader);
responseHeader.SetPayloadMarker();
VerifyOrExit((message = mSecureCoapServer.NewMessage(responseHeader)) != NULL, error = kThreadError_NoBufs);
stateTlv.Init();
stateTlv.SetState(aState);
SuccessOrExit(error = message->Append(&stateTlv, sizeof(stateTlv)));
joinerMessageInfo.SetPeerAddr(mNetif.GetMle().GetMeshLocal64());
joinerMessageInfo.GetPeerAddr().SetIid(mJoinerIid);
joinerMessageInfo.SetPeerPort(mJoinerPort);
mSendKek = true;
SuccessOrExit(error = mSecureCoapServer.SendMessage(*message, joinerMessageInfo));
otLogInfoMeshCoP("sent joiner finalize response");
otLogCertMeshCoP("[THCI] direction=send | type=JOIN_FIN.rsp");
exit:
if (message != NULL)
if (error != kThreadError_None && message != NULL)
{
mSendKek = false;
message->Free();
}
otLogFuncExit();
}
void Commissioner::SendJoinFinalizeResponse(const Coap::Header &aRequestHeader, StateTlv::State aState)
ThreadError Commissioner::SendRelayTransmit(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
Coap::Header responseHeader;
MeshCoP::StateTlv *stateTlv;
uint8_t buf[128];
uint8_t *cur = buf;
return static_cast<Commissioner *>(aContext)->SendRelayTransmit(aMessage, aMessageInfo);
}
ThreadError Commissioner::SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
(void)aMessageInfo;
ThreadError error = kThreadError_None;
Coap::Header header;
JoinerUdpPortTlv udpPort;
JoinerIidTlv iid;
JoinerRouterLocatorTlv rloc;
ExtendedTlv tlv;
Message *message;
uint16_t offset;
Ip6::MessageInfo messageInfo;
otLogFuncEntry();
responseHeader.Init(kCoapTypeAcknowledgment, kCoapResponseChanged);
responseHeader.SetMessageId(aRequestHeader.GetMessageId());
responseHeader.SetToken(aRequestHeader.GetToken(), aRequestHeader.GetTokenLength());
responseHeader.SetPayloadMarker();
memcpy(cur, responseHeader.GetBytes(), responseHeader.GetLength());
cur += responseHeader.GetLength();
stateTlv = reinterpret_cast<MeshCoP::StateTlv *>(cur);
stateTlv->Init();
stateTlv->SetState(aState);
cur += sizeof(*stateTlv);
header.Init(kCoapTypeNonConfirmable, kCoapRequestPost);
header.AppendUriPathOptions(OPENTHREAD_URI_RELAY_TX);
header.SetPayloadMarker();
mSendKek = true;
mNetif.GetDtls().Send(buf, static_cast<uint16_t>(cur - buf));
mSendKek = false;
VerifyOrExit((message = mCoapClient.NewMessage(header)) != NULL, error = kThreadError_NoBufs);
otLogInfoMeshCoP("sent joiner finalize response");
otLogCertMeshCoP("[THCI] direction=send | type=JOIN_FIN.rsp");
otLogFuncExit();
udpPort.Init();
udpPort.SetUdpPort(mJoinerPort);
SuccessOrExit(error = message->Append(&udpPort, sizeof(udpPort)));
iid.Init();
iid.SetIid(mJoinerIid);
SuccessOrExit(error = message->Append(&iid, sizeof(iid)));
rloc.Init();
rloc.SetJoinerRouterLocator(mJoinerRloc);
SuccessOrExit(error = message->Append(&rloc, sizeof(rloc)));
if (mSendKek)
{
JoinerRouterKekTlv kek;
kek.Init();
kek.SetKek(mNetif.GetKeyManager().GetKek());
SuccessOrExit(error = message->Append(&kek, sizeof(kek)));
mSendKek = false;
}
tlv.SetType(Tlv::kJoinerDtlsEncapsulation);
tlv.SetLength(aMessage.GetLength());
SuccessOrExit(error = message->Append(&tlv, sizeof(tlv)));
offset = message->GetLength();
message->SetLength(offset + aMessage.GetLength());
aMessage.CopyTo(0, offset, aMessage.GetLength(), *message);
messageInfo.SetPeerAddr(mNetif.GetMle().GetMeshLocal16());
messageInfo.GetPeerAddr().mFields.m16[7] = HostSwap16(mJoinerRloc);
messageInfo.SetPeerPort(kCoapUdpPort);
messageInfo.SetInterfaceId(mNetif.GetInterfaceId());
SuccessOrExit(error = mCoapClient.SendMessage(*message, messageInfo));
aMessage.Free();
exit:
if (error != kThreadError_None && message != NULL)
{
message->Free();
}
otLogFuncExitErr(error);
return error;
}
} // namespace MeshCoP
+9 -11
View File
@@ -38,6 +38,7 @@
#include <coap/coap_client.hpp>
#include <coap/coap_server.hpp>
#include <coap/secure_coap_server.hpp>
#include <common/timer.hpp>
#include <mac/mac_frame.hpp>
#include <meshcop/announce_begin_client.hpp>
@@ -210,18 +211,15 @@ private:
Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void HandleDatasetChanged(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength);
void HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength);
static void HandleJoinerFinalize(void *aContext, Coap::Header &aHeader,
Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void HandleJoinerFinalize(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static ThreadError HandleDtlsSend(void *aContext, const uint8_t *aBuf, uint16_t aLength);
ThreadError HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength);
static void HandleUdpTransmit(void *aContext);
void HandleUdpTransmit(void);
void ReceiveJoinerFinalize(uint8_t *buf, uint16_t length);
void SendJoinFinalizeResponse(const Coap::Header &aRequestHeader, StateTlv::State aState);
static ThreadError SendRelayTransmit(void *aContext, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
ThreadError SendRelayTransmit(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void SendDatasetChangedResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aMessageInfo);
ThreadError SendCommissionerSet(void);
ThreadError SendPetition(void);
@@ -247,16 +245,16 @@ private:
uint16_t mJoinerRloc;
uint16_t mSessionId;
Message *mTransmitMessage;
Timer mTimer;
Tasklet mTransmitTask;
uint8_t mTransmitAttempts;
bool mSendKek;
Coap::Resource mRelayReceive;
Coap::Resource mDatasetChanged;
Coap::Resource mJoinerFinalize;
Coap::Server &mCoapServer;
Coap::Client &mCoapClient;
Coap::SecureServer &mSecureCoapServer;
ThreadNetif &mNetif;
};
+14 -3
View File
@@ -168,10 +168,21 @@ bool Dtls::IsConnected(void)
return mSsl.state == MBEDTLS_SSL_HANDSHAKE_OVER;
}
ThreadError Dtls::Send(const uint8_t *aBuf, uint16_t aLength)
ThreadError Dtls::Send(Message &aMessage, uint16_t aLength)
{
int rval = mbedtls_ssl_write(&mSsl, aBuf, aLength);
return MapError(rval);
ThreadError error = kThreadError_None;
uint8_t buffer[kApplicationDataMaxLength];
VerifyOrExit(aLength <= kApplicationDataMaxLength, error = kThreadError_NoBufs);
aMessage.Read(0, aLength, buffer);
SuccessOrExit(error = MapError(mbedtls_ssl_write(&mSsl, buffer, aLength)));
aMessage.Free();
exit:
return error;
}
ThreadError Dtls::Receive(Message &aMessage, uint16_t aOffset, uint16_t aLength)
+6 -4
View File
@@ -59,6 +59,7 @@ public:
enum
{
kPskMaxLength = 32,
kApplicationDataMaxLength = 128,
};
/**
@@ -152,13 +153,14 @@ public:
/**
* This method sends data within the DTLS session.
*
* @param[in] aBuf A pointer to the data buffer.
* @param[in] aLength Number of bytes in the data buffer.
* @param[in] aMessage A message to send via DTLS.
* @param[in] aLength Number of bytes in the data buffer.
*
* @retval kThreadError_None Successfully sent the data via the DTLS session.
* @retval kThreadError_None Successfully sent the data via the DTLS session.
* @retval kThreadError_NoBufs A message is too long.
*
*/
ThreadError Send(const uint8_t *aBuf, uint16_t aLength);
ThreadError Send(Message &aMessage, uint16_t aLength);
/**
* This method provides a received DTLS message to the DTLS object.
+73 -165
View File
@@ -59,12 +59,13 @@ namespace Thread {
namespace MeshCoP {
Joiner::Joiner(ThreadNetif &aNetif):
mTransmitMessage(NULL),
mSocket(aNetif.GetIp6().mUdp),
mTransmitTask(aNetif.GetIp6().mTaskletScheduler, &Joiner::HandleUdpTransmit, this),
mJoinerRouterChannel(0),
mJoinerRouterPanId(0),
mJoinerUdpPort(0),
mTimer(aNetif.GetIp6().mTimerScheduler, &Joiner::HandleTimer, this),
mJoinerEntrust(OPENTHREAD_URI_JOINER_ENTRUST, &Joiner::HandleJoinerEntrust, this),
mCoapServer(aNetif.GetCoapServer()),
mSecureCoapClient(aNetif.GetSecureCoapClient()),
mNetif(aNetif)
{
mCoapServer.AddResource(mJoinerEntrust);
@@ -82,9 +83,9 @@ ThreadError Joiner::Start(const char *aPSKd, const char *aProvisioningUrl)
mNetif.GetMac().SetExtAddress(extAddress);
mNetif.GetMle().UpdateLinkLocalAddress();
SuccessOrExit(error = mNetif.GetDtls().SetPsk(reinterpret_cast<const uint8_t *>(aPSKd),
static_cast<uint8_t>(strlen(aPSKd))));
SuccessOrExit(error = mNetif.GetDtls().mProvisioningUrl.SetProvisioningUrl(aProvisioningUrl));
SuccessOrExit(error = mSecureCoapClient.GetDtls().SetPsk(reinterpret_cast<const uint8_t *>(aPSKd),
static_cast<uint8_t>(strlen(aPSKd))));
SuccessOrExit(error = mSecureCoapClient.GetDtls().mProvisioningUrl.SetProvisioningUrl(aProvisioningUrl));
mJoinerRouterPanId = Mac::kPanIdBroadcast;
SuccessOrExit(error = mNetif.GetMle().Discover(0, 0, mNetif.GetMac().GetPanId(), HandleDiscoverResult, this));
@@ -97,13 +98,23 @@ exit:
ThreadError Joiner::Stop(void)
{
otLogFuncEntry();
mNetif.GetIp6Filter().RemoveUnsecurePort(mSocket.GetSockName().mPort);
mSocket.Close();
mNetif.GetDtls().Stop();
Close();
otLogFuncExit();
return kThreadError_None;
}
void Joiner::Close(void)
{
otLogFuncEntry();
mSecureCoapClient.Disconnect();
mNetif.GetIp6Filter().RemoveUnsecurePort(mSecureCoapClient.GetPort());
otLogFuncExit();
}
void Joiner::HandleDiscoverResult(otActiveScanResult *aResult, void *aContext)
{
static_cast<Joiner *>(aContext)->HandleDiscoverResult(aResult);
@@ -111,6 +122,10 @@ void Joiner::HandleDiscoverResult(otActiveScanResult *aResult, void *aContext)
void Joiner::HandleDiscoverResult(otActiveScanResult *aResult)
{
Ip6::MessageInfo messageInfo;
otLogFuncEntry();
if (aResult != NULL)
{
otLogFuncEntryMsg("aResult = %llX", HostSwap64(*reinterpret_cast<uint64_t *>(&aResult->mExtAddress)));
@@ -148,196 +163,92 @@ void Joiner::HandleDiscoverResult(otActiveScanResult *aResult)
{
otLogFuncEntryMsg("aResult = NULL");
// open UDP port
Ip6::SockAddr sockaddr;
sockaddr.mPort = mJoinerUdpPort;
mSocket.Open(&Joiner::HandleUdpReceive, this);
mSocket.Bind(sockaddr);
mNetif.GetMac().SetPanId(mJoinerRouterPanId);
mNetif.GetMac().SetChannel(mJoinerRouterChannel);
mNetif.GetIp6Filter().AddUnsecurePort(sockaddr.mPort);
mNetif.GetIp6Filter().AddUnsecurePort(mSecureCoapClient.GetPort());
mNetif.GetDtls().Start(true, HandleDtlsReceive, HandleDtlsSend, this);
messageInfo.GetPeerAddr().mFields.m16[0] = HostSwap16(0xfe80);
messageInfo.GetPeerAddr().SetIid(mJoinerRouter);
messageInfo.mPeerPort = mJoinerUdpPort;
messageInfo.mInterfaceId = OT_NETIF_INTERFACE_ID_THREAD;
mSecureCoapClient.Connect(messageInfo, Joiner::HandleSecureCoapClientConnect, this);
}
otLogFuncExit();
}
ThreadError Joiner::HandleDtlsSend(void *aContext, const uint8_t *aBuf, uint16_t aLength)
void Joiner::HandleSecureCoapClientConnect(void *aContext)
{
otLogInfoMeshCoP("Joiner::HandleDtlsTransmit");
return static_cast<Joiner *>(aContext)->HandleDtlsSend(aBuf, aLength);
}
ThreadError Joiner::HandleDtlsSend(const unsigned char *aBuf, uint16_t aLength)
{
ThreadError error = kThreadError_None;
otLogFuncEntry();
if (mTransmitMessage == NULL)
{
VerifyOrExit((mTransmitMessage = mSocket.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
mTransmitMessage->SetLinkSecurityEnabled(false);
}
VerifyOrExit(mTransmitMessage->Append(aBuf, aLength) == kThreadError_None, error = kThreadError_NoBufs);
mTransmitTask.Post();
exit:
if (error != kThreadError_None && mTransmitMessage != NULL)
{
mTransmitMessage->Free();
}
otLogFuncExitErr(error);
return error;
}
void Joiner::HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength)
{
otLogInfoMeshCoP("Joiner::HandleDtlsReceive");
static_cast<Joiner *>(aContext)->HandleDtlsReceive(aBuf, aLength);
}
void Joiner::HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength)
{
ReceiveJoinerFinalizeResponse(aBuf, aLength);
}
void Joiner::HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo)
{
otLogInfoMeshCoP("Joiner::HandleUdpReceive");
static_cast<Joiner *>(aContext)->HandleUdpReceive(*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
void Joiner::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
otLogFuncEntry();
(void)aMessageInfo;
mNetif.GetDtls().Receive(aMessage, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset());
if (mNetif.GetDtls().IsConnected())
{
SendJoinerFinalize();
}
otLogFuncExit();
}
void Joiner::HandleUdpTransmit(void *aContext)
{
otLogInfoMeshCoP("Joiner::HandleUdpTransmit");
static_cast<Joiner *>(aContext)->HandleUdpTransmit();
}
void Joiner::HandleUdpTransmit(void)
{
ThreadError error = kThreadError_None;
Ip6::MessageInfo messageInfo;
otLogFuncEntry();
VerifyOrExit(mTransmitMessage != NULL, error = kThreadError_NoBufs);
otLogInfoMeshCoP("transmit %d (to %llX)", mTransmitMessage->GetLength(),
HostSwap64(*reinterpret_cast<uint64_t *>(&mJoinerRouter)));
messageInfo.GetPeerAddr().mFields.m16[0] = HostSwap16(0xfe80);
messageInfo.GetPeerAddr().SetIid(mJoinerRouter);
messageInfo.SetPeerPort(mJoinerUdpPort);
messageInfo.SetInterfaceId(OT_NETIF_INTERFACE_ID_THREAD);
SuccessOrExit(error = mSocket.SendTo(*mTransmitMessage, messageInfo));
exit:
if (error != kThreadError_None && mTransmitMessage != NULL)
{
mTransmitMessage->Free();
}
mTransmitMessage = NULL;
otLogFuncExit();
static_cast<Joiner *>(aContext)->SendJoinerFinalize();
}
void Joiner::SendJoinerFinalize(void)
{
Coap::Header header;
StateTlv *stateTlv;
ThreadError error = kThreadError_None;
Message *message = NULL;
StateTlv stateTlv;
uint8_t length;
uint8_t buf[128];
uint8_t *cur = buf;
otLogFuncEntry();
header.Init(kCoapTypeConfirmable, kCoapRequestPost);
header.SetMessageId(0);
header.SetToken(NULL, 0);
header.AppendUriPathOptions(OPENTHREAD_URI_JOINER_FINALIZE);
header.SetPayloadMarker();
memcpy(cur, header.GetBytes(), header.GetLength());
cur += header.GetLength();
stateTlv = reinterpret_cast<MeshCoP::StateTlv *>(cur);
stateTlv->Init();
stateTlv->SetState(MeshCoP::StateTlv::kAccept);
cur += sizeof(*stateTlv);
VerifyOrExit((message = mSecureCoapClient.NewMessage(header)) != NULL, error = kThreadError_NoBufs);
length = mNetif.GetDtls().mProvisioningUrl.GetLength();
stateTlv.Init();
stateTlv.SetState(MeshCoP::StateTlv::kAccept);
SuccessOrExit(error = message->Append(&stateTlv, sizeof(stateTlv)));
length = mSecureCoapClient.GetDtls().mProvisioningUrl.GetLength();
if (length > 0)
{
length += sizeof(Tlv);
memcpy(cur, &mNetif.GetDtls().mProvisioningUrl, length);
cur += length;
SuccessOrExit(error = message->Append(&stateTlv, length + sizeof(Tlv)));
}
mNetif.GetDtls().Send(buf, static_cast<uint16_t>(cur - buf));
mSecureCoapClient.SendMessage(*message, Joiner::HandleJoinerFinalizeResponse, this);
otLogInfoMeshCoP("Sent joiner finalize");
otDumpCertMeshCoP("[THCI] direction=send | type=JOIN_FIN.req |", buf + header.GetLength(),
cur - buf - header.GetLength());
otLogCertMeshCoP("[THCI] direction=send | type=JOIN_FIN.req");
exit:
if (error != kThreadError_None && message != NULL)
{
message->Free();
}
otLogFuncExit();
}
void Joiner::ReceiveJoinerFinalizeResponse(uint8_t *buf, uint16_t length)
void Joiner::HandleJoinerFinalizeResponse(void *aContext, otCoapHeader *aHeader,
otMessage aMessage, ThreadError result)
{
static_cast<Joiner *>(aContext)->HandleJoinerFinalizeResponse(
static_cast<Coap::Header *>(aHeader), static_cast<Message *>(aMessage), result);
}
void Joiner::HandleJoinerFinalizeResponse(Coap::Header *aHeader, Message *aMessage, ThreadError result)
{
Message *message = NULL;
Coap::Header header;
StateTlv state;
otLogFuncEntry();
VerifyOrExit((message = mNetif.GetIp6().mMessagePool.New(Message::kTypeIp6, 0)) != NULL, ;);
SuccessOrExit(message->Append(buf, length));
SuccessOrExit(header.FromMessage(*message));
SuccessOrExit(message->SetOffset(header.GetLength()));
VerifyOrExit(result == kThreadError_None &&
aHeader->GetType() == kCoapTypeAcknowledgment &&
aHeader->GetCode() == kCoapResponseChanged, ;);
VerifyOrExit(header.GetType() == kCoapTypeAcknowledgment &&
header.GetCode() == kCoapResponseChanged &&
header.GetMessageId() == 0 &&
header.GetTokenLength() == 0, ;);
SuccessOrExit(Tlv::GetTlv(*message, Tlv::kState, sizeof(state), state));
SuccessOrExit(Tlv::GetTlv(*aMessage, Tlv::kState, sizeof(state), state));
VerifyOrExit(state.IsValid(), ;);
otLogInfoMeshCoP("received joiner finalize response %d", static_cast<uint8_t>(state.GetState()));
otLogCertMeshCoP("[THCI] direction=recv | type=JOIN_FIN.rsp");
Close();
exit:
if (message != NULL)
{
message->Free();
}
Close();
otLogFuncExit();
}
@@ -400,13 +311,15 @@ exit:
void Joiner::SendJoinerEntrustResponse(const Coap::Header &aRequestHeader,
const Ip6::MessageInfo &aRequestInfo)
{
ThreadError error = kThreadError_None;
Message *message;
Coap::Header responseHeader;
Ip6::MessageInfo responseInfo(aRequestInfo);
otLogFuncEntry();
VerifyOrExit((message = mCoapServer.NewMessage(0)) != NULL, error = kThreadError_NoBufs);
message->SetSubType(Message::kSubTypeJoinerEntrust);
responseHeader.SetDefaultResponseHeader(aRequestHeader);
@@ -415,7 +328,7 @@ void Joiner::SendJoinerEntrustResponse(const Coap::Header &aRequestHeader,
memset(&responseInfo.mSockAddr, 0, sizeof(responseInfo.mSockAddr));
SuccessOrExit(error = mCoapServer.SendMessage(*message, responseInfo));
otLogInfoArp("Sent address notification acknowledgment");
otLogInfoArp("Sent Joiner Entrust response");
exit:
@@ -423,6 +336,8 @@ exit:
{
message->Free();
}
otLogFuncExit();
}
void Joiner::HandleTimer(void *aContext)
@@ -443,12 +358,5 @@ void Joiner::HandleTimer(void)
mNetif.GetMle().UpdateLinkLocalAddress();
}
void Joiner::Close(void)
{
otLogFuncEntry();
mNetif.GetDtls().Stop();
otLogFuncExit();
}
} // namespace Dtls
} // namespace MeshCoP
} // namespace Thread
+13 -22
View File
@@ -38,6 +38,7 @@
#include <coap/coap_header.hpp>
#include <coap/coap_server.hpp>
#include <coap/secure_coap_client.hpp>
#include <common/message.hpp>
#include <net/udp6.hpp>
#include <meshcop/dtls.hpp>
@@ -88,42 +89,32 @@ private:
static void HandleDiscoverResult(otActiveScanResult *aResult, void *aContext);
void HandleDiscoverResult(otActiveScanResult *aResult);
static void HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength);
void HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength);
static ThreadError HandleDtlsSend(void *aContext, const uint8_t *aBuf, uint16_t aLength);
ThreadError HandleDtlsSend(const uint8_t *aBuf, uint16_t aLength);
static void HandleUdpReceive(void *aContext, otMessage aMessage, const otMessageInfo *aMessageInfo);
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static void HandleUdpTransmit(void *aContext);
void HandleUdpTransmit(void);
static void HandleJoinerEntrust(void *aContext, Coap::Header &aHeader,
Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void HandleJoinerEntrust(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void SendJoinerEntrustResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aRequestInfo);
static void HandleTimer(void *aContext);
void HandleTimer(void);
void Close(void);
void ReceiveJoinerFinalizeResponse(uint8_t *buf, uint16_t length);
static void HandleSecureCoapClientConnect(void *aContext);
void SendJoinerFinalize(void);
static void HandleJoinerFinalizeResponse(void *aContext, otCoapHeader *aHeader,
otMessage aMessage, ThreadError result);
void HandleJoinerFinalizeResponse(Coap::Header *aHeader, Message *aMessage, ThreadError result);
static void HandleJoinerEntrust(void *aContext, Coap::Header &aHeader,
Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void HandleJoinerEntrust(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void SendJoinerEntrustResponse(const Coap::Header &aRequestHeader, const Ip6::MessageInfo &aRequestInfo);
uint8_t mJoinerRouterChannel;
uint16_t mJoinerRouterPanId;
uint16_t mJoinerUdpPort;
Mac::ExtAddress mJoinerRouter;
Message *mTransmitMessage;
Ip6::UdpSocket mSocket;
Tasklet mTransmitTask;
Timer mTimer;
Coap::Resource mJoinerEntrust;
Coap::Server &mCoapServer;
Coap::SecureClient &mSecureCoapClient;
ThreadNetif &mNetif;
};
+9 -1
View File
@@ -75,12 +75,14 @@ ThreadNetif::ThreadNetif(Ip6::Ip6 &aIp6):
mNetworkDataLeader(*this),
mNetworkDiagnostic(*this),
#if OPENTHREAD_ENABLE_COMMISSIONER
mSecureCoapServer(*this, OPENTHREAD_CONFIG_JOINER_UDP_PORT),
mCommissioner(*this),
#endif // OPENTHREAD_ENABLE_COMMISSIONER
#if OPENTHREAD_ENABLE_DTLS
mDtls(*this),
#endif
#if OPENTHREAD_ENABLE_JOINER
mSecureCoapClient(*this),
mJoiner(*this),
#endif // OPENTHREAD_ENABLE_JOINER
#if OPENTHREAD_ENABLE_JAM_DETECTION
@@ -103,11 +105,14 @@ ThreadError ThreadNetif::Up(void)
mIp6.AddNetif(*this);
mMeshForwarder.Start();
mCoapServer.Start();
mCoapClient.Start();
#if OPENTHREAD_ENABLE_JOINER
mSecureCoapClient.Start();
#endif
mMleRouter.Enable();
mIsUp = true;
}
mCoapClient.Start();
return kThreadError_None;
}
@@ -115,6 +120,9 @@ ThreadError ThreadNetif::Down(void)
{
mCoapServer.Stop();
mCoapClient.Stop();
#if OPENTHREAD_ENABLE_JOINER
mSecureCoapClient.Stop();
#endif
mMleRouter.Disable();
mMeshForwarder.Stop();
mIp6.RemoveNetif(*this);
+8
View File
@@ -44,6 +44,8 @@
#include <coap/coap_server.hpp>
#include <coap/coap_client.hpp>
#include <coap/secure_coap_client.hpp>
#include <coap/secure_coap_server.hpp>
#include <mac/mac.hpp>
#include <meshcop/joiner_router.hpp>
#include <meshcop/leader.hpp>
@@ -282,6 +284,8 @@ public:
#if OPENTHREAD_ENABLE_COMMISSIONER
MeshCoP::Commissioner &GetCommissioner(void) { return mCommissioner; }
Coap::SecureServer &GetSecureCoapServer(void) { return mSecureCoapServer; }
#endif // OPENTHREAD_ENABLE_COMMISSIONER
#if OPENTHREAD_ENABLE_DTLS
@@ -290,6 +294,8 @@ public:
#if OPENTHREAD_ENABLE_JOINER
MeshCoP::Joiner &GetJoiner(void) { return mJoiner; }
Coap::SecureClient &GetSecureCoapClient(void) { return mSecureCoapClient; }
#endif // OPENTHREAD_ENABLE_JOINER
#if OPENTHREAD_ENABLE_JAM_DETECTION
@@ -334,6 +340,7 @@ private:
bool mIsUp;
#if OPENTHREAD_ENABLE_COMMISSIONER
Coap::SecureServer mSecureCoapServer;
MeshCoP::Commissioner mCommissioner;
#endif // OPENTHREAD_ENABLE_COMMISSIONER
@@ -342,6 +349,7 @@ private:
#endif// OPENTHREAD_ENABLE_DTLS
#if OPENTHREAD_ENABLE_JOINER
Coap::SecureClient mSecureCoapClient;
MeshCoP::Joiner mJoiner;
#endif // OPENTHREAD_ENABLE_JOINER