Add multi connection support in secure session manager
diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 0e23ebb..5ea4ed1 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp
@@ -51,15 +51,16 @@ ChipDeviceController::ChipDeviceController() { - mState = kState_NotInitialized; - AppState = NULL; - mConState = kConnectionState_NotConnected; - mDeviceCon = NULL; - mCurReqMsg = NULL; - mOnError = NULL; - mDeviceAddr = IPAddress::Any; - mDevicePort = CHIP_PORT; - mLocalDeviceId = 0; + mState = kState_NotInitialized; + AppState = NULL; + mConState = kConnectionState_NotConnected; + mSessionManager = NULL; + mCurReqMsg = NULL; + mOnError = NULL; + mOnNewConnection = NULL; + mDeviceAddr = IPAddress::Any; + mDevicePort = CHIP_PORT; + mLocalDeviceId = 0; memset(&mOnComplete, 0, sizeof(mOnComplete)); } @@ -105,10 +106,10 @@ CHIP_ERROR err = CHIP_NO_ERROR; mState = kState_NotInitialized; - if (mDeviceCon != NULL) + if (mSessionManager != NULL) { - delete mDeviceCon; - mDeviceCon = NULL; + delete mSessionManager; + mSessionManager = NULL; } mSystemLayer->Shutdown(); mInetLayer->Shutdown(); @@ -119,36 +120,41 @@ mConState = kConnectionState_NotConnected; memset(&mOnComplete, 0, sizeof(mOnComplete)); - mOnError = NULL; - mMessageNumber = 0; + mOnError = NULL; + mOnNewConnection = NULL; + mMessageNumber = 0; mRemoteDeviceId.ClearValue(); return err; } CHIP_ERROR ChipDeviceController::ConnectDevice(NodeId remoteDeviceId, IPAddress deviceAddr, void * appReqState, - MessageReceiveHandler onMessageReceived, ErrorHandler onError, uint16_t devicePort) + NewConnectionHandler onConnected, MessageReceiveHandler onMessageReceived, + ErrorHandler onError, uint16_t devicePort) { CHIP_ERROR err = CHIP_NO_ERROR; - if (mState != kState_Initialized || mDeviceCon != NULL || mConState != kConnectionState_NotConnected) + if (mState != kState_Initialized || mSessionManager != NULL || mConState != kConnectionState_NotConnected) { return CHIP_ERROR_INCORRECT_STATE; } - mRemoteDeviceId = Optional<NodeId>::Value(remoteDeviceId); - mDeviceAddr = deviceAddr; - mDevicePort = devicePort; - mAppReqState = appReqState; - mDeviceCon = new SecureSessionMgr(); + mRemoteDeviceId = Optional<NodeId>::Value(remoteDeviceId); + mDeviceAddr = deviceAddr; + mDevicePort = devicePort; + mAppReqState = appReqState; + mOnNewConnection = onConnected; - err = mDeviceCon->Init(mLocalDeviceId, mInetLayer, Transport::UdpListenParameters().SetAddressType(deviceAddr.Type())); + mSessionManager = new SecureSessionMgr(); + + err = mSessionManager->Init(mLocalDeviceId, mInetLayer, Transport::UdpListenParameters().SetAddressType(deviceAddr.Type())); SuccessOrExit(err); - err = mDeviceCon->Connect(remoteDeviceId, Transport::PeerAddress::UDP(deviceAddr, devicePort)); - SuccessOrExit(err); + mSessionManager->SetMessageReceiveHandler(OnReceiveMessage, this); + mSessionManager->SetNewConnectionHandler(OnNewConnection, this); - mDeviceCon->SetMessageReceiveHandler(OnReceiveMessage, this); + err = mSessionManager->Connect(remoteDeviceId, Transport::PeerAddress::UDP(deviceAddr, devicePort)); + SuccessOrExit(err); mOnComplete.Response = onMessageReceived; mOnError = onError; @@ -160,26 +166,28 @@ if (err != CHIP_NO_ERROR) { - if (mDeviceCon != NULL) + if (mSessionManager != NULL) { - delete mDeviceCon; - mDeviceCon = NULL; + delete mSessionManager; + mSessionManager = NULL; } } return err; } -CHIP_ERROR ChipDeviceController::ManualKeyExchange(const unsigned char * remote_public_key, const size_t public_key_length, - const unsigned char * local_private_key, const size_t private_key_length) +CHIP_ERROR ChipDeviceController::ManualKeyExchange(Transport::PeerConnectionState * state, const unsigned char * remote_public_key, + const size_t public_key_length, const unsigned char * local_private_key, + const size_t private_key_length) { CHIP_ERROR err = CHIP_NO_ERROR; - if (!IsConnected() || mDeviceCon == NULL) + if (!IsConnected() || mSessionManager == NULL) { return CHIP_ERROR_INCORRECT_STATE; } - err = mDeviceCon->ManualKeyExchange(remote_public_key, public_key_length, local_private_key, private_key_length); + err = state->GetSecureSession().TemporaryManualKeyExchange(remote_public_key, public_key_length, local_private_key, + private_key_length); SuccessOrExit(err); mConState = kConnectionState_SecureConnected; @@ -220,9 +228,9 @@ return CHIP_ERROR_INCORRECT_STATE; } - delete mDeviceCon; - mDeviceCon = NULL; - mConState = kConnectionState_NotConnected; + delete mSessionManager; + mSessionManager = NULL; + mConState = kConnectionState_NotConnected; return err; }; @@ -235,7 +243,7 @@ mAppReqState = appReqState; VerifyOrExit(IsSecurelyConnected(), err = CHIP_ERROR_INCORRECT_STATE); - err = mDeviceCon->SendMessage(mRemoteDeviceId.Value(), buffer); + err = mSessionManager->SendMessage(mRemoteDeviceId.Value(), buffer); exit: return err; @@ -322,7 +330,15 @@ } } -void ChipDeviceController::OnReceiveMessage(const MessageHeader & header, const IPPacketInfo & pktInfo, +void ChipDeviceController::OnNewConnection(Transport::PeerConnectionState * state, ChipDeviceController * mgr) +{ + if (mgr->mOnNewConnection) + { + mgr->mOnNewConnection(mgr, state, mgr->mAppReqState); + } +} + +void ChipDeviceController::OnReceiveMessage(const MessageHeader & header, Transport::PeerConnectionState * state, System::PacketBuffer * msgBuf, ChipDeviceController * mgr) { if (header.GetSourceNodeId().HasValue()) @@ -339,7 +355,7 @@ } if (mgr->IsSecurelyConnected() && mgr->mOnComplete.Response != NULL) { - mgr->mOnComplete.Response(mgr, mgr->mAppReqState, msgBuf, &pktInfo); + mgr->mOnComplete.Response(mgr, mgr->mAppReqState, msgBuf); } }
diff --git a/src/controller/CHIPDeviceController.h b/src/controller/CHIPDeviceController.h index 510d79f..ab8ef9b 100644 --- a/src/controller/CHIPDeviceController.h +++ b/src/controller/CHIPDeviceController.h
@@ -41,11 +41,12 @@ class ChipDeviceController; extern "C" { +typedef void (*NewConnectionHandler)(ChipDeviceController * deviceController, Transport::PeerConnectionState * state, + void * appReqState); typedef void (*CompleteHandler)(ChipDeviceController * deviceController, void * appReqState); typedef void (*ErrorHandler)(ChipDeviceController * deviceController, void * appReqState, CHIP_ERROR err, const IPPacketInfo * pktInfo); -typedef void (*MessageReceiveHandler)(ChipDeviceController * deviceController, void * appReqState, System::PacketBuffer * payload, - const IPPacketInfo * pktInfo); +typedef void (*MessageReceiveHandler)(ChipDeviceController * deviceController, void * appReqState, System::PacketBuffer * payload); }; class DLL_EXPORT ChipDeviceController @@ -66,12 +67,13 @@ * @param[in] remoteDeviceId The remote device Id. * @param[in] deviceAddr The IPAddress of the requested Device * @param[in] appReqState Application specific context to be passed back when a message is received or on error + * @param[in] onConnected Callback for when the connection is established * @param[in] onMessageReceived Callback for when a message is received * @param[in] onError Callback for when an error occurs * @param[in] devicePort [Optional] The CHIP Device's port, defaults to CHIP_PORT * @return CHIP_ERROR The connection status */ - CHIP_ERROR ConnectDevice(NodeId remoteDeviceId, IPAddress deviceAddr, void * appReqState, + CHIP_ERROR ConnectDevice(NodeId remoteDeviceId, IPAddress deviceAddr, void * appReqState, NewConnectionHandler onConnected, MessageReceiveHandler onMessageReceived, ErrorHandler onError, uint16_t devicePort = CHIP_PORT); /** @@ -80,14 +82,16 @@ * until we have automatic key exchange in place. The function is useful only for * example applications for now. It will eventually be removed. * + * @param state Peer connection for which to establish the key * @param remote_public_key A pointer to peer's public key * @param public_key_length Length of remote_public_key * @param local_private_key A pointer to local private key * @param private_key_length Length of local_private_key * @return CHIP_ERROR The result of key derivation */ - CHIP_ERROR ManualKeyExchange(const unsigned char * remote_public_key, const size_t public_key_length, - const unsigned char * local_private_key, const size_t private_key_length); + CHIP_ERROR ManualKeyExchange(Transport::PeerConnectionState * state, const unsigned char * remote_public_key, + const size_t public_key_length, const unsigned char * local_private_key, + const size_t private_key_length); /** * @brief @@ -168,7 +172,11 @@ System::Layer * mSystemLayer; Inet::InetLayer * mInetLayer; - SecureSessionMgr * mDeviceCon; + + // TODO: CHIPDeviceController assumes a single device connection, where as + // session manager handles multiple connections. Need to finalize design on this + // as otherwise a single connection may end up processing data from other peers. + SecureSessionMgr * mSessionManager; ConnectionState mConState; void * mAppReqState; @@ -180,6 +188,7 @@ } mOnComplete; ErrorHandler mOnError; + NewConnectionHandler mOnNewConnection; System::PacketBuffer * mCurReqMsg; NodeId mLocalDeviceId; @@ -191,8 +200,10 @@ void ClearRequestState(); void ClearOpState(); - static void OnReceiveMessage(const MessageHeader & header, const IPPacketInfo & pktInfo, System::PacketBuffer * msgBuf, - ChipDeviceController * controller); + static void OnNewConnection(Transport::PeerConnectionState * state, ChipDeviceController * controller); + + static void OnReceiveMessage(const MessageHeader & header, Transport::PeerConnectionState * state, + System::PacketBuffer * msgBuf, ChipDeviceController * controller); }; } // namespace DeviceController
diff --git a/src/transport/SecureSession.cpp b/src/transport/SecureSession.cpp index ca776f0..21053d5 100644 --- a/src/transport/SecureSession.cpp +++ b/src/transport/SecureSession.cpp
@@ -31,6 +31,12 @@ namespace chip { +namespace { + +const char * kManualKeyExchangeChannelInfo = "Manual Key Exchanged Channel"; + +} // namespace + using namespace Crypto; SecureSession::SecureSession() : mKeyAvailable(false), mNextIV(0) {} @@ -116,4 +122,18 @@ return error; } +CHIP_ERROR SecureSession::TemporaryManualKeyExchange(const unsigned char * remote_public_key, const size_t public_key_length, + const unsigned char * local_private_key, const size_t private_key_length) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + size_t info_len = strlen(kManualKeyExchangeChannelInfo); + + err = Init(remote_public_key, public_key_length, local_private_key, private_key_length, NULL, 0, + (const unsigned char *) kManualKeyExchangeChannelInfo, info_len); + SuccessOrExit(err); + +exit: + return err; +} + } // namespace chip
diff --git a/src/transport/SecureSession.h b/src/transport/SecureSession.h index 609d6e6..65ee9d7 100644 --- a/src/transport/SecureSession.h +++ b/src/transport/SecureSession.h
@@ -93,6 +93,22 @@ */ void Reset(void); + /** + * @brief + * The keypair for the secure channel. This is a utility function that will be used + * until we have automatic key exchange in place. The function is useful only for + * example applications for now. It will eventually be removed. + * + * @param remote_public_key A pointer to peer's public key + * @param public_key_length Length of remote_public_key + * @param local_private_key A pointer to local private key + * @param private_key_length Length of local_private_key + * @return CHIP_ERROR The result of key derivation + */ + [[deprecated("Available until actual key exchange is implemented")]] CHIP_ERROR + TemporaryManualKeyExchange(const unsigned char * remote_public_key, const size_t public_key_length, + const unsigned char * local_private_key, const size_t private_key_length); + private: static constexpr size_t kAES_CCM128_Key_Length = 16;
diff --git a/src/transport/SecureSessionMgr.cpp b/src/transport/SecureSessionMgr.cpp index 410ebf6..35441ca 100644 --- a/src/transport/SecureSessionMgr.cpp +++ b/src/transport/SecureSessionMgr.cpp
@@ -33,13 +33,15 @@ namespace chip { +using Transport::PeerAddress; +using Transport::PeerConnectionState; + // Maximum length of application data that can be encrypted as one block. // The limit is derived from IPv6 MTU (1280 bytes) - expected header overheads. // This limit would need additional reviews once we have formalized Secure Transport header. -static const size_t kMax_SecureSDU_Length = 1024; -static const char * kManualKeyExchangeChannelInfo = "Manual Key Exchanged Channel"; +static const size_t kMax_SecureSDU_Length = 1024; -SecureSessionMgr::SecureSessionMgr() : mConnectionState(Transport::PeerAddress::Uninitialized()), mState(State::kNotReady) +SecureSessionMgr::SecureSessionMgr() : mState(State::kNotReady) { OnMessageReceived = NULL; } @@ -52,7 +54,7 @@ err = mTransport.Init(inet, listenParams); SuccessOrExit(err); - mTransport.SetMessageReceiveHandler(HandleDataReceived, this); + mTransport.SetMessageReceiveHandler(HandleUdpDataReceived, this); mState = State::kInitialized; mLocalNodeId = localNodeId; @@ -62,30 +64,24 @@ CHIP_ERROR SecureSessionMgr::Connect(NodeId peerNodeId, const Transport::PeerAddress & peerAddress) { - CHIP_ERROR err = CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + PeerConnectionState * state = nullptr; VerifyOrExit(mState == State::kInitialized, err = CHIP_ERROR_INCORRECT_STATE); - mConnectionState.SetPeerNodeId(peerNodeId); - mConnectionState.SetPeerAddress(peerAddress); - - mState = State::kConnected; - -exit: - return err; -} - -CHIP_ERROR SecureSessionMgr::ManualKeyExchange(const unsigned char * remote_public_key, const size_t public_key_length, - const unsigned char * local_private_key, const size_t private_key_length) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - size_t info_len = strlen(kManualKeyExchangeChannelInfo); - - VerifyOrExit(mState == State::kConnected || mState == State::kInitialized, err = CHIP_ERROR_INCORRECT_STATE); - err = mConnectionState.GetSecureSession().Init(remote_public_key, public_key_length, local_private_key, private_key_length, - NULL, 0, (const unsigned char *) kManualKeyExchangeChannelInfo, info_len); + err = mPeerConnections.CreateNewPeerConnectionState(peerAddress, &state); SuccessOrExit(err); - mState = State::kSecureConnected; + + state->SetPeerNodeId(peerNodeId); + + // TODO: + // - on new connection for other transports may not be inline. + // - determine if logic is required to prevent multiple connections to the + // same node or if some connection reuse is required. + if (OnNewConnection) + { + OnNewConnection(state, mNewConnectionArgument); + } exit: return err; @@ -93,40 +89,42 @@ CHIP_ERROR SecureSessionMgr::SendMessage(NodeId peerNodeId, System::PacketBuffer * msgBuf) { - CHIP_ERROR err = CHIP_NO_ERROR; + CHIP_ERROR err = CHIP_NO_ERROR; + PeerConnectionState * state = nullptr; - VerifyOrExit(StateAllowsSend(), err = CHIP_ERROR_INCORRECT_STATE); + VerifyOrExit(mState == State::kInitialized, err = CHIP_ERROR_INCORRECT_STATE); VerifyOrExit(msgBuf != NULL, err = CHIP_ERROR_INVALID_ARGUMENT); VerifyOrExit(msgBuf->Next() == NULL, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); VerifyOrExit(msgBuf->TotalLength() < kMax_SecureSDU_Length, err = CHIP_ERROR_INVALID_MESSAGE_LENGTH); + // Find an active connection to the specified peer node + VerifyOrExit(mPeerConnections.FindPeerConnectionState(peerNodeId, &state), err = CHIP_ERROR_INVALID_DESTINATION_NODE_ID); + { uint8_t * data = msgBuf->Start(); MessageHeader header; - err = mConnectionState.GetSecureSession().Encrypt(data, msgBuf->TotalLength(), data, header); + err = state->GetSecureSession().Encrypt(data, msgBuf->TotalLength(), data, header); SuccessOrExit(err); - ChipLogProgress(Inet, "Secure transport transmitting msg %u after encryption", mConnectionState.GetSendMessageIndex()); + ChipLogProgress(Inet, "Secure transport transmitting msg %u after encryption", state->GetSendMessageIndex()); header .SetSourceNodeId(mLocalNodeId) // .SetDestinationNodeId(peerNodeId) // - .SetMessageId(mConnectionState.GetSendMessageIndex()); + .SetMessageId(state->GetSendMessageIndex()); - err = mTransport.SendMessage(header, mConnectionState.GetPeerAddress(), msgBuf); + err = mTransport.SendMessage(header, state->GetPeerAddress(), msgBuf); msgBuf = NULL; } SuccessOrExit(err); - - mConnectionState.IncrementSendMessageIndex(); + state->IncrementSendMessageIndex(); exit: if (msgBuf != NULL) { - ChipLogProgress(Inet, "Secure transport failed to encrypt msg %u: %s", mConnectionState.GetSendMessageIndex(), - ErrorStr(err)); + ChipLogProgress(Inet, "Secure transport failed to encrypt msg %u: %s", state->GetSendMessageIndex(), ErrorStr(err)); PacketBuffer::Free(msgBuf); msgBuf = NULL; } @@ -134,21 +132,47 @@ return err; } -void SecureSessionMgr::HandleDataReceived(const MessageHeader & header, const IPPacketInfo & pktInfo, System::PacketBuffer * msg, - SecureSessionMgr * connection) +CHIP_ERROR SecureSessionMgr::AllocateNewConnection(const MessageHeader & header, const PeerAddress & address, + Transport::PeerConnectionState ** state) { - CHIP_ERROR err = CHIP_ERROR_INVALID_ARGUMENT; + CHIP_ERROR err = CHIP_NO_ERROR; - System::PacketBuffer * origMsg = nullptr; + err = mPeerConnections.CreateNewPeerConnectionState(address, state); + SuccessOrExit(err); - // TODO: actual key exchange should happen here - if (!connection->StateAllowsReceive()) + if (header.GetSourceNodeId().HasValue()) { - if (connection->OnNewConnection) + (*state)->SetPeerNodeId(header.GetSourceNodeId().Value()); + } + + if (OnNewConnection) + { + OnNewConnection(*state, mNewConnectionArgument); + } + +exit: + return err; +} +void SecureSessionMgr::HandleUdpDataReceived(const MessageHeader & header, const IPPacketInfo & pktInfo, System::PacketBuffer * msg, + SecureSessionMgr * connection) + +{ + CHIP_ERROR err = CHIP_NO_ERROR; + System::PacketBuffer * origMsg = nullptr; + PeerConnectionState * state = nullptr; + + VerifyOrExit(msg != nullptr, ChipLogError(Inet, "Secure transport received NULL packet, discarding")); + + { + PeerAddress peerAddress = PeerAddress::UDP(pktInfo.SrcAddress, pktInfo.SrcPort); + + if (!connection->mPeerConnections.FindPeerConnectionState(peerAddress, &state)) { - connection->OnNewConnection(header, pktInfo, connection->mNewConnectionArgument); + ChipLogProgress(Inet, "New peer connection received."); + + err = connection->AllocateNewConnection(header, peerAddress, &state); + SuccessOrExit(err); } - err = CHIP_NO_ERROR; } if (!connection->StateAllowsReceive()) @@ -156,8 +180,6 @@ ExitNow(ChipLogProgress(Inet, "Secure transport failed: state does not allow receive")); } - VerifyOrExit(msg != nullptr, ChipLogError(Inet, "Secure transport received NULL packet, discarding")); - // TODO this is where messages should be decoded { uint8_t * data = msg->Start(); @@ -172,12 +194,12 @@ #endif plainText = msg->Start(); - err = connection->mConnectionState.GetSecureSession().Decrypt(data, len, plainText, header); + err = state->GetSecureSession().Decrypt(data, len, plainText, header); VerifyOrExit(err == CHIP_NO_ERROR, ChipLogProgress(Inet, "Secure transport failed to decrypt msg: err %d", err)); if (connection->OnMessageReceived) { - connection->OnMessageReceived(header, pktInfo, msg, connection->mMessageReceivedArgument); + connection->OnMessageReceived(header, state, msg, connection->mMessageReceivedArgument); msg = nullptr; } }
diff --git a/src/transport/SecureSessionMgr.h b/src/transport/SecureSessionMgr.h index e54488d..11d9e35 100644 --- a/src/transport/SecureSessionMgr.h +++ b/src/transport/SecureSessionMgr.h
@@ -32,7 +32,7 @@ #include <core/ReferenceCounted.h> #include <inet/IPAddress.h> #include <inet/IPEndPointBasis.h> -#include <transport/PeerConnectionState.h> +#include <transport/PeerConnections.h> #include <transport/SecureSession.h> #include <transport/UDP.h> @@ -48,10 +48,8 @@ */ enum class State { - kNotReady, /**< State before initialization. */ - kInitialized, /**< State when the object is ready to connect. */ - kConnected, /**< State when the remte peer is connected. */ - kSecureConnected, /**< State when the security of the connection has been established. */ + kNotReady, /**< State before initialization. */ + kInitialized, /**< State when the object is ready connect to other peers. */ }; /** @@ -68,21 +66,6 @@ CHIP_ERROR Init(NodeId localNodeId, Inet::InetLayer * inet, const Transport::UdpListenParameters & listenParams); /** - * @brief - * The keypair for the secure channel. This is a utility function that will be used - * until we have automatic key exchange in place. The function is useful only for - * example applications for now. It will eventually be removed. - * - * @param remote_public_key A pointer to peer's public key - * @param public_key_length Length of remote_public_key - * @param local_private_key A pointer to local private key - * @param private_key_length Length of local_private_key - * @return CHIP_ERROR The result of key derivation - */ - CHIP_ERROR ManualKeyExchange(const unsigned char * remote_public_key, const size_t public_key_length, - const unsigned char * local_private_key, const size_t private_key_length); - - /** * Establishes a connection to the given peer node. * * A connection needs to be established before SendMessage can be called. @@ -110,7 +93,8 @@ * */ template <class T> - void SetMessageReceiveHandler(void (*handler)(const MessageHeader &, const Inet::IPPacketInfo &, System::PacketBuffer *, T *), + void SetMessageReceiveHandler(void (*handler)(const MessageHeader &, Transport::PeerConnectionState *, System::PacketBuffer *, + T *), T * param) { mMessageReceivedArgument = param; @@ -136,36 +120,19 @@ * */ template <class T> - void SetNewConnectionHandler(void (*handler)(const MessageHeader &, const Inet::IPPacketInfo &, T *), T * param) + void SetNewConnectionHandler(void (*handler)(Transport::PeerConnectionState *, T *), T * param) { mNewConnectionArgument = param; OnNewConnection = reinterpret_cast<NewConnectionHandler>(handler); } - /** - * TEMPORARY method for current connection until multi-session handling support - * is added to this class. - */ - NodeId GetPeerNodeId() const { return mConnectionState.GetPeerNodeId(); }; - private: - // TODO: settings below are single-transport and single-peer. Long term - // intent for the class is to do session management and there will be - // multiple transports and multiple peers supported. - // Expected changes: - // - Transports including UDP, TCP, BLE as needed - // - Multiple peers with separate states (encryption settings and handshake state) - // - Global state is only a ready/notready and connection state is deferred into - // individual connections. - + // TODO: add support for multiple transports (TCP, BLE to be added) Transport::UDP mTransport; - Transport::PeerConnectionState mConnectionState; - NodeId mLocalNodeId; - State mState; - - bool StateAllowsSend(void) const { return mState != State::kNotReady; } - bool StateAllowsReceive(void) const { return mState == State::kSecureConnected; } + NodeId mLocalNodeId; //< Id of the current node + Transport::PeerConnections mPeerConnections; //< Active connections to other peers + State mState; //< Initialization state of the object /** * This function is the application callback that is invoked when a message is received over a @@ -173,7 +140,7 @@ * * @param[in] msgBuf A pointer to the PacketBuffer object holding the message. */ - typedef void (*MessageReceiveHandler)(const MessageHeader & header, const Inet::IPPacketInfo & source, + typedef void (*MessageReceiveHandler)(const MessageHeader & header, Transport::PeerConnectionState * state, System::PacketBuffer * msgBuf, void * param); MessageReceiveHandler OnMessageReceived = nullptr; ///< Callback on message receiving @@ -183,13 +150,28 @@ ReceiveErrorHandler OnReceiveError = nullptr; ///< Callback on error in message receiving - typedef void (*NewConnectionHandler)(const MessageHeader & header, const Inet::IPPacketInfo & source, void * param); + typedef void (*NewConnectionHandler)(Transport::PeerConnectionState * state, void * param); NewConnectionHandler OnNewConnection = nullptr; ///< Callback for new connection received void * mNewConnectionArgument = nullptr; ///< Argument for callback - static void HandleDataReceived(const MessageHeader & header, const Inet::IPPacketInfo & source, System::PacketBuffer * msgBuf, - SecureSessionMgr * transport); + /** + * Allocates a new connection for the given source. + * + * @param header The header that was received when the connection was established + * @param address Where the connection originated from + * @param state [out] the newly allocated connection state for the connection + */ + CHIP_ERROR AllocateNewConnection(const MessageHeader & header, const Transport::PeerAddress & address, + Transport::PeerConnectionState ** state); + + /** + * Handle UDP data receiving. Each transport has separate data receiving as active sessions + * follow data receiving channels. + * + */ + static void HandleUdpDataReceived(const MessageHeader & header, const Inet::IPPacketInfo & source, + System::PacketBuffer * msgBuf, SecureSessionMgr * transport); }; } // namespace chip
diff --git a/src/transport/tests/TestSecureSessionMgr.cpp b/src/transport/tests/TestSecureSessionMgr.cpp index 88b449b..0156b90 100644 --- a/src/transport/tests/TestSecureSessionMgr.cpp +++ b/src/transport/tests/TestSecureSessionMgr.cpp
@@ -62,11 +62,12 @@ int ReceiveHandlerCallCount = 0; -static void MessageReceiveHandler(const MessageHeader & header, const Inet::IPPacketInfo & source, System::PacketBuffer * msgBuf, - nlTestSuite * inSuite) +static void MessageReceiveHandler(const MessageHeader & header, Transport::PeerConnectionState * state, + System::PacketBuffer * msgBuf, nlTestSuite * inSuite) { NL_TEST_ASSERT(inSuite, header.GetSourceNodeId() == Optional<NodeId>::Value(kSourceNodeId)); NL_TEST_ASSERT(inSuite, header.GetDestinationNodeId() == Optional<NodeId>::Value(kDestinationNodeId)); + NL_TEST_ASSERT(inSuite, state->GetPeerNodeId() == kDestinationNodeId); size_t data_len = msgBuf->DataLength(); @@ -74,7 +75,19 @@ NL_TEST_ASSERT(inSuite, compare == 0); ReceiveHandlerCallCount++; -}; +} + +int NewConnectionHandlerCallCount = 0; +static void NewConnectionHandler(Transport::PeerConnectionState * state, nlTestSuite * inSuite) +{ + CHIP_ERROR err; + + NewConnectionHandlerCallCount++; + + err = state->GetSecureSession().TemporaryManualKeyExchange(remote_public_key, sizeof(remote_public_key), local_private_key, + sizeof(local_private_key)); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); +} static void DriveIO(TestContext & ctx) { @@ -162,14 +175,14 @@ err = conn.Init(kSourceNodeId, &ctx.mInetLayer, Transport::UdpListenParameters().SetAddressType(addr.Type())); NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - err = conn.Connect(kDestinationNodeId, Transport::PeerAddress::UDP(addr)); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - - err = conn.ManualKeyExchange(remote_public_key, sizeof(remote_public_key), local_private_key, sizeof(local_private_key)); - NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); - + conn.SetNewConnectionHandler(NewConnectionHandler, inSuite); conn.SetMessageReceiveHandler(MessageReceiveHandler, inSuite); + NewConnectionHandlerCallCount = 0; + err = conn.Connect(kDestinationNodeId, Transport::PeerAddress::UDP(addr)); + NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR); + NL_TEST_ASSERT(inSuite, NewConnectionHandlerCallCount == 1); + // Should be able to send a message to itself by just calling send. ReceiveHandlerCallCount = 0; err = conn.SendMessage(kDestinationNodeId, buffer);