Commit 57672039 authored by Todd Malsbary's avatar Todd Malsbary Committed by Dan Mihai

[IOT-1942] Add support for diagnostic payloads.

Bug: https://jira.iotivity.org/browse/IOT-1942
Change-Id: Ia4d761bfc49d646b2e1514844826411df272d5a4
Signed-off-by: default avatarTodd Malsbary <todd.malsbary@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/18721Tested-by: default avatarjenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: default avatarDan Mihai <Daniel.Mihai@microsoft.com>
parent df218cd3
......@@ -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.
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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)
{
......
......@@ -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;
}
......@@ -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);
......
......@@ -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),
......
......@@ -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;
}
......
......@@ -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();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment