diff --git a/include/openthread.h b/include/openthread.h index 4b684f650..e771d166b 100644 --- a/include/openthread.h +++ b/include/openthread.h @@ -1894,6 +1894,29 @@ OTAPI ThreadError OTCALL otGetParentInfo(otInstance *aInstance, otRouterInfo *aP */ OTAPI uint8_t OTCALL otGetStableNetworkDataVersion(otInstance *aInstance); +/** + * This function pointer is called when an DIAG_GET.rsp is received. + * + * @param[in] aMessage A pointer to the message buffer containing the received DIAG_GET.rsp payload. + * @param[in] aMessageInfo A pointer to the message info for @p aMessage. + * @param[in] aContext A pointer to application-specific context. + * + */ +typedef void (*otReceiveDiagnosticGetCallback)(otMessage aMessage, const otMessageInfo *aMessageInfo, + void *aContext); + +/** + * This function registers a callback to provide received raw DIAG_GET.rsp payload. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aCallback A pointer to a function that is called when an DIAG_GET.rsp is received or + * NULL to disable the callback. + * @param[in] aCallbackContext A pointer to application-specific context. + * + */ +void otSetReceiveDiagnosticGetCallback(otInstance *aInstance, otReceiveDiagnosticGetCallback aCallback, + void *aCallbackContext); + /** * Send a Network Diagnostic Get request * diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index e06edd3c2..333c85da7 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -143,6 +143,7 @@ Interpreter::Interpreter(otInstance *aInstance): memset(mSlaacAddresses, 0, sizeof(mSlaacAddresses)); mInstance->mIp6.mIcmp.SetEchoReplyHandler(&s_HandleEchoResponse, this); otSetStateChangedCallback(mInstance, &Interpreter::s_HandleNetifStateChanged, this); + otSetReceiveDiagnosticGetCallback(mInstance, &Interpreter::s_HandleDiagnosticGetResponse, this); } int Interpreter::Hex2Bin(const char *aHex, uint8_t *aBin, uint16_t aBinLength) @@ -2652,6 +2653,7 @@ void Interpreter::ProcessNetworkDiagnostic(int argc, char *argv[]) if (strcmp(argv[0], "get") == 0) { otSendDiagnosticGet(mInstance, &address, payload, payloadIndex); + return; } else if (strcmp(argv[0], "reset") == 0) { @@ -2662,5 +2664,35 @@ exit: AppendResult(error); } +void Interpreter::s_HandleDiagnosticGetResponse(otMessage aMessage, const otMessageInfo *aMessageInfo, + void *aContext) +{ + static_cast(aContext)->HandleDiagnosticGetResponse(*static_cast(aMessage), + *static_cast(aMessageInfo)); +} + +void Interpreter::HandleDiagnosticGetResponse(Message &aMessage, const Ip6::MessageInfo &) +{ + uint8_t buf[16]; + uint16_t bytesToPrint; + uint16_t bytesPrinted = 0; + uint16_t length = aMessage.GetLength() - aMessage.GetOffset(); + + sServer->OutputFormat("DIAG_GET.rsp: "); + + while (length > 0) + { + bytesToPrint = (length < sizeof(buf)) ? length : sizeof(buf); + aMessage.Read(aMessage.GetOffset() + bytesPrinted, bytesToPrint, buf); + + OutputBytes(buf, static_cast(bytesToPrint)); + + length -= bytesToPrint; + bytesPrinted += bytesToPrint; + } + + sServer->OutputFormat("\r\n"); +} + } // namespace Cli } // namespace Thread diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 032c6e09e..82460889e 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -224,6 +224,7 @@ private: static void s_HandleEnergyReport(uint32_t aChannelMask, const uint8_t *aEnergyList, uint8_t aEnergyListLength, void *aContext); static void s_HandlePanIdConflict(uint16_t aPanId, uint32_t aChannelMask, void *aContext); + static void s_HandleDiagnosticGetResponse(otMessage aMessage, const otMessageInfo *aMessageInfo, void *aContext); void HandleEchoResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); void HandlePingTimer(); @@ -232,6 +233,7 @@ private: void HandleLinkPcapReceive(const RadioPacket *aFrame); void HandleEnergyReport(uint32_t aChannelMask, const uint8_t *aEnergyList, uint8_t aEnergyListLength); void HandlePanIdConflict(uint16_t aPanId, uint32_t aChannelMask); + void HandleDiagnosticGetResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo); static const struct Command sCommands[]; diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp index 0eeb8996f..a0cd00f5e 100644 --- a/src/core/openthread.cpp +++ b/src/core/openthread.cpp @@ -1189,6 +1189,13 @@ exit: #endif + +void otSetReceiveDiagnosticGetCallback(otInstance *aInstance, otReceiveDiagnosticGetCallback aCallback, + void *aCallbackContext) +{ + aInstance->mThreadNetif.GetNetworkDiagnostic().SetReceiveDiagnosticGetCallback(aCallback, aCallbackContext); +} + ThreadError otSendDiagnosticGet(otInstance *aInstance, const otIp6Address *aDestination, const uint8_t aTlvTypes[], uint8_t aCount) { diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp index 7d46fb864..abc801e2d 100644 --- a/src/core/thread/network_diagnostic.cpp +++ b/src/core/thread/network_diagnostic.cpp @@ -62,12 +62,21 @@ NetworkDiagnostic::NetworkDiagnostic(ThreadNetif &aThreadNetif) : mCoapClient(aThreadNetif.GetCoapClient()), mMle(aThreadNetif.GetMle()), mMac(aThreadNetif.GetMac()), - mNetif(aThreadNetif) + mNetif(aThreadNetif), + mReceiveDiagnosticGetCallback(NULL), + mReceiveDiagnosticGetCallbackContext(NULL) { mCoapServer.AddResource(mDiagnosticGet); mCoapServer.AddResource(mDiagnosticReset); } +void NetworkDiagnostic::SetReceiveDiagnosticGetCallback(otReceiveDiagnosticGetCallback aCallback, + void *aCallbackContext) +{ + mReceiveDiagnosticGetCallback = aCallback; + mReceiveDiagnosticGetCallbackContext = aCallbackContext; +} + ThreadError NetworkDiagnostic::SendDiagnosticGet(const Ip6::Address &aDestination, const uint8_t aTlvTypes[], uint8_t aCount) { @@ -79,7 +88,6 @@ ThreadError NetworkDiagnostic::SendDiagnosticGet(const Ip6::Address &aDestinatio sockaddr.mPort = kCoapUdpPort; - header.Init(kCoapTypeConfirmable, kCoapRequestGet); header.SetToken(Coap::Header::kDefaultTokenLength); header.AppendUriPathOptions(OPENTHREAD_URI_DIAGNOSTIC_GET); @@ -121,14 +129,16 @@ void NetworkDiagnostic::HandleDiagnosticGetResponse(void *aContext, otCoapHeader void NetworkDiagnostic::HandleDiagnosticGetResponse(Coap::Header *aHeader, Message *aMessage, const Ip6::MessageInfo *aMessageInfo, ThreadError aResult) { - (void)aMessage; - (void)aMessageInfo; - VerifyOrExit(aResult == kThreadError_None, ;); VerifyOrExit(aHeader->GetCode() == kCoapResponseChanged, ;); otLogInfoNetDiag("Network Diagnostic get response received"); + VerifyOrExit(mReceiveDiagnosticGetCallback != NULL, ;); + + // Call application defined callback. + mReceiveDiagnosticGetCallback(aMessage, aMessageInfo, mReceiveDiagnosticGetCallbackContext); + exit: return; } diff --git a/src/core/thread/network_diagnostic.hpp b/src/core/thread/network_diagnostic.hpp index 539b766a1..dd05b89e1 100644 --- a/src/core/thread/network_diagnostic.hpp +++ b/src/core/thread/network_diagnostic.hpp @@ -72,6 +72,16 @@ public: */ explicit NetworkDiagnostic(ThreadNetif &aThreadNetif); + /** + * This method registers a callback to provide received raw DIAG_GET.rsp payload. + * + * @param[in] aCallback A pointer to a function that is called when an DIAG_GET.rsp is received or + * NULL to disable the callback. + * @param[in] aCallbackContext A pointer to application-specific context. + * + */ + void SetReceiveDiagnosticGetCallback(otReceiveDiagnosticGetCallback aCallback, void *aCallbackContext); + /** * This method sends Diagnostic Get request. * @@ -132,6 +142,9 @@ private: Mle::MleRouter &mMle; Mac::Mac &mMac; ThreadNetif &mNetif; + + otReceiveDiagnosticGetCallback mReceiveDiagnosticGetCallback; + void *mReceiveDiagnosticGetCallbackContext; }; /**