From dfa005e2c6df7b3c1b01727837beff0e490f1a7c Mon Sep 17 00:00:00 2001 From: Habib Virji Date: Tue, 11 Aug 2015 14:11:10 +0100 Subject: [PATCH] RDServer publish parsing and managing resource Payload sent by the RD Client parsing from cbor to the structure. This also defines the structure used for handling publish resources. Change-Id: I2ad40c0f74aa162bf933675a3d71c11204285224 Signed-off-by: Habib Virji Reviewed-on: https://gerrit.iotivity.org/gerrit/2169 Tested-by: jenkins-iotivity Reviewed-by: Madan Lanka --- service/resource-directory/include/rd_payload.h | 30 ++- service/resource-directory/include/rd_types.h | 40 +++- service/resource-directory/src/rd_payload.c | 281 ++++++++++++++++++++++-- service/resource-directory/src/rd_server.c | 63 +++++- 4 files changed, 376 insertions(+), 38 deletions(-) diff --git a/service/resource-directory/include/rd_payload.h b/service/resource-directory/include/rd_payload.h index da219fe..df2b823 100644 --- a/service/resource-directory/include/rd_payload.h +++ b/service/resource-directory/include/rd_payload.h @@ -21,13 +21,9 @@ #ifndef _RESOURCE_DIRECTORY_PAYLOAD_H_ #define _RESOURCE_DIRECTORY_PAYLOAD_H_ -#include "rd_types.h" - #include -#include "octypes.h" -#include "ocstack.h" -#include "logger.h" +#include "rd_types.h" #ifdef __cplusplus extern "C" { @@ -82,6 +78,30 @@ OCRDPayload *OCRDPayloadCreate(OCRDPayloadType payloadType); OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(int biasFactor); /** + * Creates the links payload, which is then embedded inside OCRDPublishPayload. + * + * @param uri The Web Link Address of the resource. + * @param rt The resource type of the published resource. + * @param itf The interface type of the published resource. + * @param linkPayload The address of the allocated memory or NULL in case if failed + * to allocate memory. + */ +void OCRDLinksPayloadCreate(const char *uri, const char *rt, const char *itf, + OCRDLinksPayload **linkPayload); + +/** + * Creates the links payload, which is then embedded inside OCRDPublishPayload. + * + * @param ttl Time to live of the published resource.. + * @param linkPayload The link payload with uri, rt and itf. + * + * @return Allocated memory of OCRDPublishPayload or NULL in case if failed + * to allocate memory. + */ +OCRDPublishPayload *OCRDPublishPayloadCreate(const int ttl, + OCRDLinksPayload *linkPayload); + +/** * Free memory allocation of the RDPayload and its internal structure. * * @param payload Pointer to already allocated memory for OCRDPayload. diff --git a/service/resource-directory/include/rd_types.h b/service/resource-directory/include/rd_types.h index 1c03479..31dfd14 100644 --- a/service/resource-directory/include/rd_types.h +++ b/service/resource-directory/include/rd_types.h @@ -35,6 +35,9 @@ extern "C" { /** RD Discovery bias factor type. */ #define OC_RSRVD_RD_DISCOVERY_SEL "sel" +/** To represent resource type with Publish RD.*/ +#define OC_RSRVD_RESOURCE_TYPE_RDPUBLISH "oic.wk.rdPub" + /** Max ADDR SIZE */ #define MAX_ADDR_STR_SIZE (40) @@ -60,12 +63,45 @@ typedef struct } OCRDDiscoveryPayload; /** + * Structure holding RD Links Payload. It is a sub-structure used in + * OCRDPublishPayload. + */ +typedef struct OCRDLinksPayload +{ + /** Web Link Address of the resource. */ + char *href; + /** Resource type of the resource. */ + char *rt; + /** Interace type of the resource. */ + char *itf; + /** Holding address of the next resource. */ + struct OCRDLinksPayload *next; +} OCRDLinksPayload; + +/** + * Structure holding RD Publish payload. + */ +typedef struct +{ + /** Device Name. */ + OCDeviceInfo deviceName; + /** Device id. */ + OCIdentity deviceId; + /** Time to keep holding resource.*/ + uint32_t ttl; + /** List of resource information that will be stored at RD.*/ + OCRDLinksPayload *links; +} OCRDPublishPayload; + +/** * Enum values of multiple RD type payload. */ typedef enum { /** Value pf the RD discovery payload. */ - RD_PAYLOAD_TYPE_DISCOVERY + RD_PAYLOAD_TYPE_DISCOVERY, + /** Value of the RD publish payload. */ + RD_PAYLOAD_TYPE_PUBLISH } OCRDPayloadType; /** @@ -79,6 +115,8 @@ typedef struct OCRDPayloadType payloadType; /** Pointer to the discovery response payload.*/ OCRDDiscoveryPayload *rdDiscovery; + /** Pointer to the publish payload.*/ + OCRDPublishPayload *rdPublish; } OCRDPayload; #ifdef __cplusplus diff --git a/service/resource-directory/src/rd_payload.c b/service/resource-directory/src/rd_payload.c index 441b192..23a5f81 100644 --- a/service/resource-directory/src/rd_payload.c +++ b/service/resource-directory/src/rd_payload.c @@ -19,17 +19,33 @@ //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include "rd_payload.h" -#include - #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) @@ -47,14 +63,15 @@ OCStackResult OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t **outPaylo *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."); @@ -97,7 +114,7 @@ OCStackResult OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t **outPaylo { 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; @@ -151,7 +168,12 @@ OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPay 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; @@ -172,7 +194,6 @@ OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPay 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); @@ -201,7 +222,6 @@ OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPay goto exit; } } - OC_LOG_V(DEBUG, TAG, "Bias Factor : %d ", biasFactor); rdPayload->rdDiscovery = OCRDDiscoveryPayloadCreate(biasFactor); if (!rdPayload->rdDiscovery) @@ -209,19 +229,126 @@ OCStackResult OCRDCborToPayload(const CborValue *cborPayload, OCPayload **outPay 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); @@ -247,10 +374,59 @@ OCRDPayload *OCRDPayloadCreate(OCRDPayloadType payloadType) 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) { @@ -261,6 +437,29 @@ OCRDDiscoveryPayload *OCRDDiscoveryPayloadCreate(int biasFactor) 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) @@ -273,6 +472,21 @@ void OCRDPayloadDestroy(OCRDPayload *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); } @@ -290,4 +504,29 @@ void OCRDPayloadLog(LogLevel level, const char *tag, const OCRDPayload *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); + } + } + } } diff --git a/service/resource-directory/src/rd_server.c b/service/resource-directory/src/rd_server.c index c605bb8..72446f3 100644 --- a/service/resource-directory/src/rd_server.c +++ b/service/resource-directory/src/rd_server.c @@ -28,13 +28,23 @@ // 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) { @@ -60,13 +70,7 @@ static OCEntityHandlerResult HandleRDGetRequest(const OCEntityHandlerRequest *eh 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; @@ -77,6 +81,40 @@ static OCEntityHandlerResult HandleRDGetRequest(const OCEntityHandlerRequest *eh 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. @@ -98,9 +136,11 @@ static OCEntityHandlerResult RDEntityHandler(OCEntityHandlerFlag flag, { 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: @@ -121,10 +161,11 @@ static OCEntityHandlerResult RDEntityHandler(OCEntityHandlerFlag flag, 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, -- 2.7.4