//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#include "rd_payload.h"
-#include <cbor.h>
-
#include "oic_malloc.h"
#include "oic_string.h"
-#ifdef WITH_RD
-#include "rd_payload.h"
-#endif
+#include "octypes.h"
+#include "ocstack.h"
+#include "logger.h"
#define TAG PCF("OCRDPayload")
+#define CBOR_ROOT_ARRAY_LENGTH 2
+
+static void linksPayloadDestroy(OCRDLinksPayload *linkPayload)
+{
+ OCRDLinksPayload *links = linkPayload;
+
+ while (links)
+ {
+ OICFree(links->href);
+ OICFree(links->rt);
+ OICFree(links->itf);
+ OCRDLinksPayload *tmp = links;
+ links = links->next;
+ OICFree(tmp);
+ }
+
+}
+
OCStackResult OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t **outPayload, size_t *size)
{
if (!outPayload || !size)
*size = MAX_REQUEST_LENGTH;
CborEncoder encoder;
- cbor_encoder_init(&encoder, *outPayload, *size, 0);
+ int flags = 0;
+ cbor_encoder_init(&encoder, *outPayload, *size, flags);
OC_LOG_V(DEBUG, TAG, "RD Payload : %d", rdPayload->base.type);
OC_LOG_V(DEBUG, TAG, "RD Payload Type: %d", rdPayload->payloadType);
CborEncoder rootArray;
CborError cborEncoderResult;
- cborEncoderResult = cbor_encoder_create_array(&encoder, &rootArray, 2);
+ cborEncoderResult = cbor_encoder_create_array(&encoder, &rootArray, CBOR_ROOT_ARRAY_LENGTH);
if (CborNoError != cborEncoderResult)
{
OC_LOG_V(ERROR, TAG, "Failed creating cbor array.");
{
cborEncoderResult = cbor_encode_text_string(&map,
OC_RSRVD_RD_DISCOVERY_SEL, sizeof(OC_RSRVD_RD_DISCOVERY_SEL) -1);
- if (CborNoError != cborEncoderResult)
+ if (CborNoError != cborEncoderResult)
{
OC_LOG_V(ERROR, TAG, "Failed setting discovery sel type.");
goto exit;
CborValue *rdCBORPayload = (CborValue *)cborPayload;
OCRDPayload *rdPayload = NULL;
- if (cbor_value_is_map(rdCBORPayload))
+ if (!cbor_value_is_map(rdCBORPayload))
+ {
+ OC_LOG_V(ERROR, TAG, "RD CBOR Payload is not in map format.");
+ return OC_STACK_ERROR;
+ }
+ else
{
CborValue curVal;
CborError cborFindResult;
OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_CONTENT_TYPE value in the payload.");
goto exit;
}
- OC_LOG_V(DEBUG, TAG, "RD Payload Type : %d ", payloadType);
}
rdPayload = OCRDPayloadCreate(payloadType);
goto exit;
}
}
- OC_LOG_V(DEBUG, TAG, "Bias Factor : %d ", biasFactor);
rdPayload->rdDiscovery = OCRDDiscoveryPayloadCreate(biasFactor);
if (!rdPayload->rdDiscovery)
goto no_memory;
}
}
+ else
+ { // TTL
+ int ttl = 0;
+ cborFindResult = cbor_value_map_find_value(rdCBORPayload, OC_RSRVD_TTL, &curVal);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_TTL type in the payload.");
+ goto exit;
+ }
- cborFindResult = cbor_value_advance(rdCBORPayload);
- if (CborNoError != cborFindResult)
- {
- OC_LOG_V(ERROR, TAG, "Failed advancing the payload.");
- goto exit;
- }
+ cborFindResult = cbor_value_get_int(&curVal, &ttl);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_TTL value in the payload.");
+ goto exit;
+ }
+
+ // Link Array
+ CborValue linkArray;
+ cborFindResult = cbor_value_map_find_value(rdCBORPayload, OC_RSRVD_LINKS, &linkArray);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed finding OC_RSRVD_LINKS type in the payload.");
+ goto exit;
+ }
+
+ CborValue linkVal;
+ cborFindResult = cbor_value_enter_container(&linkArray, &linkVal);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed entering linkArray container in the payload.");
+ goto exit;
+ }
+
+ OCRDLinksPayload *links = NULL;
+ while(cbor_value_is_map(&linkVal))
+ {
+ char *href = NULL;
+ char *itf = NULL;
+ char *rt = NULL;
+ size_t len;
+
+ cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_HREF, &curVal);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_HREF type in the payload.");
+ goto exit;
+ }
+
+ cborFindResult = cbor_value_dup_text_string(&curVal, &href, &len, NULL);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_HREF value in the payload.");
+ goto exit;
+ }
+
+ cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_INTERFACE, &curVal);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_INTERFACE type in the payload.");
+ goto exit;
+ }
+
+ cborFindResult = cbor_value_dup_text_string(&curVal, &itf, &len, NULL);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_INTERFACE value in the payload.");
+ goto exit;
+ }
+
+ cborFindResult = cbor_value_map_find_value(&linkVal, OC_RSRVD_RESOURCE_TYPE, &curVal);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_RESOURCE_TYPE type in the payload.");
+ goto exit;
+ }
+
+ cborFindResult = cbor_value_dup_text_string(&curVal, &rt, &len, NULL);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed finding link value OC_RSRVD_RESOURCE_TYPE value in the payload.");
+ goto exit;
+ }
+
+ OCRDLinksPayloadCreate(href, itf, rt, &links);
+ if (!links)
+ {
+ goto no_memory;
+ }
+
+ cborFindResult = cbor_value_advance(&linkVal);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed advancing the linkVal payload.");
+ goto exit;
+ }
+ }
+ cborFindResult = cbor_value_advance(&linkArray);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed advancing the linkArray payload.");
+ goto exit;
+ }
+ rdPayload->rdPublish = OCRDPublishPayloadCreate(ttl, links);
+ if (!rdPayload->rdPublish)
+ {
+ goto no_memory;
+ }
+ OCRDPayloadLog(DEBUG, TAG, rdPayload);
+ cborFindResult = cbor_value_advance(rdCBORPayload);
+ if (CborNoError != cborFindResult)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed advancing the payload.");
+ goto exit;
+ }
+ }
*outPayload = (OCPayload *)rdPayload;
}
-
return OC_STACK_OK;
-
no_memory:
OC_LOG_V(ERROR, TAG, "Failed allocating memory.");
OCRDPayloadDestroy(rdPayload);
return rdPayload;
}
+void OCRDLinksPayloadCreate(const char *uri, const char *rt, const char *itf,
+ OCRDLinksPayload **linksPayload)
+{
+ OCRDLinksPayload *payload = OICCalloc(1, sizeof(OCRDLinksPayload));
+
+ if (!payload)
+ {
+ goto no_memory;
+ }
+
+ payload->href = OICStrdup(uri);
+ if (!payload->href)
+ {
+ goto no_memory;
+ }
+
+ payload->rt = OICStrdup(rt);
+ if (!payload->rt)
+ {
+ goto no_memory;
+ }
+
+ payload->itf = OICStrdup(itf);
+ if (!payload->itf)
+ {
+ goto no_memory;
+ }
+
+ payload->next = NULL;
+
+ if (*linksPayload == NULL)
+ {
+ *linksPayload = payload;
+ }
+ else
+ {
+ OCRDLinksPayload *temp = *linksPayload;
+ while (temp->next)
+ {
+ temp = temp->next;
+ }
+ temp->next = payload;
+ }
+ return;
+
+no_memory:
+ OC_LOG_V(ERROR, TAG, "Memory allocation failed.");
+ linksPayloadDestroy(payload);
+}
+
OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(int biasFactor)
{
- OCRDDiscoveryPayload *discoveryPayload = (OCRDDiscoveryPayload *)
- OICCalloc(1, sizeof(OCRDDiscoveryPayload));
+ OCRDDiscoveryPayload *discoveryPayload = OICCalloc(1, sizeof(OCRDDiscoveryPayload));
if (!discoveryPayload)
{
return discoveryPayload;
}
+
+OCRDPublishPayload* OCRDPublishPayloadCreate(int ttl,
+ OCRDLinksPayload *linksPayload)
+{
+ OCRDPublishPayload *rdPublish = OICCalloc(1, sizeof(OCRDPublishPayload));
+
+ if (!rdPublish)
+ {
+ return NULL;
+ }
+
+ //TODO: Find way of device device id.
+ // rdPayload->rdPublish->id = (uint8_t *)OICCalloc(1, UUID_SIZE);
+ // memcpy(rdPayload->rdPublish->id, , UUID_SIZE);
+ //TODO: Find way of device device name.
+ // rdPayload->rdPublish->n = (char*)OICCalloc(1, strlen(name));
+ // memcpy(rdPayload->rdPublish->n, , strlen(name));
+ rdPublish->ttl = ttl; // TODO Expose API to allow user to set this value.
+ rdPublish->links = linksPayload;
+
+ return rdPublish;
+}
+
void OCRDPayloadDestroy(OCRDPayload *payload)
{
if (!payload)
OICFree(payload->rdDiscovery);
}
+ if (payload->rdPublish)
+ {
+ if (payload->rdPublish->links)
+ {
+ linksPayloadDestroy(payload->rdPublish->links);
+ }
+
+ if (payload->rdPublish->deviceName.deviceName)
+ {
+ OICFree(payload->rdPublish->deviceName.deviceName);
+ }
+
+ OICFree(payload->rdPublish);
+ }
+
OICFree(payload);
}
{
OC_LOG_V(level, tag, "RD Payload Discovery BIAS : %d", payload->rdDiscovery->sel);
}
+
+ if (payload->rdPublish)
+ {
+ if (payload->rdPublish->deviceName.deviceName)
+ {
+ OC_LOG_V(level, tag, "RD Payload Pulish Name : %s", payload->rdPublish->deviceName.deviceName);
+ }
+
+ if (payload->rdPublish->deviceId.id)
+ {
+ OC_LOG_V(level, tag, "RD Payload Publish ID : %s", payload->rdPublish->deviceId.id);
+ }
+
+ OC_LOG_V(level, tag, "RD Payload Publish TTL : %d", payload->rdPublish->ttl);
+
+ if (payload->rdPublish->links)
+ {
+ for (OCRDLinksPayload *temp = payload->rdPublish->links; temp; temp = temp->next)
+ {
+ OC_LOG_V(level, tag, "RD Payload Publish Link RT : %s", temp->rt);
+ OC_LOG_V(level, tag, "RD Payload Publish Link ITF : %s", temp->itf);
+ OC_LOG_V(level, tag, "RD Payload Publish Link HREF : %s", temp->href);
+ }
+ }
+ }
}
// This is temporary hardcoded value for bias factor.
#define OC_RD_DISC_SEL 100
-static OCResourceHandle gRDHandle = NULL;
+static OCStackResult sendResponse(const OCEntityHandlerRequest *ehRequest, OCRDPayload *rdPayload)
+{
+ OCEntityHandlerResponse response = { 0 };
+ response.requestHandle = ehRequest->requestHandle;
+ response.resourceHandle = ehRequest->resource;
+ response.ehResult = OC_EH_OK;
+ response.payload = (OCPayload*)(&rdPayload);
+ response.payload->type = PAYLOAD_TYPE_RD;
+
+ return OCDoResponse(&response);
+}
/**
* This internal method handles RD discovery request.
* Responds with the RD discovery payload message.
*/
-static OCEntityHandlerResult HandleRDGetRequest(const OCEntityHandlerRequest *ehRequest)
+static OCEntityHandlerResult handleGetRequest(const OCEntityHandlerRequest *ehRequest)
{
if (!ehRequest)
{
OCRDPayloadLog(DEBUG, TAG, rdPayload);
- OCEntityHandlerResponse ehResponse = {};
- ehResponse.requestHandle = ehRequest->requestHandle;
- ehResponse.resourceHandle = ehRequest->resource;
- ehResponse.payload = (OCPayload *)rdPayload;
- ehResponse.ehResult = ehResult;
-
- if (OCDoResponse(&ehResponse) != OC_STACK_OK)
+ if (sendResponse(ehRequest, rdPayload) != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, "Sending response failed.");
ehResult = OC_EH_ERROR;
return ehResult;
}
+/**
+ * This internal method handles RD publish request.
+ * Responds with the RD success message.
+ */
+static OCEntityHandlerResult handlePublishRequest(const OCEntityHandlerRequest *ehRequest)
+{
+ OCEntityHandlerResult ehResult = OC_EH_OK;
+
+ OC_LOG_V(DEBUG, TAG, "Received OC_REST_PUT from client with query: %s.", ehRequest->query);
+
+ if (!ehRequest)
+ {
+ OC_LOG_V(DEBUG, TAG, "Invalid request pointer");
+ return OC_EH_ERROR;
+ }
+
+ OCRDPayload *payload = (OCRDPayload*)ehRequest->payload;
+ if (payload->payloadType == RD_PAYLOAD_TYPE_PUBLISH)
+ {
+ // TODO STORE RESOURCE...
+ }
+
+ OC_LOG_V(DEBUG, TAG, "Sending success response");
+ OCRDPayload *rdPayload = OCRDPayloadCreate(RD_PAYLOAD_TYPE_PUBLISH);
+ if (sendResponse(ehRequest, rdPayload) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "Sending response failed.");
+ ehResult = OC_EH_ERROR;
+ }
+
+ OCRDPayloadDestroy(rdPayload);
+
+ return ehResult;
+}
/*
* This internal method is the entity handler for RD resources and
* will handle REST request (GET/PUT/POST/DEL) for them.
{
case OC_REST_GET:
case OC_REST_DISCOVER:
- HandleRDGetRequest(ehRequest);
+ handleGetRequest(ehRequest);
break;
case OC_REST_POST:
+ handlePublishRequest(ehRequest);
+ break;
case OC_REST_PUT:
case OC_REST_DELETE:
case OC_REST_OBSERVE:
OCStackResult OCRDStart()
{
OCStackResult result = OCInit(NULL, 0, OC_CLIENT_SERVER);
+ OCResourceHandle rdHandle = NULL;
if (result == OC_STACK_OK)
{
- result = OCCreateResource(&gRDHandle,
+ result = OCCreateResource(&rdHandle,
OC_RSRVD_RESOURCE_TYPE_RD,
OC_RSRVD_INTERFACE_DEFAULT,
OC_RSRVD_RD_URI,