[IOT-1942] Add support for diagnostic payloads.
authorTodd Malsbary <todd.malsbary@intel.com>
Tue, 11 Apr 2017 18:42:10 +0000 (11:42 -0700)
committerDan Mihai <Daniel.Mihai@microsoft.com>
Tue, 18 Apr 2017 15:46:42 +0000 (15:46 +0000)
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>
resource/csdk/include/octypes.h
resource/csdk/stack/include/ocpayload.h
resource/csdk/stack/src/ocpayload.c
resource/csdk/stack/src/ocpayloadconvert.c
resource/csdk/stack/src/ocpayloadparse.c
resource/csdk/stack/src/ocserverrequest.c
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/test/gtest_helper.h
resource/csdk/stack/test/stacktests.cpp

index 524dad6..111e34c 100644 (file)
@@ -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.
index 66562b7..5565710 100644 (file)
@@ -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);
index 957eeef..27c2f98 100644 (file)
@@ -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)
 {
index 0e76b30..5cdbf55 100755 (executable)
@@ -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)
 {
index 2dcd6c6..68ed73b 100755 (executable)
@@ -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;
+}
index fddd9c1..4a67eb3 100644 (file)
@@ -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);
index 4b24117..7361c80 100644 (file)
@@ -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),
index a3c73cb..b68799b 100644 (file)
@@ -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;
             }
index 8e4a8c9..b5b53ee 100644 (file)
@@ -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();
+}