mirror of
https://github.com/espressif/openthread.git
synced 2026-07-28 22:57:47 +00:00
[cli] clean up coaps example implementation (#3795)
This commit is contained in:
committed by
Jonathan Hui
parent
1b9c50112e
commit
d4063fe9b8
+317
-342
@@ -46,6 +46,15 @@
|
||||
namespace ot {
|
||||
namespace Cli {
|
||||
|
||||
const struct CoapSecure::Command CoapSecure::sCommands[] = {
|
||||
{"help", &CoapSecure::ProcessHelp}, {"connect", &CoapSecure::ProcessConnect},
|
||||
{"delete", &CoapSecure::ProcessRequest}, {"disconnect", &CoapSecure::ProcessDisconnect},
|
||||
{"get", &CoapSecure::ProcessRequest}, {"post", &CoapSecure::ProcessRequest},
|
||||
{"psk", &CoapSecure::ProcessPsk}, {"put", &CoapSecure::ProcessRequest},
|
||||
{"resource", &CoapSecure::ProcessResource}, {"start", &CoapSecure::ProcessStart},
|
||||
{"stop", &CoapSecure::ProcessStop}, {"x509", &CoapSecure::ProcessX509},
|
||||
};
|
||||
|
||||
CoapSecure::CoapSecure(Interpreter &aInterpreter)
|
||||
: mInterpreter(aInterpreter)
|
||||
, mShutdownFlag(false)
|
||||
@@ -58,39 +67,6 @@ CoapSecure::CoapSecure(Interpreter &aInterpreter)
|
||||
memset(&mPskId, 0, sizeof(mPskId));
|
||||
}
|
||||
|
||||
void CoapSecure::PrintHeaderInfos(otMessage *aMessage) const
|
||||
{
|
||||
otCoapCode mCoapCode;
|
||||
otCoapType mCoapType;
|
||||
|
||||
mCoapCode = otCoapMessageGetCode(aMessage);
|
||||
mCoapType = otCoapMessageGetType(aMessage);
|
||||
|
||||
mInterpreter.mServer->OutputFormat("\r\n CoapSecure RX Header Information:"
|
||||
"\r\n Type %d => ",
|
||||
static_cast<uint16_t>(mCoapType));
|
||||
|
||||
switch (mCoapType)
|
||||
{
|
||||
case OT_COAP_TYPE_ACKNOWLEDGMENT:
|
||||
mInterpreter.mServer->OutputFormat("Ack");
|
||||
break;
|
||||
case OT_COAP_TYPE_CONFIRMABLE:
|
||||
mInterpreter.mServer->OutputFormat("Confirmable");
|
||||
break;
|
||||
case OT_COAP_TYPE_NON_CONFIRMABLE:
|
||||
mInterpreter.mServer->OutputFormat("NonConfirmable");
|
||||
break;
|
||||
case OT_COAP_TYPE_RESET:
|
||||
mInterpreter.mServer->OutputFormat("Reset");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mInterpreter.mServer->OutputFormat("\r\n Code %d => %s\r\n", static_cast<uint16_t>(mCoapCode),
|
||||
static_cast<const char *>(otCoapMessageCodeToString(aMessage)));
|
||||
}
|
||||
|
||||
void CoapSecure::PrintPayload(otMessage *aMessage) const
|
||||
{
|
||||
uint8_t buf[kMaxBufferSize];
|
||||
@@ -100,341 +76,108 @@ void CoapSecure::PrintPayload(otMessage *aMessage) const
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat(" With payload [UTF8]:\r\n", aMessage);
|
||||
mInterpreter.mServer->OutputFormat(" with payload: ");
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
bytesToPrint = (length < sizeof(buf)) ? length : sizeof(buf);
|
||||
otMessageRead(aMessage, otMessageGetOffset(aMessage) + bytesPrinted, buf, bytesToPrint);
|
||||
|
||||
for (int i = 0; i < bytesToPrint; i++)
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("%c", buf[i]);
|
||||
}
|
||||
mInterpreter.mServer->OutputFormat("\r\n");
|
||||
mInterpreter.OutputBytes(buf, static_cast<uint8_t>(bytesToPrint));
|
||||
|
||||
length -= bytesToPrint;
|
||||
bytesPrinted += bytesToPrint;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat(" No payload.");
|
||||
}
|
||||
|
||||
mInterpreter.mServer->OutputFormat("\r\n> ");
|
||||
mInterpreter.mServer->OutputFormat("\r\n");
|
||||
}
|
||||
|
||||
otError CoapSecure::Process(int argc, char *argv[])
|
||||
otError CoapSecure::ProcessHelp(int argc, char *argv[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
bool mVerifyPeerCert = true;
|
||||
long value;
|
||||
OT_UNUSED_VARIABLE(argc);
|
||||
OT_UNUSED_VARIABLE(argv);
|
||||
|
||||
VerifyOrExit(argc > 0, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
if (strcmp(argv[0], "start") == 0)
|
||||
for (size_t i = 0; i < OT_ARRAY_LENGTH(sCommands); i++)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
if (strcmp(argv[1], "false") == 0)
|
||||
{
|
||||
mVerifyPeerCert = false;
|
||||
}
|
||||
else if (strcmp(argv[1], "true") != 0)
|
||||
{
|
||||
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
}
|
||||
otCoapSecureSetSslAuthMode(mInterpreter.mInstance, mVerifyPeerCert);
|
||||
SuccessOrExit(error = otCoapSecureStart(mInterpreter.mInstance, OT_DEFAULT_COAP_SECURE_PORT));
|
||||
otCoapSecureSetClientConnectedCallback(mInterpreter.mInstance, &CoapSecure::HandleClientConnect, this);
|
||||
#if CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
|
||||
otCoapSecureSetDefaultHandler(mInterpreter.mInstance, &CoapSecure::DefaultHandler, this);
|
||||
#endif // CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
if (mUseCertificate)
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("Verify Peer Certificate: %s. Coap Secure service started: ",
|
||||
mVerifyPeerCert ? "true" : "false");
|
||||
}
|
||||
#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
mInterpreter.mServer->OutputFormat("%s\r\n", sCommands[i].mName);
|
||||
}
|
||||
else if (strcmp(argv[0], "set") == 0)
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError CoapSecure::ProcessResource(int argc, char *argv[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
if (strcmp(argv[1], "psk") == 0)
|
||||
{
|
||||
if (argc > 3)
|
||||
{
|
||||
size_t length;
|
||||
VerifyOrExit(strlen(argv[1]) < kMaxUriLength, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
length = strlen(argv[2]);
|
||||
VerifyOrExit(length <= sizeof(mPsk), error = OT_ERROR_INVALID_ARGS);
|
||||
mPskLength = static_cast<uint8_t>(length);
|
||||
memcpy(mPsk, argv[2], mPskLength);
|
||||
|
||||
length = strlen(argv[3]);
|
||||
VerifyOrExit(length <= sizeof(mPskId), error = OT_ERROR_INVALID_ARGS);
|
||||
mPskIdLength = static_cast<uint8_t>(length);
|
||||
memcpy(mPskId, argv[3], mPskIdLength);
|
||||
|
||||
SuccessOrExit(
|
||||
error = otCoapSecureSetPsk(mInterpreter.mInstance, mPsk, mPskLength, mPskId, mPskIdLength));
|
||||
mUseCertificate = false;
|
||||
mInterpreter.mServer->OutputFormat("Coap Secure set PSK: ");
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[1], "x509") == 0)
|
||||
{
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
SuccessOrExit(error = otCoapSecureSetCertificate(
|
||||
mInterpreter.mInstance, (const uint8_t *)OT_CLI_COAPS_X509_CERT,
|
||||
sizeof(OT_CLI_COAPS_X509_CERT), (const uint8_t *)OT_CLI_COAPS_PRIV_KEY,
|
||||
sizeof(OT_CLI_COAPS_PRIV_KEY)));
|
||||
|
||||
SuccessOrExit(error = otCoapSecureSetCaCertificateChain(
|
||||
mInterpreter.mInstance, (const uint8_t *)OT_CLI_COAPS_TRUSTED_ROOT_CERTIFICATE,
|
||||
sizeof(OT_CLI_COAPS_TRUSTED_ROOT_CERTIFICATE)));
|
||||
mUseCertificate = true;
|
||||
|
||||
mInterpreter.mServer->OutputFormat("Coap Secure set own .X509 certificate: ");
|
||||
#else
|
||||
ExitNow(error = OT_ERROR_DISABLED_FEATURE);
|
||||
#endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[0], "connect") == 0)
|
||||
{
|
||||
// Destination IPv6 address
|
||||
if (argc > 1)
|
||||
{
|
||||
otSockAddr sockaddr;
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
SuccessOrExit(error = otIp6AddressFromString(argv[1], &sockaddr.mAddress));
|
||||
sockaddr.mPort = OT_DEFAULT_COAP_SECURE_PORT;
|
||||
sockaddr.mScopeId = OT_NETIF_INTERFACE_ID_THREAD;
|
||||
|
||||
// check for port specification
|
||||
if (argc > 2)
|
||||
{
|
||||
error = Interpreter::ParseLong(argv[2], value);
|
||||
SuccessOrExit(error);
|
||||
sockaddr.mPort = static_cast<uint16_t>(value);
|
||||
}
|
||||
|
||||
SuccessOrExit(
|
||||
error = otCoapSecureConnect(mInterpreter.mInstance, &sockaddr, &CoapSecure::HandleClientConnect, this));
|
||||
mInterpreter.mServer->OutputFormat("Coap Secure connect: ");
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[0], "resource") == 0)
|
||||
{
|
||||
mResource.mUriPath = mUriPath;
|
||||
mResource.mContext = this;
|
||||
mResource.mHandler = &CoapSecure::HandleServerResponse;
|
||||
mResource.mHandler = &CoapSecure::HandleRequest;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
strlcpy(mUriPath, argv[1], kMaxUriLength);
|
||||
SuccessOrExit(error = otCoapSecureAddResource(mInterpreter.mInstance, &mResource));
|
||||
}
|
||||
|
||||
mInterpreter.mServer->OutputFormat("Resource name is '%s': ", mResource.mUriPath);
|
||||
}
|
||||
else if (strcmp(argv[0], "disconnect") == 0)
|
||||
{
|
||||
otCoapSecureDisconnect(mInterpreter.mInstance);
|
||||
}
|
||||
else if (strcmp(argv[0], "stop") == 0)
|
||||
{
|
||||
if (otCoapSecureIsConnectionActive(mInterpreter.mInstance))
|
||||
{
|
||||
otCoapSecureDisconnect(mInterpreter.mInstance);
|
||||
mShutdownFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[0], "help") == 0)
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("CLI CoAPS help:\r\n\r\n");
|
||||
mInterpreter.mServer->OutputFormat(">'coaps start (false)' "
|
||||
": start coap secure service, false disable peer cert verification\r\n");
|
||||
mInterpreter.mServer->OutputFormat(">'coaps set psk <psk> <client id>' "
|
||||
": set Preshared Key and Client Identity (Ciphersuite PSK_AES128)\r\n");
|
||||
mInterpreter.mServer->OutputFormat(">'coaps set x509' "
|
||||
": set X509 Cert und Private Key (Ciphersuite ECDHE_ECDSA_AES128)\r\n");
|
||||
mInterpreter.mServer->OutputFormat(">'coaps connect <servers ipv6 addr> (port)' "
|
||||
": start dtls session with a server\r\n");
|
||||
mInterpreter.mServer->OutputFormat(">'coaps get' 'coaps put' 'coaps post' 'coaps delete' "
|
||||
": interact with coap resource from server, ipv6 is not need as client\r\n");
|
||||
mInterpreter.mServer->OutputFormat(
|
||||
" >> args:(ipv6_addr_srv) <coap_src> and, if you have payload: <con> <payload>\r\n");
|
||||
mInterpreter.mServer->OutputFormat(">'coaps resource <uri>' "
|
||||
": add a coap server resource with 'helloWorld' as content.\r\n");
|
||||
mInterpreter.mServer->OutputFormat(">'coaps disconnect' "
|
||||
": stop dtls session with a server\r\n");
|
||||
mInterpreter.mServer->OutputFormat(">'coaps stop' "
|
||||
": stop coap secure service\r\n");
|
||||
mInterpreter.mServer->OutputFormat("\r\n legend: <>: must, (): opt "
|
||||
"\r\n");
|
||||
mInterpreter.mServer->OutputFormat("\r\n");
|
||||
strlcpy(mUriPath, argv[1], kMaxUriLength);
|
||||
SuccessOrExit(error = otCoapSecureAddResource(mInterpreter.mInstance, &mResource));
|
||||
}
|
||||
else
|
||||
{
|
||||
error = ProcessRequest(argc, argv);
|
||||
mInterpreter.mServer->OutputFormat("%s\r\n", mResource.mUriPath);
|
||||
}
|
||||
|
||||
exit:
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError CoapSecure::ProcessStart(int argc, char *argv[])
|
||||
{
|
||||
otError error;
|
||||
bool verifyPeerCert = true;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
if (strcmp(argv[1], "false") == 0)
|
||||
{
|
||||
verifyPeerCert = false;
|
||||
}
|
||||
else if (strcmp(argv[1], "true") != 0)
|
||||
{
|
||||
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
}
|
||||
|
||||
otCoapSecureSetSslAuthMode(mInterpreter.mInstance, verifyPeerCert);
|
||||
otCoapSecureSetClientConnectedCallback(mInterpreter.mInstance, &CoapSecure::HandleConnected, this);
|
||||
|
||||
#if CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
|
||||
otCoapSecureSetDefaultHandler(mInterpreter.mInstance, &CoapSecure::DefaultHandler, this);
|
||||
#endif
|
||||
|
||||
SuccessOrExit(error = otCoapSecureStart(mInterpreter.mInstance, OT_DEFAULT_COAP_SECURE_PORT));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void CoapSecure::Stop(void)
|
||||
otError CoapSecure::ProcessStop(int argc, char *argv[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(argc);
|
||||
OT_UNUSED_VARIABLE(argv);
|
||||
|
||||
otCoapRemoveResource(mInterpreter.mInstance, &mResource);
|
||||
otCoapSecureStop(mInterpreter.mInstance);
|
||||
mInterpreter.mServer->OutputFormat("Coap Secure service stopped");
|
||||
}
|
||||
|
||||
void OTCALL CoapSecure::HandleClientConnect(bool aConnected, void *aContext)
|
||||
{
|
||||
static_cast<CoapSecure *>(aContext)->HandleClientConnect(aConnected);
|
||||
}
|
||||
|
||||
void CoapSecure::HandleClientConnect(bool aConnected)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aConnected);
|
||||
|
||||
if (aConnected)
|
||||
if (otCoapSecureIsConnectionActive(mInterpreter.mInstance))
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("CoAP Secure connected!\r\n> ");
|
||||
otCoapSecureDisconnect(mInterpreter.mInstance);
|
||||
mShutdownFlag = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mShutdownFlag)
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("CoAP Secure not connected or disconnected.\r\n> ");
|
||||
}
|
||||
else
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("CoAP Secure disconnected before stop.\r\n> ");
|
||||
Stop();
|
||||
mInterpreter.mServer->OutputFormat(" Done\r\n> ");
|
||||
mShutdownFlag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OTCALL CoapSecure::HandleServerResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
static_cast<CoapSecure *>(aContext)->HandleServerResponse(aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
void CoapSecure::HandleServerResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otMessage *responseMessage = NULL;
|
||||
otCoapCode responseCode = OT_COAP_CODE_EMPTY;
|
||||
char responseContent[] = "helloWorld";
|
||||
|
||||
mInterpreter.mServer->OutputFormat(
|
||||
"Received coap secure request from [%x:%x:%x:%x:%x:%x:%x:%x]: ",
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[0]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[1]),
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[2]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[3]),
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[4]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[5]),
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[6]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[7]));
|
||||
|
||||
switch (otCoapMessageGetCode(aMessage))
|
||||
{
|
||||
case OT_COAP_CODE_GET:
|
||||
mInterpreter.mServer->OutputFormat("GET");
|
||||
break;
|
||||
|
||||
case OT_COAP_CODE_DELETE:
|
||||
mInterpreter.mServer->OutputFormat("DELETE");
|
||||
break;
|
||||
|
||||
case OT_COAP_CODE_PUT:
|
||||
mInterpreter.mServer->OutputFormat("PUT");
|
||||
break;
|
||||
|
||||
case OT_COAP_CODE_POST:
|
||||
mInterpreter.mServer->OutputFormat("POST");
|
||||
break;
|
||||
|
||||
default:
|
||||
mInterpreter.mServer->OutputFormat("Undefined\r\n");
|
||||
return;
|
||||
Stop();
|
||||
}
|
||||
|
||||
PrintPayload(aMessage);
|
||||
|
||||
if ((otCoapMessageGetType(aMessage) == OT_COAP_TYPE_CONFIRMABLE) ||
|
||||
(otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET))
|
||||
{
|
||||
if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
|
||||
{
|
||||
responseCode = OT_COAP_CODE_CONTENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
responseCode = OT_COAP_CODE_VALID;
|
||||
}
|
||||
|
||||
responseMessage = otCoapNewMessage(mInterpreter.mInstance, NULL);
|
||||
VerifyOrExit(responseMessage != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
otCoapMessageInit(responseMessage, OT_COAP_TYPE_ACKNOWLEDGMENT, responseCode);
|
||||
otCoapMessageSetMessageId(responseMessage, otCoapMessageGetMessageId(aMessage));
|
||||
otCoapMessageSetToken(responseMessage, otCoapMessageGetToken(aMessage), otCoapMessageGetTokenLength(aMessage));
|
||||
|
||||
if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
|
||||
{
|
||||
otCoapMessageSetPayloadMarker(responseMessage);
|
||||
}
|
||||
|
||||
if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
|
||||
{
|
||||
SuccessOrExit(error = otMessageAppend(responseMessage, &responseContent, sizeof(responseContent)));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = otCoapSecureSendResponse(mInterpreter.mInstance, responseMessage, aMessageInfo));
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (error != OT_ERROR_NONE && responseMessage != NULL)
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("Cannot send coap secure response message: Error %d: %s\r\n", error,
|
||||
otThreadErrorToString(error));
|
||||
otMessageFree(responseMessage);
|
||||
}
|
||||
else if (responseCode >= OT_COAP_CODE_RESPONSE_MIN)
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("coap secure response sent successfully!\r\n");
|
||||
}
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError CoapSecure::ProcessRequest(int argc, char *argv[])
|
||||
@@ -541,15 +284,13 @@ otError CoapSecure::ProcessRequest(int argc, char *argv[])
|
||||
|
||||
if ((coapType == OT_COAP_TYPE_CONFIRMABLE) || (coapCode == OT_COAP_CODE_GET))
|
||||
{
|
||||
error = otCoapSecureSendRequest(mInterpreter.mInstance, message, &CoapSecure::HandleClientResponse, this);
|
||||
error = otCoapSecureSendRequest(mInterpreter.mInstance, message, &CoapSecure::HandleResponse, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = otCoapSecureSendRequest(mInterpreter.mInstance, message, NULL, NULL);
|
||||
}
|
||||
|
||||
mInterpreter.mServer->OutputFormat("Sending coap secure request: ");
|
||||
|
||||
exit:
|
||||
|
||||
if ((error != OT_ERROR_NONE) && (message != NULL))
|
||||
@@ -560,33 +301,268 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void OTCALL CoapSecure::HandleClientResponse(void * aContext,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
otError aError)
|
||||
otError CoapSecure::ProcessConnect(int argc, char *argv[])
|
||||
{
|
||||
static_cast<CoapSecure *>(aContext)->HandleClientResponse(aMessage, aMessageInfo, aError);
|
||||
otError error;
|
||||
otSockAddr sockaddr;
|
||||
|
||||
VerifyOrExit(argc > 1, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
// Destination IPv6 address
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
SuccessOrExit(error = otIp6AddressFromString(argv[1], &sockaddr.mAddress));
|
||||
sockaddr.mPort = OT_DEFAULT_COAP_SECURE_PORT;
|
||||
sockaddr.mScopeId = OT_NETIF_INTERFACE_ID_THREAD;
|
||||
|
||||
// check for port specification
|
||||
if (argc > 2)
|
||||
{
|
||||
long value;
|
||||
|
||||
error = Interpreter::ParseLong(argv[2], value);
|
||||
SuccessOrExit(error);
|
||||
sockaddr.mPort = static_cast<uint16_t>(value);
|
||||
}
|
||||
|
||||
SuccessOrExit(error = otCoapSecureConnect(mInterpreter.mInstance, &sockaddr, &CoapSecure::HandleConnected, this));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void CoapSecure::HandleClientResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError)
|
||||
otError CoapSecure::ProcessDisconnect(int argc, char *argv[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(argc);
|
||||
OT_UNUSED_VARIABLE(argv);
|
||||
|
||||
otCoapSecureDisconnect(mInterpreter.mInstance);
|
||||
|
||||
return OT_ERROR_NONE;
|
||||
}
|
||||
|
||||
otError CoapSecure::ProcessPsk(int argc, char *argv[])
|
||||
{
|
||||
otError error;
|
||||
size_t length;
|
||||
|
||||
VerifyOrExit(argc > 2, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
length = strlen(argv[1]);
|
||||
VerifyOrExit(length <= sizeof(mPsk), error = OT_ERROR_INVALID_ARGS);
|
||||
mPskLength = static_cast<uint8_t>(length);
|
||||
memcpy(mPsk, argv[1], mPskLength);
|
||||
|
||||
length = strlen(argv[2]);
|
||||
VerifyOrExit(length <= sizeof(mPskId), error = OT_ERROR_INVALID_ARGS);
|
||||
mPskIdLength = static_cast<uint8_t>(length);
|
||||
memcpy(mPskId, argv[2], mPskIdLength);
|
||||
|
||||
SuccessOrExit(error = otCoapSecureSetPsk(mInterpreter.mInstance, mPsk, mPskLength, mPskId, mPskIdLength));
|
||||
mUseCertificate = false;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError CoapSecure::ProcessX509(int argc, char *argv[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(argc);
|
||||
OT_UNUSED_VARIABLE(argv);
|
||||
|
||||
#ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
otError error;
|
||||
|
||||
SuccessOrExit(error = otCoapSecureSetCertificate(
|
||||
mInterpreter.mInstance, (const uint8_t *)OT_CLI_COAPS_X509_CERT, sizeof(OT_CLI_COAPS_X509_CERT),
|
||||
(const uint8_t *)OT_CLI_COAPS_PRIV_KEY, sizeof(OT_CLI_COAPS_PRIV_KEY)));
|
||||
|
||||
SuccessOrExit(error = otCoapSecureSetCaCertificateChain(mInterpreter.mInstance,
|
||||
(const uint8_t *)OT_CLI_COAPS_TRUSTED_ROOT_CERTIFICATE,
|
||||
sizeof(OT_CLI_COAPS_TRUSTED_ROOT_CERTIFICATE)));
|
||||
mUseCertificate = true;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
#else
|
||||
return OT_ERROR_DISABLED_FEATURE
|
||||
#endif
|
||||
}
|
||||
|
||||
otError CoapSecure::Process(int argc, char *argv[])
|
||||
{
|
||||
otError error = OT_ERROR_PARSE;
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
ProcessHelp(0, NULL);
|
||||
error = OT_ERROR_INVALID_ARGS;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < OT_ARRAY_LENGTH(sCommands); i++)
|
||||
{
|
||||
if (strcmp(argv[0], sCommands[i].mName) == 0)
|
||||
{
|
||||
error = (this->*sCommands[i].mCommand)(argc, argv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void CoapSecure::Stop(void)
|
||||
{
|
||||
otCoapRemoveResource(mInterpreter.mInstance, &mResource);
|
||||
otCoapSecureStop(mInterpreter.mInstance);
|
||||
}
|
||||
|
||||
void CoapSecure::HandleConnected(bool aConnected, void *aContext)
|
||||
{
|
||||
static_cast<CoapSecure *>(aContext)->HandleConnected(aConnected);
|
||||
}
|
||||
|
||||
void CoapSecure::HandleConnected(bool aConnected)
|
||||
{
|
||||
if (aConnected)
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("coaps connected\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("coaps disconnected\r\n");
|
||||
|
||||
if (mShutdownFlag)
|
||||
{
|
||||
Stop();
|
||||
mShutdownFlag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CoapSecure::HandleRequest(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
static_cast<CoapSecure *>(aContext)->HandleRequest(aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
void CoapSecure::HandleRequest(otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otMessage *responseMessage = NULL;
|
||||
otCoapCode responseCode = OT_COAP_CODE_EMPTY;
|
||||
char responseContent[] = "helloWorld";
|
||||
|
||||
mInterpreter.mServer->OutputFormat(
|
||||
"coaps request from [%x:%x:%x:%x:%x:%x:%x:%x] ", HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[0]),
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[1]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[2]),
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[3]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[4]),
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[5]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[6]),
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[7]));
|
||||
|
||||
switch (otCoapMessageGetCode(aMessage))
|
||||
{
|
||||
case OT_COAP_CODE_GET:
|
||||
mInterpreter.mServer->OutputFormat("GET");
|
||||
break;
|
||||
|
||||
case OT_COAP_CODE_DELETE:
|
||||
mInterpreter.mServer->OutputFormat("DELETE");
|
||||
break;
|
||||
|
||||
case OT_COAP_CODE_PUT:
|
||||
mInterpreter.mServer->OutputFormat("PUT");
|
||||
break;
|
||||
|
||||
case OT_COAP_CODE_POST:
|
||||
mInterpreter.mServer->OutputFormat("POST");
|
||||
break;
|
||||
|
||||
default:
|
||||
mInterpreter.mServer->OutputFormat("Undefined\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
PrintPayload(aMessage);
|
||||
|
||||
if ((otCoapMessageGetType(aMessage) == OT_COAP_TYPE_CONFIRMABLE) ||
|
||||
(otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET))
|
||||
{
|
||||
if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
|
||||
{
|
||||
responseCode = OT_COAP_CODE_CONTENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
responseCode = OT_COAP_CODE_VALID;
|
||||
}
|
||||
|
||||
responseMessage = otCoapNewMessage(mInterpreter.mInstance, NULL);
|
||||
VerifyOrExit(responseMessage != NULL, error = OT_ERROR_NO_BUFS);
|
||||
|
||||
otCoapMessageInit(responseMessage, OT_COAP_TYPE_ACKNOWLEDGMENT, responseCode);
|
||||
otCoapMessageSetMessageId(responseMessage, otCoapMessageGetMessageId(aMessage));
|
||||
otCoapMessageSetToken(responseMessage, otCoapMessageGetToken(aMessage), otCoapMessageGetTokenLength(aMessage));
|
||||
|
||||
if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
|
||||
{
|
||||
otCoapMessageSetPayloadMarker(responseMessage);
|
||||
}
|
||||
|
||||
if (otCoapMessageGetCode(aMessage) == OT_COAP_CODE_GET)
|
||||
{
|
||||
SuccessOrExit(error = otMessageAppend(responseMessage, &responseContent, sizeof(responseContent)));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = otCoapSecureSendResponse(mInterpreter.mInstance, responseMessage, aMessageInfo));
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
if (responseMessage != NULL)
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("coaps send response error %d: %s\r\n", error,
|
||||
otThreadErrorToString(error));
|
||||
otMessageFree(responseMessage);
|
||||
}
|
||||
}
|
||||
else if (responseCode >= OT_COAP_CODE_RESPONSE_MIN)
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("coaps response sent\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
void CoapSecure::HandleResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError)
|
||||
{
|
||||
static_cast<CoapSecure *>(aContext)->HandleResponse(aMessage, aMessageInfo, aError);
|
||||
}
|
||||
|
||||
void CoapSecure::HandleResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aMessageInfo);
|
||||
|
||||
if (aError != OT_ERROR_NONE)
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("Error receiving coap secure response message: Error %d: %s\r\n", aError,
|
||||
mInterpreter.mServer->OutputFormat("coaps receive response error %d: %s\r\n", aError,
|
||||
otThreadErrorToString(aError));
|
||||
}
|
||||
else
|
||||
{
|
||||
mInterpreter.mServer->OutputFormat("Received coap secure response");
|
||||
PrintHeaderInfos(aMessage);
|
||||
mInterpreter.mServer->OutputFormat(
|
||||
"coaps response from [%x:%x:%x:%x:%x:%x:%x:%x]", HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[0]),
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[1]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[2]),
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[3]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[4]),
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[5]), HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[6]),
|
||||
HostSwap16(aMessageInfo->mPeerAddr.mFields.m16[7]));
|
||||
|
||||
PrintPayload(aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
#if CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
|
||||
void OTCALL CoapSecure::DefaultHandler(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
void CoapSecure::DefaultHandler(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
|
||||
{
|
||||
static_cast<CoapSecure *>(aContext)->DefaultHandler(aMessage, aMessageInfo);
|
||||
}
|
||||
@@ -610,8 +586,7 @@ void CoapSecure::DefaultHandler(otMessage *aMessage, const otMessageInfo *aMessa
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
mInterpreter.mServer->OutputFormat("Default handler called.\r\n> ");
|
||||
return;
|
||||
}
|
||||
#endif // CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
|
||||
|
||||
|
||||
+24
-14
@@ -79,36 +79,46 @@ private:
|
||||
kPskIdMaxLength = 32
|
||||
};
|
||||
|
||||
void PrintHeaderInfos(otMessage *aMessage) const;
|
||||
struct Command
|
||||
{
|
||||
const char *mName;
|
||||
otError (CoapSecure::*mCommand)(int argc, char *argv[]);
|
||||
};
|
||||
|
||||
void PrintPayload(otMessage *aMessage) const;
|
||||
|
||||
otError ProcessHelp(int argc, char *argv[]);
|
||||
otError ProcessConnect(int argc, char *argv[]);
|
||||
otError ProcessDisconnect(int argc, char *argv[]);
|
||||
otError ProcessPsk(int argc, char *argv[]);
|
||||
otError ProcessRequest(int argc, char *argv[]);
|
||||
otError ProcessResource(int argc, char *argv[]);
|
||||
otError ProcessStart(int argc, char *argv[]);
|
||||
otError ProcessStop(int argc, char *argv[]);
|
||||
otError ProcessX509(int argc, char *argv[]);
|
||||
|
||||
void Stop(void);
|
||||
|
||||
static void OTCALL HandleServerResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
void HandleServerResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
static void HandleRequest(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
void HandleRequest(otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
|
||||
static void OTCALL HandleClientResponse(void * aContext,
|
||||
otMessage * aMessage,
|
||||
const otMessageInfo *aMessageInfo,
|
||||
otError aError);
|
||||
void HandleClientResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
|
||||
static void HandleResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
|
||||
void HandleResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aError);
|
||||
|
||||
#if CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
|
||||
static void OTCALL DefaultHandler(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
void DefaultHandler(otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
static void DefaultHandler(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
void DefaultHandler(otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
#endif // CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER
|
||||
|
||||
static void OTCALL HandleClientConnect(bool aConnected, void *aContext);
|
||||
void HandleClientConnect(bool aConnected);
|
||||
static void HandleConnected(bool aConnected, void *aContext);
|
||||
void HandleConnected(bool aConnected);
|
||||
|
||||
static const Command sCommands[];
|
||||
Interpreter & mInterpreter;
|
||||
|
||||
otCoapResource mResource;
|
||||
char mUriPath[kMaxUriLength];
|
||||
|
||||
Interpreter &mInterpreter;
|
||||
|
||||
bool mShutdownFlag;
|
||||
bool mUseCertificate;
|
||||
uint8_t mPsk[kPskMaxLength];
|
||||
|
||||
@@ -854,7 +854,7 @@ class otCli:
|
||||
self._expect('Done')
|
||||
|
||||
def coaps_start_psk(self, psk, pskIdentity):
|
||||
cmd = 'coaps set psk ' + psk + ' ' + pskIdentity
|
||||
cmd = 'coaps psk ' + psk + ' ' + pskIdentity
|
||||
self.send_command(cmd)
|
||||
self._expect('Done')
|
||||
|
||||
@@ -863,7 +863,7 @@ class otCli:
|
||||
self._expect('Done')
|
||||
|
||||
def coaps_start_x509(self):
|
||||
cmd = 'coaps set x509'
|
||||
cmd = 'coaps x509'
|
||||
self.send_command(cmd)
|
||||
self._expect('Done')
|
||||
|
||||
@@ -898,7 +898,7 @@ class otCli:
|
||||
else:
|
||||
timeout = 5
|
||||
|
||||
self._expect('CoAP Secure connected!', timeout=timeout)
|
||||
self._expect('coaps connected', timeout=timeout)
|
||||
|
||||
def coaps_disconnect(self):
|
||||
cmd = 'coaps disconnect'
|
||||
@@ -916,7 +916,7 @@ class otCli:
|
||||
else:
|
||||
timeout = 5
|
||||
|
||||
self._expect('Received coap secure response', timeout=timeout)
|
||||
self._expect('coaps response', timeout=timeout)
|
||||
|
||||
def commissioner_mgmtset(self, tlvs_binary):
|
||||
cmd = 'commissioner mgmtset binary ' + tlvs_binary
|
||||
|
||||
Reference in New Issue
Block a user