/** 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;
/**
} 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.
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);
case PAYLOAD_TYPE_PRESENCE:
OCPresencePayloadDestroy((OCPresencePayload*)payload);
break;
+ case PAYLOAD_TYPE_DIAGNOSTIC:
+ OCDiagnosticPayloadDestroy((OCDiagnosticPayload*)payload);
+ break;
case PAYLOAD_TYPE_SECURITY:
OCSecurityPayloadDestroy((OCSecurityPayload*)payload);
break;
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)
{
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);
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:
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)
{
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,
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;
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;
+}
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);
}
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
}
// 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),
break;
}
OCProcess();
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
return m_called ? OC_STACK_OK : OC_STACK_TIMEOUT;
}
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();
+}