[dtls] simplify dtls state machine (#3529)

This commit also adds checks to ensure there is only one outstanding
connection at a time.
This commit is contained in:
Jonathan Hui
2019-01-30 08:47:42 -08:00
committed by GitHub
parent f9d757a161
commit ba9709b674
3 changed files with 56 additions and 51 deletions
+7 -4
View File
@@ -138,12 +138,12 @@ otError CoapSecure::Connect(const Ip6::SockAddr &aSockAddr, ConnectedCallback aC
bool CoapSecure::IsConnectionActive(void)
{
return GetNetif().GetDtls().IsStarted();
return GetNetif().GetDtls().GetState() != MeshCoP::Dtls::kStateStopped;
}
bool CoapSecure::IsConnected(void)
{
return GetNetif().GetDtls().IsConnected();
return GetNetif().GetDtls().GetState() == MeshCoP::Dtls::kStateConnected;
}
otError CoapSecure::Disconnect(void)
@@ -258,7 +258,7 @@ void CoapSecure::HandleUdpReceive(ot::Message &aMessage, const Ip6::MessageInfo
{
ThreadNetif &netif = GetNetif();
if (!netif.GetDtls().IsStarted())
if (netif.GetDtls().GetState() == MeshCoP::Dtls::kStateStopped)
{
Ip6::SockAddr sockAddr;
sockAddr.mAddress = aMessageInfo.GetPeerAddr();
@@ -287,7 +287,10 @@ void CoapSecure::HandleUdpReceive(ot::Message &aMessage, const Ip6::MessageInfo
}
#if OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER
netif.GetDtls().SetClientId(mPeerAddress.GetPeerAddr().mFields.m8, sizeof(mPeerAddress.GetPeerAddr().mFields));
if (netif.GetDtls().GetState() == MeshCoP::Dtls::kStateConnecting)
{
netif.GetDtls().SetClientId(mPeerAddress.GetPeerAddr().mFields.m8, sizeof(mPeerAddress.GetPeerAddr().mFields));
}
#endif
netif.GetDtls().Receive(aMessage, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset());
+33 -32
View File
@@ -55,9 +55,9 @@ namespace MeshCoP {
Dtls::Dtls(Instance &aInstance)
: InstanceLocator(aInstance)
, mState(kStateStopped)
, mPskLength(0)
, mVerifyPeerCertificate(true)
, mStarted(false)
, mTimer(aInstance, &Dtls::HandleTimer, this)
, mTimerIntermediate(0)
, mTimerSet(false)
@@ -68,7 +68,6 @@ Dtls::Dtls(Instance &aInstance)
, mReceiveHandler(NULL)
, mSendHandler(NULL)
, mContext(NULL)
, mGuardTimerSet(false)
, mMessageSubType(Message::kSubTypeNone)
, mMessageDefaultSubType(Message::kSubTypeNone)
{
@@ -159,7 +158,7 @@ otError Dtls::Start(bool aClient,
int rval;
// do not handle new connection before guard time expired
VerifyOrExit(mGuardTimerSet == false, rval = MBEDTLS_ERR_SSL_TIMEOUT);
VerifyOrExit(mState == kStateStopped, rval = MBEDTLS_ERR_SSL_TIMEOUT);
mbedtls_ssl_init(&mSsl);
mbedtls_ssl_config_init(&mConf);
@@ -250,7 +249,7 @@ otError Dtls::Start(bool aClient,
mContext = aContext;
mReceiveMessage = NULL;
mMessageSubType = Message::kSubTypeNone;
mStarted = true;
mState = kStateConnecting;
if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8)
{
@@ -333,33 +332,28 @@ void Dtls::SetSslAuthMode(bool aVerifyPeerCertificate)
otError Dtls::Stop(void)
{
VerifyOrExit((mState == kStateConnecting) || (mState == kStateConnected));
mbedtls_ssl_close_notify(&mSsl);
Close();
exit:
return OT_ERROR_NONE;
}
void Dtls::Close(void)
{
// guard time, that the possible close notify
// not open an invalid (new) connection
mGuardTimerSet = true;
assert((mState == kStateConnecting) || (mState == kStateConnected));
mState = kStateCloseNotify;
mTimer.Start(kGuardTimeNewConnectionMilli);
VerifyOrExit(mStarted);
mStarted = false;
FreeMbedtls();
if (mConnectedHandler != NULL)
{
mConnectedHandler(mContext, false);
}
exit:
return;
}
bool Dtls::IsStarted(void)
{
return mStarted;
}
otError Dtls::SetPsk(const uint8_t *aPsk, uint8_t aPskLength)
@@ -451,7 +445,7 @@ otError Dtls::GetPeerCertificateBase64(unsigned char *aPeerCert, size_t *aCertLe
{
otError error = OT_ERROR_NONE;
VerifyOrExit(IsConnected() == true, error = OT_ERROR_INVALID_STATE);
VerifyOrExit(mState == kStateConnected, error = OT_ERROR_INVALID_STATE);
VerifyOrExit(mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength, mSsl.session->peer_cert->raw.p,
mSsl.session->peer_cert->raw.len) == 0,
@@ -472,11 +466,6 @@ otError Dtls::SetClientId(const uint8_t *aClientId, uint8_t aLength)
}
#endif // OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER
bool Dtls::IsConnected(void)
{
return mSsl.state == MBEDTLS_SSL_HANDSHAKE_OVER;
}
otError Dtls::Send(Message &aMessage, uint16_t aLength)
{
otError error = OT_ERROR_NONE;
@@ -710,14 +699,21 @@ void Dtls::HandleTimer(Timer &aTimer)
void Dtls::HandleTimer(void)
{
if (!mGuardTimerSet)
switch (mState)
{
case kStateConnecting:
case kStateConnected:
Process();
}
else
{
mGuardTimerSet = false;
break;
case kStateCloseNotify:
mState = kStateStopped;
mTimer.Stop();
break;
default:
assert(false);
break;
}
}
@@ -727,15 +723,20 @@ void Dtls::Process(void)
bool shouldClose = false;
int rval;
while (mStarted)
while ((mState == kStateConnecting) || (mState == kStateConnected))
{
if (mSsl.state != MBEDTLS_SSL_HANDSHAKE_OVER)
if (mState == kStateConnecting)
{
rval = mbedtls_ssl_handshake(&mSsl);
if ((mSsl.state == MBEDTLS_SSL_HANDSHAKE_OVER) && (mConnectedHandler != NULL))
if (mSsl.state == MBEDTLS_SSL_HANDSHAKE_OVER)
{
mConnectedHandler(mContext, true);
mState = kStateConnected;
if (mConnectedHandler != NULL)
{
mConnectedHandler(mContext, true);
}
}
}
else
+16 -15
View File
@@ -79,6 +79,14 @@ public:
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
};
enum State
{
kStateStopped = 0,
kStateConnecting,
kStateConnected,
kStateCloseNotify,
};
/**
* This constructor initializes the DTLS object.
*
@@ -148,12 +156,15 @@ public:
otError Stop(void);
/**
* This method indicates whether or not the DTLS service is active.
* This method returns the DTLS connection state.
*
* @returns true if the DTLS service is active, false otherwise.
* @retval kStateStopped If the DTLS service has not been started.
* @retval kStateConnecting If the DTLS service is establishing a connection.
* @retval kStateConnected If the DTLS service has a connection established.
* @retval kStateCloseNotify If the DTLS service is closing a connection.
*
*/
bool IsStarted(void);
State GetState(void) const { return mState; }
/**
* This method sets the PSK.
@@ -267,15 +278,6 @@ public:
otError SetClientId(const uint8_t *aClientId, uint8_t aLength);
#endif // OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER
/**
* 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 sends data within the DTLS session.
*
@@ -364,6 +366,8 @@ private:
void Close(void);
void Process(void);
State mState;
int mCipherSuites[2];
uint8_t mPsk[kPskMaxLength];
uint8_t mPskLength;
@@ -401,8 +405,6 @@ private:
mbedtls_ssl_cookie_ctx mCookieCtx;
#endif
bool mStarted;
TimerMilli mTimer;
uint32_t mTimerIntermediate;
bool mTimerSet;
@@ -415,7 +417,6 @@ private:
ReceiveHandler mReceiveHandler;
SendHandler mSendHandler;
void * mContext;
bool mGuardTimerSet;
uint8_t mMessageSubType;
uint8_t mMessageDefaultSubType;