From a26ce097009531138ffe1e07a85ba4e2e6584e5b Mon Sep 17 00:00:00 2001 From: Habib Virji Date: Tue, 18 Aug 2015 14:39:09 +0100 Subject: [PATCH] RD Client publish functionality Includes RD payload changes to support CBOR messages. Change-Id: I74892b40fe676337e4b0e1c50363d16a88011710 Signed-off-by: Habib Virji Reviewed-on: https://gerrit.iotivity.org/gerrit/2190 Tested-by: jenkins-iotivity Reviewed-by: Madan Lanka --- service/resource-directory/include/rd_client.h | 12 +++ service/resource-directory/src/rd_client.c | 142 +++++++++++++++++++------ service/resource-directory/src/rd_payload.c | 116 +++++++++++++++++++- 3 files changed, 238 insertions(+), 32 deletions(-) diff --git a/service/resource-directory/include/rd_client.h b/service/resource-directory/include/rd_client.h index e6c1db3..9a1bb9a 100644 --- a/service/resource-directory/include/rd_client.h +++ b/service/resource-directory/include/rd_client.h @@ -41,6 +41,18 @@ extern "C" { */ OCStackResult OCRDDiscover(OCRDBiasFactorCB cbBiasFactor); +/* +* Publish resource on the RD. +* +* @param addr The IP address of the RD, it could be either retrieved via OCRDDiscover(). +* @param port The port of the RD. +* @param num This denotes the number of registered resource handles being passed +* for the remaining arguments. +* +* @returns ::OC_STACK_OK when successful and OC_STACK_ERROR when query failed. +*/ +OCStackResult OCRDPublish(char *addr, uint16_t port, int num, ...); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/service/resource-directory/src/rd_client.c b/service/resource-directory/src/rd_client.c index 630d88a..0077a95 100644 --- a/service/resource-directory/src/rd_client.c +++ b/service/resource-directory/src/rd_client.c @@ -17,28 +17,69 @@ // limitations under the License. // //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +#include + +#include "rd_client.h" + #include "logger.h" #include "oic_malloc.h" +#include "oic_string.h" -#include "rd_client.h" #include "rd_payload.h" #define DEFAULT_CONTEXT_VALUE 0x99 +#define OC_RD_PUBLISH_TTL 86400 #define TAG PCF("RDClient") -static void retreiveRDDetails(OCClientResponse *clientResponse, OCRDBiasFactorCB clientCB) +static OCStackResult sendRequest(OCMethod method, char *uri, OCDevAddr *addr, + OCPayload *payload, OCCallbackData cbData) { - OC_LOG_V(DEBUG, TAG, "\tAddress: %s : %d", clientResponse->devAddr.addr, - clientResponse->devAddr.port); + OCDoHandle handle; + OCStackResult result; + + result = OCDoResource(handle, + method, + uri, + addr, + payload, + CT_ADAPTER_IP, + OC_LOW_QOS, + &cbData, + NULL, + 0); - OCRDPayload *payload = (OCRDPayload *) clientResponse->payload; - if (payload) + if (result == OC_STACK_OK) + { + OC_LOG_V(DEBUG, TAG, "Resource Directory send successful..."); + } + else { - OC_LOG_V(DEBUG, TAG, "\tType: %d", payload->base.type); - OC_LOG_V(DEBUG, TAG, "\tPayloadType: %d", payload->payloadType); - OC_LOG_V(DEBUG, TAG, "\tBiasFactor: %d", payload->rdDiscovery->sel); + OC_LOG_V(ERROR, TAG, "Resource Directory send failed..."); } + + return result; +} + +static OCStackApplicationResult handlePublishCB(void *ctx, + OCDoHandle handle, OCClientResponse *clientResponse) +{ + OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION; + OC_LOG_V(DEBUG, TAG, "Successfully published resources."); + + // TOOO: Stop multicast traffic on the client. + + return ret; +} + +static void retreiveRDDetails(OCClientResponse *clientResponse, OCRDBiasFactorCB clientCB) +{ + OC_LOG_V(DEBUG, TAG, "\tAddress of the RD: %s : %d", clientResponse->devAddr.addr, + clientResponse->devAddr.port); + + OCRDPayload *payload = (OCRDPayload *) clientResponse->payload; + OCRDPayloadLog(DEBUG, TAG, payload); + // TODO: Multiple Resource Directory will have different biasFactor, // needs to cache here detail // and after certain timeout then decide based on the biasFactor. @@ -47,13 +88,13 @@ static void retreiveRDDetails(OCClientResponse *clientResponse, OCRDBiasFactorCB } -static OCStackApplicationResult discoverRDCB(void *ctx, +static OCStackApplicationResult handleDiscoverCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse) { OC_LOG(DEBUG, TAG, "Found Resource Directory"); OCStackApplicationResult ret = OC_STACK_DELETE_TRANSACTION; - OCRDClientContextCB *cb = (OCRDClientContextCB*) ctx; + OCRDClientContextCB *cb = (OCRDClientContextCB *) ctx; if (!cb) { OC_LOG(ERROR, TAG, "RD Context Invalid Parameters."); @@ -82,10 +123,6 @@ static OCStackApplicationResult discoverRDCB(void *ctx, OCStackResult OCRDDiscover(OCRDBiasFactorCB cbBiasFactor) { - OCStackResult result = OC_STACK_ERROR; - OCCallbackData cbData; - OCDoHandle handle; - if (!cbBiasFactor) { OC_LOG(DEBUG, TAG, "No callback function specified."); @@ -102,29 +139,72 @@ OCStackResult OCRDDiscover(OCRDBiasFactorCB cbBiasFactor) cbContext.context = (void *)DEFAULT_CONTEXT_VALUE; cbContext.cbFunc = cbBiasFactor; - cbData.cb = discoverRDCB; + OCCallbackData cbData; + cbData.cb = handleDiscoverCB; cbData.context = (void *)(&cbContext); cbData.cd = NULL; - result = OCDoResource(&handle, - OC_REST_DISCOVER, - queryUri, - 0, - 0, - CT_ADAPTER_IP, - OC_LOW_QOS, - &cbData, - NULL, - 0); + return sendRequest(OC_REST_DISCOVER, queryUri, NULL, NULL, cbData); +} - if (result == OC_STACK_OK) +OCStackResult OCRDPublish(char *addr, uint16_t port, int numArg, ... ) +{ + if (!addr) { - OC_LOG_V(DEBUG, TAG, "Resource Directory finding query send successful..."); + OC_LOG_V(ERROR, TAG, "RD address not specified."); + return OC_STACK_INVALID_PARAM; } - else + + char targetUri[MAX_URI_LENGTH]; + snprintf(targetUri, MAX_URI_LENGTH, "coap://%s:%d%s?rt=%s", addr, port, + OC_RSRVD_RD_URI, OC_RSRVD_RESOURCE_TYPE_RDPUBLISH); + OC_LOG_V(DEBUG, TAG, "Target URI : %s", targetUri); + + // Gather all resources locally and do publish + OCCallbackData cbData = { 0 }; + cbData.cb = &handlePublishCB; + cbData.cd = NULL; + cbData.context = (void*)DEFAULT_CONTEXT_VALUE; + + OCRDLinksPayload* linksPayload = NULL; + + va_list arguments; + va_start (arguments, numArg); + + for (int j = 0 ; j < numArg; j++) { - OC_LOG_V(ERROR, TAG, "Resource Directory finding query send failed..."); + OCResourceHandle handle = va_arg(arguments, OCResourceHandle); + if (handle) + { + const char* uri = OCGetResourceUri(handle); + const char* rt = OCGetResourceTypeName(handle, 0); + const char* itf = OCGetResourceInterfaceName(handle, 0); + if (uri && rt && itf) + { + OCRDLinksPayloadCreate(uri, rt, itf, &linksPayload); + } + } } + va_end(arguments); - return result; + OCRDPayload *rdPayload = OCRDPayloadCreate(RD_PAYLOAD_TYPE_PUBLISH); + if (!rdPayload) + { + OC_LOG_V(ERROR, TAG, "Failed allocating memory."); + return OC_STACK_NO_MEMORY; + } + rdPayload->rdPublish = OCRDPublishPayloadCreate(OC_RD_PUBLISH_TTL, linksPayload); + if (!rdPayload->rdPublish) + { + OC_LOG_V(ERROR, TAG, "Failed allocating memory."); + return OC_STACK_NO_MEMORY; + } + + OCDevAddr rdAddr = { 0 }; + OICStrcpy(rdAddr.addr, MAX_ADDR_STR_SIZE, addr); + rdAddr.port = port; + + OCRDPayloadLog(DEBUG, TAG, rdPayload); + + return sendRequest(OC_REST_POST, targetUri, &rdAddr, (OCPayload *)rdPayload, cbData); } diff --git a/service/resource-directory/src/rd_payload.c b/service/resource-directory/src/rd_payload.c index 9ec372a..cb05de7 100644 --- a/service/resource-directory/src/rd_payload.c +++ b/service/resource-directory/src/rd_payload.c @@ -29,6 +29,7 @@ #define TAG PCF("OCRDPayload") #define CBOR_ROOT_ARRAY_LENGTH 2 +#define CBOR_LINK_ARRAY_LENGTH 3 static void linksPayloadDestroy(OCRDLinksPayload *linkPayload) { @@ -126,12 +127,125 @@ OCStackResult OCRDPayloadToCbor(const OCRDPayload *rdPayload, uint8_t **outPaylo } OC_LOG_V(DEBUG, TAG, "RD Payload bias factor: %d", rdPayload->rdDiscovery->sel); } + else + { + OC_LOG_V(ERROR, TAG, "Missing sel parameter in the discovery payload."); + goto exit; + } + } + else if (rdPayload->payloadType == RD_PAYLOAD_TYPE_PUBLISH) + { + cborEncoderResult = cbor_encode_text_string(&map, OC_RSRVD_TTL, sizeof(OC_RSRVD_TTL) - 1); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed setting publish ttl type."); + goto exit; + } + + cborEncoderResult = cbor_encode_uint(&map, rdPayload->rdPublish->ttl); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed setting publish ttl value."); + goto exit; + } + + CborEncoder linksArray; + cborEncoderResult = cbor_encode_text_string(&map, OC_RSRVD_LINKS, sizeof(OC_RSRVD_LINKS) - 1); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed setting publish links type."); + goto exit; + } + + cborEncoderResult = cbor_encoder_create_array(&map, &linksArray, CborIndefiniteLength); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed setting publish links array."); + goto exit; + } + + { + OCRDLinksPayload *rtPtr = rdPayload->rdPublish->links; + while(rtPtr) + { + CborEncoder linksMap; + cborEncoderResult = cbor_encoder_create_map(&linksArray, &linksMap, CBOR_LINK_ARRAY_LENGTH); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed setting publish map."); + goto exit; + } + + cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_HREF, + sizeof(OC_RSRVD_HREF) - 1); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed setting publish href type."); + goto exit; + } + + cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->href, + strlen(rtPtr->href)); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed setting publish href value."); + goto exit; + } + + cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_INTERFACE, + sizeof(OC_RSRVD_INTERFACE) - 1); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed setting publish itf type."); + goto exit; + } + + cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->itf, + strlen(rtPtr->itf)); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed setting publish itf value."); + goto exit; + } + + cborEncoderResult = cbor_encode_text_string(&linksMap, OC_RSRVD_RESOURCE_TYPE, + sizeof(OC_RSRVD_RESOURCE_TYPE) - 1); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed setting publish rt type."); + goto exit; + } + + cborEncoderResult = cbor_encode_text_string(&linksMap, rtPtr->rt, + strlen(rtPtr->rt)); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed setting publish rt value."); + goto exit; + } + + cborEncoderResult = cbor_encoder_close_container(&linksArray, &linksMap); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed closing linksMap publish map."); + goto exit; + } + + rtPtr = rtPtr->next; + } + } + cborEncoderResult = cbor_encoder_close_container(&map, &linksArray); + if (CborNoError != cborEncoderResult) + { + OC_LOG_V(ERROR, TAG, "Failed closing linksArray container."); + goto exit; + } } cborEncoderResult = cbor_encoder_close_container(&rootArray, &map); if (CborNoError != cborEncoderResult) { - OC_LOG_V(ERROR, TAG, "Failed closing rootArray container."); + OC_LOG_V(ERROR, TAG, "Failed closing map container."); goto exit; } -- 2.7.4