Skip to content

Commit

Permalink
TCP ConnectToPeer() API in Transport Manager
Browse files Browse the repository at this point in the history
Currently, connecting to a peer is coupled with sending a message to the
peer.
This decouples the two and creates a clear API for connecting to a peer
address. Goes along with the existing Disconnect() API.
This would be essential during activation of retained sessions by solely
connecting to the peer and associating with the retained session.

Surface Connection completion and Closure callbacks and hook them
within SessionManager and CASESession.
  • Loading branch information
pidarped committed Nov 8, 2023
1 parent fe513bb commit bc9155c
Show file tree
Hide file tree
Showing 13 changed files with 712 additions and 150 deletions.
46 changes: 27 additions & 19 deletions src/inet/TCPEndPoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,26 @@ class TCPTest;
class DLL_EXPORT TCPEndPoint : public EndPointBasis<TCPEndPoint>
{
public:
/**
* Basic dynamic state of the underlying endpoint.
*
* Objects are initialized in the "ready" state, proceed to subsequent
* states corresponding to a simplification of the states of the TCP
* transport state machine.
*/
enum class State : uint8_t
{
kReady = 0, /**< Endpoint initialized, but not bound. */
kBound = 1, /**< Endpoint bound, but not listening. */
kListening = 2, /**< Endpoint receiving connections. */
kConnecting = 3, /**< Endpoint attempting to connect. */
kConnected = 4, /**< Endpoint connected, ready for tx/rx. */
kSendShutdown = 5, /**< Endpoint initiated its half-close. */
kReceiveShutdown = 6, /**< Endpoint responded to half-close. */
kClosing = 7, /**< Endpoint closing bidirectionally. */
kClosed = 8 /**< Endpoint closed, ready for release. */
};

/**
* @brief Bind the endpoint to an interface IP address.
*
Expand Down Expand Up @@ -330,6 +350,12 @@ class DLL_EXPORT TCPEndPoint : public EndPointBasis<TCPEndPoint>
*/
void Free();

/**
* @brief Get current state of the TCP connection.
*
*/
State GetTCPState() const { return mState; };

/**
* @brief Extract whether TCP connection is established.
*/
Expand Down Expand Up @@ -544,25 +570,7 @@ class DLL_EXPORT TCPEndPoint : public EndPointBasis<TCPEndPoint>

virtual ~TCPEndPoint() = default;

/**
* Basic dynamic state of the underlying endpoint.
*
* Objects are initialized in the "ready" state, proceed to subsequent
* states corresponding to a simplification of the states of the TCP
* transport state machine.
*/
enum class State : uint8_t
{
kReady = 0, /**< Endpoint initialized, but not bound. */
kBound = 1, /**< Endpoint bound, but not listening. */
kListening = 2, /**< Endpoint receiving connections. */
kConnecting = 3, /**< Endpoint attempting to connect. */
kConnected = 4, /**< Endpoint connected, ready for tx/rx. */
kSendShutdown = 5, /**< Endpoint initiated its half-close. */
kReceiveShutdown = 6, /**< Endpoint responded to half-close. */
kClosing = 7, /**< Endpoint closing bidirectionally. */
kClosed = 8 /**< Endpoint closed, ready for release. */
} mState;
State mState;

/** Control switch indicating whether the application is receiving data. */
bool mReceiveEnabled;
Expand Down
14 changes: 14 additions & 0 deletions src/lib/core/CHIPConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,20 @@ extern const char CHIP_NON_PRODUCTION_MARKER[];
#define CHIP_CONFIG_SYNCHRONOUS_REPORTS_ENABLED 0
#endif

/**
* @def CHIP_CONFIG_TCP_SUPPORT_ENABLED
*
* @brief
* Enable (1) or disable (0) support for TCP as a transport protocol for
* operational communications.
*
* When enabled, the node would advertise this support via DNS-SD advertisements to allow peers
* to know and select the appropriate transport for session establishment.
*/
#ifndef CHIP_CONFIG_TCP_SUPPORT_ENABLED
#define CHIP_CONFIG_TCP_SUPPORT_ENABLED (INET_CONFIG_ENABLE_TCP_ENDPOINT)
#endif

/**
* @}
*/
59 changes: 57 additions & 2 deletions src/protocols/secure_channel/CASESession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,13 +444,18 @@ CHIP_ERROR CASESession::Init(SessionManager & sessionManager, Credentials::Certi
ReturnErrorOnFailure(mCommissioningHash.Begin());

mDelegate = delegate;
mSessionManager = &sessionManager;

ReturnErrorOnFailure(AllocateSecureSession(sessionManager, sessionEvictionHint));

mValidContext.Reset();
mValidContext.mRequiredKeyUsages.Set(KeyUsageFlags::kDigitalSignature);
mValidContext.mRequiredKeyPurposes.Set(KeyPurposeFlags::kServerAuth);
mValidContext.mValidityPolicy = policy;

// Set callbacks for connection in sessionmanager
sessionManager.SetConnectionCallbacks(HandleConnectionComplete, HandleConnectionClosed, this);

return CHIP_NO_ERROR;
}

Expand Down Expand Up @@ -530,8 +535,24 @@ CHIP_ERROR CASESession::EstablishSession(SessionManager & sessionManager, Fabric
ChipLogProgress(SecureChannel, "Initiating session on local FabricIndex %u from 0x" ChipLogFormatX64 " -> 0x" ChipLogFormatX64,
static_cast<unsigned>(mFabricIndex), ChipLogValueX64(mLocalNodeId), ChipLogValueX64(mPeerNodeId));

err = SendSigma1();
SuccessOrExit(err);

//TODO: Need to look into unifying this call to invoke ConnectToPeer() for
// all transports, including MRP.
// For UDP based transports, this call would short-circuit back into
// HandleConnectionComplete() callback.
// Currently, TestCASESession is organized such that it requires synchronous
// calls back from EstablishSession() over UDP. So, bifurcate TCP and MRP
// calls here, for now.
if (mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->GetPeerAddress().GetTransportType() == Transport::Type::kTcp)
{
err = sessionManager.ConnectToPeer(mExchangeCtxt->GetSessionHandle()->AsUnauthenticatedSession()->GetPeerAddress());
SuccessOrExit(err);
}
else
{
err = SendSigma1();
SuccessOrExit(err);
}

exit:
if (err != CHIP_NO_ERROR)
Expand Down Expand Up @@ -637,6 +658,40 @@ CHIP_ERROR CASESession::RecoverInitiatorIpk()
return CHIP_NO_ERROR;
}

void CASESession::HandleConnectionComplete(void *context, Inet::TCPEndPoint * conObj, CHIP_ERROR conErr)
{
CHIP_ERROR err = CHIP_NO_ERROR;

VerifyOrReturn(context != nullptr);
// VerifyOrReturn(peerAddr.GetTransportType() == Transport::Type::kTcp);

CASESession * caseSession = reinterpret_cast<CASESession *>(context);

// Send Sigma1 after connection is established for sessions over TCP
err = caseSession->SendSigma1();
if (err != CHIP_NO_ERROR)
{
caseSession->Clear();
}
}

void CASESession::HandleConnectionClosed(void *context, Inet::TCPEndPoint * conObj, CHIP_ERROR conErr)
{
//CHIP_ERROR err = CHIP_NO_ERROR;

VerifyOrReturn(context != nullptr);
CASESession * caseSession = reinterpret_cast<CASESession *>(context);
if (conErr == CHIP_NO_ERROR)
{
caseSession->Clear();
}
else
{
// Connection establishment failed

}
}

CHIP_ERROR CASESession::SendSigma1()
{
MATTER_TRACE_SCOPE("SendSigma1", "CASESession");
Expand Down
6 changes: 6 additions & 0 deletions src/protocols/secure_channel/CASESession.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,11 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler,

void InvalidateIfPendingEstablishmentOnFabric(FabricIndex fabricIndex);

#if CHIP_CONFIG_TCP_SUPPORT_ENABLED
static void HandleConnectionComplete(void *context, Inet::TCPEndPoint * conObj, CHIP_ERROR conErr);
static void HandleConnectionClosed(void *context, Inet::TCPEndPoint * conObj, CHIP_ERROR conErr);
#endif // CHIP_CONFIG_TCP_SUPPORT_ENABLED

#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
void SetStopSigmaHandshakeAt(Optional<State> state) { mStopHandshakeAtState = state; }
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
Expand All @@ -298,6 +303,7 @@ class DLL_EXPORT CASESession : public Messaging::UnsolicitedMessageHandler,
uint8_t mIPK[kIPKSize];

SessionResumptionStorage * mSessionResumptionStorage = nullptr;
SessionManager * mSessionManager = nullptr;

FabricTable * mFabricsTable = nullptr;
FabricIndex mFabricIndex = kUndefinedFabricIndex;
Expand Down
67 changes: 67 additions & 0 deletions src/transport/SessionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ CHIP_ERROR SessionManager::Init(System::Layer * systemLayer, TransportMgrBase *

mTransportMgr->SetSessionManager(this);

mTransportMgr->SetSystemLayer(systemLayer);

#if CHIP_CONFIG_TCP_SUPPORT_ENABLED
mConnCompleteCb = nullptr;
mConnClosedCb = nullptr;
#endif // CHIP_CONFIG_TCP_SUPPORT_ENABLED

return CHIP_NO_ERROR;
}

Expand Down Expand Up @@ -582,6 +589,66 @@ void SessionManager::OnMessageReceived(const PeerAddress & peerAddress, System::
}
}

#if CHIP_CONFIG_TCP_SUPPORT_ENABLED
void SessionManager::SetConnectionCallbacks(OnConnectionCompleteCallback connCompleteCb,
OnConnectionClosedCallback connClosedCb,
void * connContext)
{
mConnCompleteCb = connCompleteCb;
mConnClosedCb = connClosedCb;
mConnContext = connContext;
}

void SessionManager::HandleConnectionComplete(Inet::TCPEndPoint * conObj, CHIP_ERROR conErr)
{
if (mConnCompleteCb != nullptr)
{
ChipLogProgress(Inet, "Calling Connection Complete callback");
mConnCompleteCb(mConnContext, conObj, conErr);
}
else
{
ChipLogProgress(Inet, "Connection Complete callback missing");
}
}

void SessionManager::HandleConnectionClosed(Inet::TCPEndPoint * conObj, CHIP_ERROR conErr)
{
if (mConnClosedCb != nullptr)
{
mConnClosedCb(mConnContext, conObj, conErr);
}
else
{
ChipLogProgress(Inet, "Connection Closed callback missing");
}
}

CHIP_ERROR SessionManager::ConnectToPeer(const PeerAddress & peerAddress)
{
if (mTransportMgr != nullptr)
{
ChipLogProgress(Inet, "Connecting to peer ");
return mTransportMgr->ConnectToPeer(peerAddress);
}

ChipLogError(Inet, "The transport manager is not initialized. Unable to connect to peer");

return CHIP_ERROR_INCORRECT_STATE;
}

CHIP_ERROR SessionManager::Disconnect(const PeerAddress & peerAddress)
{
if (mTransportMgr != nullptr)
{
ChipLogProgress(Inet, "Disconnecting from peer ");
mTransportMgr->Disconnect(peerAddress);
}

return CHIP_NO_ERROR;
}
#endif // CHIP_CONFIG_TCP_SUPPORT_ENABLED

void SessionManager::UnauthenticatedMessageDispatch(const PacketHeader & partialPacketHeader,
const Transport::PeerAddress & peerAddress, System::PacketBufferHandle && msg)
{
Expand Down
27 changes: 27 additions & 0 deletions src/transport/SessionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ class DLL_EXPORT SessionManager : public TransportMgrDelegate, public FabricTabl
TransportMgrBase * GetTransportManager() const { return mTransportMgr; }
Transport::SecureSessionTable & GetSecureSessions() { return mSecureSessions; }


/**
* @brief
* Handle received secure message. Implements TransportMgrDelegate
Expand All @@ -416,6 +417,26 @@ class DLL_EXPORT SessionManager : public TransportMgrDelegate, public FabricTabl
*/
void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf) override;

#if CHIP_CONFIG_TCP_SUPPORT_ENABLED
CHIP_ERROR ConnectToPeer(const Transport::PeerAddress & peerAddress);

CHIP_ERROR Disconnect(const Transport::PeerAddress & peerAddress);

void HandleConnectionComplete(Inet::TCPEndPoint * conObj, CHIP_ERROR conErr) override;

void HandleConnectionClosed(Inet::TCPEndPoint * conObj, CHIP_ERROR conErr) override;

// Functors for callbacks into higher layers
using OnConnectionCompleteCallback = void (*)(void * appContext, Inet::TCPEndPoint * conObj, CHIP_ERROR conErr);

using OnConnectionClosedCallback = void (*)(void * appContext, Inet::TCPEndPoint * conObj, CHIP_ERROR conErr);

// Set the higher layer callbacks
void SetConnectionCallbacks(OnConnectionCompleteCallback connCompleteCb,
OnConnectionClosedCallback connClosedCb,
void *connContext);
#endif // CHIP_CONFIG_TCP_SUPPORT_ENABLED

Optional<SessionHandle> CreateUnauthenticatedSession(const Transport::PeerAddress & peerAddress,
const ReliableMessageProtocolConfig & config)
{
Expand Down Expand Up @@ -477,6 +498,12 @@ class DLL_EXPORT SessionManager : public TransportMgrDelegate, public FabricTabl
State mState; // < Initialization state of the object
chip::Transport::GroupOutgoingCounters mGroupClientCounter;

#if CHIP_CONFIG_TCP_SUPPORT_ENABLED
OnConnectionCompleteCallback mConnCompleteCb = nullptr;
OnConnectionClosedCallback mConnClosedCb = nullptr;
void * mConnContext = nullptr;
#endif // CHIP_CONFIG_TCP_SUPPORT_ENABLED

SessionMessageDelegate * mCB = nullptr;

TransportMgrBase * mTransportMgr = nullptr;
Expand Down
14 changes: 14 additions & 0 deletions src/transport/TransportMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ class TransportMgrDelegate
* @param msgBuf the buffer containing a full CHIP message (except for the optional length field).
*/
virtual void OnMessageReceived(const Transport::PeerAddress & source, System::PacketBufferHandle && msgBuf) = 0;

#if CHIP_CONFIG_TCP_SUPPORT_ENABLED
/**
* @brief
* Handle connection completion.
*
* @param conObj the connection object
* @param conErr the connection error on the attempt.
*/
virtual void HandleConnectionComplete(Inet::TCPEndPoint * conObj, CHIP_ERROR conErr) {};


virtual void HandleConnectionClosed(Inet::TCPEndPoint * conObj, CHIP_ERROR conErr) {};
#endif // CHIP_CONFIG_TCP_SUPPORT_ENABLED
};

template <typename... TransportTypes>
Expand Down
Loading

0 comments on commit bc9155c

Please sign in to comment.