diff options
author | Todd Malsbary <todd.malsbary@intel.com> | 2017-04-11 11:42:10 -0700 |
---|---|---|
committer | Dan Mihai <Daniel.Mihai@microsoft.com> | 2017-04-18 15:46:42 +0000 |
commit | 5767203911c874ab2b2b027db372996b6904e99b (patch) | |
tree | 05468bbaf88406a9e4d58d4e4e7878120620b528 | |
parent | df218cd3941360bad0e83c8d051ae0dc716c56f3 (diff) | |
download | iotivity-5767203911c874ab2b2b027db372996b6904e99b.tar.gz iotivity-5767203911c874ab2b2b027db372996b6904e99b.tar.bz2 iotivity-5767203911c874ab2b2b027db372996b6904e99b.zip |
[IOT-1942] Add support for diagnostic payloads.
Bug: https://jira.iotivity.org/browse/IOT-1942
Change-Id: Ia4d761bfc49d646b2e1514844826411df272d5a4
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/18721
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
-rw-r--r-- | resource/csdk/include/octypes.h | 10 | ||||
-rw-r--r-- | resource/csdk/stack/include/ocpayload.h | 4 | ||||
-rw-r--r-- | resource/csdk/stack/src/ocpayload.c | 31 | ||||
-rwxr-xr-x | resource/csdk/stack/src/ocpayloadconvert.c | 20 | ||||
-rwxr-xr-x | resource/csdk/stack/src/ocpayloadparse.c | 34 | ||||
-rw-r--r-- | resource/csdk/stack/src/ocserverrequest.c | 3 | ||||
-rw-r--r-- | resource/csdk/stack/src/ocstack.c | 18 | ||||
-rw-r--r-- | resource/csdk/stack/test/gtest_helper.h | 1 | ||||
-rw-r--r-- | resource/csdk/stack/test/stacktests.cpp | 61 |
9 files changed, 176 insertions, 6 deletions
diff --git a/resource/csdk/include/octypes.h b/resource/csdk/include/octypes.h index 524dad642..111e34c22 100644 --- a/resource/csdk/include/octypes.h +++ b/resource/csdk/include/octypes.h @@ -1418,7 +1418,9 @@ typedef enum /** The payload is an OCSecurityPayload */ PAYLOAD_TYPE_SECURITY, /** The payload is an OCPresencePayload */ - PAYLOAD_TYPE_PRESENCE + PAYLOAD_TYPE_PRESENCE, + /** The payload is an OCDiagnosticPayload */ + PAYLOAD_TYPE_DIAGNOSTIC } OCPayloadType; /** @@ -1578,6 +1580,12 @@ typedef struct } OCPresencePayload; #endif +typedef struct +{ + OCPayload base; + char* message; +} OCDiagnosticPayload; + /** * Incoming requests handled by the server. Requests are passed in as a parameter to the * OCEntityHandler callback API. diff --git a/resource/csdk/stack/include/ocpayload.h b/resource/csdk/stack/include/ocpayload.h index 66562b7a3..556571027 100644 --- a/resource/csdk/stack/include/ocpayload.h +++ b/resource/csdk/stack/include/ocpayload.h @@ -264,6 +264,10 @@ OCPresencePayload* OCPresencePayloadCreate(uint32_t seqNum, uint32_t maxAge, OCPresenceTrigger trigger, const char* resourceType); void OCPresencePayloadDestroy(OCPresencePayload* payload); +// Diagnostic Payload +OCDiagnosticPayload* OCDiagnosticPayloadCreate(const char *message); +void OCDiagnosticPayloadDestroy(OCDiagnosticPayload* payload); + // Helper API OCStringLL* CloneOCStringLL (OCStringLL* ll); void OCFreeOCStringLL(OCStringLL* ll); diff --git a/resource/csdk/stack/src/ocpayload.c b/resource/csdk/stack/src/ocpayload.c index 957eeeff4..27c2f98f2 100644 --- a/resource/csdk/stack/src/ocpayload.c +++ b/resource/csdk/stack/src/ocpayload.c @@ -59,6 +59,9 @@ void OCPayloadDestroy(OCPayload* payload) case PAYLOAD_TYPE_PRESENCE: OCPresencePayloadDestroy((OCPresencePayload*)payload); break; + case PAYLOAD_TYPE_DIAGNOSTIC: + OCDiagnosticPayloadDestroy((OCDiagnosticPayload*)payload); + break; case PAYLOAD_TYPE_SECURITY: OCSecurityPayloadDestroy((OCSecurityPayload*)payload); break; @@ -2137,6 +2140,34 @@ void OCPresencePayloadDestroy(OCPresencePayload* payload) OICFree(payload); } +OCDiagnosticPayload* OCDiagnosticPayloadCreate(const char* message) +{ + if (!message) + { + return NULL; + } + + OCDiagnosticPayload* payload = (OCDiagnosticPayload*)OICCalloc(1, sizeof(OCDiagnosticPayload)); + if (!payload) + { + return NULL; + } + + payload->base.type = PAYLOAD_TYPE_DIAGNOSTIC; + payload->message = OICStrdup(message); + return payload; +} + +void OCDiagnosticPayloadDestroy(OCDiagnosticPayload* payload) +{ + if (!payload) + { + return; + } + OICFree(payload->message); + OICFree(payload); +} + OCStackResult OCLinksPayloadValueCreate(const char* resourceUri, OCRepPayloadValue** linksRepPayloadValue, OCDevAddr* devAddr) { diff --git a/resource/csdk/stack/src/ocpayloadconvert.c b/resource/csdk/stack/src/ocpayloadconvert.c index 0e76b306e..5cdbf5520 100755 --- a/resource/csdk/stack/src/ocpayloadconvert.c +++ b/resource/csdk/stack/src/ocpayloadconvert.c @@ -54,6 +54,8 @@ static int64_t OCConvertRepPayload(OCRepPayload *payload, uint8_t *outPayload, s static int64_t OCConvertRepMap(CborEncoder *map, const OCRepPayload *payload); static int64_t OCConvertPresencePayload(OCPresencePayload *payload, uint8_t *outPayload, size_t *size); +static int64_t OCConvertDiagnosticPayload(OCDiagnosticPayload *payload, uint8_t *outPayload, + size_t *size); static int64_t OCConvertSecurityPayload(OCSecurityPayload *payload, uint8_t *outPayload, size_t *size); static int64_t OCConvertSingleRepPayloadValue(CborEncoder *parent, const OCRepPayloadValue *value); @@ -147,6 +149,8 @@ static int64_t OCConvertPayloadHelper(OCPayload* payload, OCPayloadFormat format return OCConvertRepPayload((OCRepPayload*)payload, outPayload, size); case PAYLOAD_TYPE_PRESENCE: return OCConvertPresencePayload((OCPresencePayload*)payload, outPayload, size); + case PAYLOAD_TYPE_DIAGNOSTIC: + return OCConvertDiagnosticPayload((OCDiagnosticPayload*)payload, outPayload, size); case PAYLOAD_TYPE_SECURITY: return OCConvertSecurityPayload((OCSecurityPayload*)payload, outPayload, size); default: @@ -1011,6 +1015,22 @@ exit: return checkError(err, &encoder, outPayload, size); } +static int64_t OCConvertDiagnosticPayload(OCDiagnosticPayload *payload, uint8_t *outPayload, + size_t *size) +{ + int64_t err = CborNoError; + CborEncoder encoder; + + cbor_encoder_init(&encoder, outPayload, *size, 0); + + // Message + err |= cbor_encode_text_string(&encoder, payload->message, strlen(payload->message)); + VERIFY_CBOR_SUCCESS(TAG, err, "Failed adding message"); + +exit: + return checkError(err, &encoder, outPayload, size); +} + static int64_t AddTextStringToMap(CborEncoder* map, const char* key, size_t keylen, const char* value) { diff --git a/resource/csdk/stack/src/ocpayloadparse.c b/resource/csdk/stack/src/ocpayloadparse.c index 2dcd6c602..68ed73bb9 100755 --- a/resource/csdk/stack/src/ocpayloadparse.c +++ b/resource/csdk/stack/src/ocpayloadparse.c @@ -50,6 +50,7 @@ static OCStackResult OCParseDiscoveryPayload(OCPayload **outPayload, OCPayloadFo static CborError OCParseSingleRepPayload(OCRepPayload **outPayload, CborValue *repParent, bool isRoot); static OCStackResult OCParseRepPayload(OCPayload **outPayload, CborValue *arrayVal); static OCStackResult OCParsePresencePayload(OCPayload **outPayload, CborValue *arrayVal); +static OCStackResult OCParseDiagnosticPayload(OCPayload **outPayload, CborValue *arrayVal); static OCStackResult OCParseSecurityPayload(OCPayload **outPayload, const uint8_t *payload, size_t size); OCStackResult OCParsePayload(OCPayload **outPayload, OCPayloadFormat payloadFormat, @@ -81,6 +82,9 @@ OCStackResult OCParsePayload(OCPayload **outPayload, OCPayloadFormat payloadForm case PAYLOAD_TYPE_PRESENCE: result = OCParsePresencePayload(outPayload, &rootValue); break; + case PAYLOAD_TYPE_DIAGNOSTIC: + result = OCParseDiagnosticPayload(outPayload, &rootValue); + break; case PAYLOAD_TYPE_SECURITY: result = OCParseSecurityPayload(outPayload, payload, payloadSize); break; @@ -1327,3 +1331,33 @@ exit: OCPresencePayloadDestroy(payload); return ret; } + +static OCStackResult OCParseDiagnosticPayload(OCPayload **outPayload, CborValue *rootValue) +{ + OCStackResult ret = OC_STACK_INVALID_PARAM; + OCDiagnosticPayload *payload = NULL; + VERIFY_PARAM_NON_NULL(TAG, outPayload, "Invalid Parameter outPayload"); + + *outPayload = NULL; + + payload = (OCDiagnosticPayload *)OICCalloc(1, sizeof(OCDiagnosticPayload)); + ret = OC_STACK_NO_MEMORY; + VERIFY_PARAM_NON_NULL(TAG, payload, "Failed allocating diagnostic payload"); + payload->base.type = PAYLOAD_TYPE_DIAGNOSTIC; + ret = OC_STACK_MALFORMED_RESPONSE; + + if (cbor_value_is_text_string(rootValue)) + { + size_t len = 0; + CborError err = cbor_value_dup_text_string(rootValue, &payload->message, &len, NULL); + VERIFY_CBOR_SUCCESS(TAG, err, "Failed finding message value"); + } + + *outPayload = (OCPayload *)payload; + return OC_STACK_OK; + +exit: + OIC_LOG(ERROR, TAG, "CBOR error Parse Diagnostic Payload"); + OCDiagnosticPayloadDestroy(payload); + return ret; +} diff --git a/resource/csdk/stack/src/ocserverrequest.c b/resource/csdk/stack/src/ocserverrequest.c index fddd9c1b9..4a67eb3ed 100644 --- a/resource/csdk/stack/src/ocserverrequest.c +++ b/resource/csdk/stack/src/ocserverrequest.c @@ -658,7 +658,8 @@ OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse) return result; } // Add CONTENT_FORMAT OPT if payload exist - if (responseInfo.info.payloadSize > 0) + if (ehResponse->payload->type != PAYLOAD_TYPE_DIAGNOSTIC && + responseInfo.info.payloadSize > 0) { responseInfo.info.payloadFormat = OCToCAPayloadFormat( serverRequest->acceptFormat); diff --git a/resource/csdk/stack/src/ocstack.c b/resource/csdk/stack/src/ocstack.c index 4b24117f3..7361c8074 100644 --- a/resource/csdk/stack/src/ocstack.c +++ b/resource/csdk/stack/src/ocstack.c @@ -1692,9 +1692,18 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp } if (type == PAYLOAD_TYPE_INVALID) { - OIC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s", - cbNode->method, cbNode->requestUri); - type = PAYLOAD_TYPE_REPRESENTATION; + if (responseInfo->info.payloadFormat == CA_FORMAT_UNDEFINED) + { + OIC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_DIAGNOSTIC: %d %s", + cbNode->method, cbNode->requestUri); + type = PAYLOAD_TYPE_DIAGNOSTIC; + } + else + { + OIC_LOG_V(INFO, TAG, "Assuming PAYLOAD_TYPE_REPRESENTATION: %d %s", + cbNode->method, cbNode->requestUri); + type = PAYLOAD_TYPE_REPRESENTATION; + } } } else @@ -1712,7 +1721,8 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp } // In case of error, still want application to receive the error message. - if (OCResultToSuccess(response->result) || PAYLOAD_TYPE_REPRESENTATION == type) + if (OCResultToSuccess(response->result) || PAYLOAD_TYPE_REPRESENTATION == type || + PAYLOAD_TYPE_DIAGNOSTIC == type) { if (OC_STACK_OK != OCParsePayload(&response->payload, CAToOCPayloadFormat(responseInfo->info.payloadFormat), diff --git a/resource/csdk/stack/test/gtest_helper.h b/resource/csdk/stack/test/gtest_helper.h index a3c73cba9..b68799be6 100644 --- a/resource/csdk/stack/test/gtest_helper.h +++ b/resource/csdk/stack/test/gtest_helper.h @@ -168,6 +168,7 @@ namespace iotivity break; } OCProcess(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } return m_called ? OC_STACK_OK : OC_STACK_TIMEOUT; } diff --git a/resource/csdk/stack/test/stacktests.cpp b/resource/csdk/stack/test/stacktests.cpp index 8e4a8c9d9..b5b53eeea 100644 --- a/resource/csdk/stack/test/stacktests.cpp +++ b/resource/csdk/stack/test/stacktests.cpp @@ -2817,3 +2817,64 @@ TEST(LinksPayloadValue, createLinksPayloadValue) EXPECT_EQ(OC_STACK_OK, OCStop()); } + +TEST(DiagnosticPayload, CreateDestroy) +{ + OCDiagnosticPayload *payload; + + payload = NULL; + OCDiagnosticPayloadDestroy(payload); + + payload = OCDiagnosticPayloadCreate(NULL); + ASSERT_TRUE(payload == NULL); + + payload = OCDiagnosticPayloadCreate("message"); + ASSERT_TRUE(payload != NULL); + ASSERT_STREQ("message", payload->message); + OCDiagnosticPayloadDestroy(payload); +} + +static OCEntityHandlerResult DiagnosticPayloadRequest(OCEntityHandlerFlag flag, + OCEntityHandlerRequest *request, void *ctx) +{ + OC_UNUSED(flag); + OC_UNUSED(ctx); + OCEntityHandlerResponse response; + memset(&response, 0, sizeof(response)); + response.requestHandle = request->requestHandle; + response.resourceHandle = request->resource; + response.ehResult = OC_EH_BAD_REQ; + response.payload = (OCPayload*) OCDiagnosticPayloadCreate("message"); + EXPECT_TRUE(response.payload != NULL); + EXPECT_EQ(OC_STACK_OK, OCDoResponse(&response)); + return OC_EH_OK; +} + +static OCStackApplicationResult DiagnosticPayloadResponse(void *ctx, OCDoHandle handle, + OCClientResponse *response) +{ + OC_UNUSED(ctx); + OC_UNUSED(handle); + EXPECT_EQ(OC_STACK_INVALID_QUERY, response->result); + EXPECT_EQ(PAYLOAD_TYPE_DIAGNOSTIC, response->payload->type); + OCDiagnosticPayload *payload = (OCDiagnosticPayload*) response->payload; + EXPECT_STREQ("message", payload->message); + return OC_STACK_DELETE_TRANSACTION; +} + +TEST(DiagnosticPayload, DISABLED_EndToEnd) +{ + EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER)); + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + + OCResourceHandle handle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, "core.light", "oic.if.baseline", "/a/light", + DiagnosticPayloadRequest, NULL, OC_DISCOVERABLE)); + + itst::Callback diagnosticPayloadCB(&DiagnosticPayloadResponse); + EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_GET, "127.0.0.1:5683/a/light", NULL, + 0, CT_DEFAULT, OC_HIGH_QOS, diagnosticPayloadCB, NULL, 0)); + EXPECT_EQ(OC_STACK_OK, diagnosticPayloadCB.Wait(100)); + + OCStop(); +} |