From 8757dadbc4f510f0a75f67600785dddf5d94ab58 Mon Sep 17 00:00:00 2001 From: uzchoi Date: Mon, 27 Mar 2017 21:41:29 +0900 Subject: [PATCH] Create links OCRepPayloadValue for collection resource By adding the payload definition includes links parameter in linklist interface for collection. Server application developer should implement it to comply to OCF specification, but this requires lots of coding work with holding the policy map info and so on. This API returns back links parameter which can be set as response payload for linklist request for collection. OCRepPayloadValue created by this function has following struct in depth. OCRepPayloadValue.arr->objArray[] as each resource links payload ..objArray[]->values->obj as policyMap Patch10 include tcp, tls port in the policy map. relocate code into occollection.c to better cohesion Change-Id: I399c5b6e40d0a00f43e106619cdc17ac480ed985 Reviewed-on: https://gerrit.iotivity.org/gerrit/18195 Tested-by: jenkins-iotivity Reviewed-by: Dan Mihai Reviewed-by: Ashok Babu Channa --- .../csdk/stack/include/internal/occollection.h | 3 + .../csdk/stack/include/internal/ocstackinternal.h | 3 + resource/csdk/stack/include/ocpayload.h | 14 ++ resource/csdk/stack/src/occollection.c | 158 +++++++++++++++++++++ resource/csdk/stack/src/ocpayload.c | 13 ++ resource/csdk/stack/src/ocresource.c | 10 +- resource/csdk/stack/test/stacktests.cpp | 105 ++++++++++++++ 7 files changed, 303 insertions(+), 3 deletions(-) diff --git a/resource/csdk/stack/include/internal/occollection.h b/resource/csdk/stack/include/internal/occollection.h index 24c7a18..9d5cece 100644 --- a/resource/csdk/stack/include/internal/occollection.h +++ b/resource/csdk/stack/include/internal/occollection.h @@ -29,4 +29,7 @@ uint8_t GetNumOfResourcesInCollection(const OCResource *resource); OCStackResult DefaultCollectionEntityHandler (OCEntityHandlerFlag flag, OCEntityHandlerRequest *entityHandlerRequest); +OCStackResult BuildCollectionLinksPayloadValue(const char* resourceUri, + OCRepPayloadValue** linksRepPayloadValue, OCDevAddr* devAddr); + #endif //OC_COLLECTION_H diff --git a/resource/csdk/stack/include/internal/ocstackinternal.h b/resource/csdk/stack/include/internal/ocstackinternal.h index 9efb21c..6bbe98f 100644 --- a/resource/csdk/stack/include/internal/ocstackinternal.h +++ b/resource/csdk/stack/include/internal/ocstackinternal.h @@ -360,6 +360,9 @@ void OCDiscoveryPayloadAddResourceWithEps(OCDiscoveryPayload *payload, const OCR void OCDiscoveryPayloadAddResourceWithEps(OCDiscoveryPayload *payload, const OCResource *res, uint16_t securePort, void *networkInfo, size_t infoSize, const OCDevAddr *devAddr, uint16_t tcpPort); + +/* This method will retrieve the tcp port */ +OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port, bool secured); #endif #ifdef __cplusplus } diff --git a/resource/csdk/stack/include/ocpayload.h b/resource/csdk/stack/include/ocpayload.h index 3106e2b..66562b7 100644 --- a/resource/csdk/stack/include/ocpayload.h +++ b/resource/csdk/stack/include/ocpayload.h @@ -292,6 +292,20 @@ char* OCCreateString(const OCStringLL* ll); **/ bool OCByteStringCopy(OCByteString *dest, const OCByteString *source); +/** +* This function creates the payloadValue for links parameter of collection resource. +* @param[in] resourceUri Resource uri (this should be a collection resource) +* @param[out] linksRepPayloadValue The payloadValue for links parameter of collection +* @param[in] devAddr Structure pointing to the address. (from OCEntityHandlerRequest) +* +* @note: The destroy of OCRepPayloadValue is not supported. Instead, use +* OCRepPayloadDestroy(...) to destroy RepPayload of the collection Resource +* +* @return ::OC_STACK_OK if successful or else other value. +*/ +OCStackResult OCLinksPayloadValueCreate(const char *resourceUri, + OCRepPayloadValue **linksRepPayloadValue, OCDevAddr *devAddr); + #ifdef __cplusplus } #endif diff --git a/resource/csdk/stack/src/occollection.c b/resource/csdk/stack/src/occollection.c index d4198fb..5a19e15 100755 --- a/resource/csdk/stack/src/occollection.c +++ b/resource/csdk/stack/src/occollection.c @@ -29,6 +29,7 @@ #include "occollection.h" #include "ocpayload.h" #include "ocstack.h" +#include "ocstackinternal.h" #include "oicgroup.h" #include "oic_string.h" #include "payload_logging.h" @@ -303,3 +304,160 @@ exit: OICFree(rtQueryParam); return result; } + +static OCRepPayload* addPolicyPayload(OCResourceHandle* resourceHandle, OCDevAddr* devAddr) +{ + OCResourceProperty p = OCGetResourceProperties(resourceHandle); + OCRepPayload* policy = OCRepPayloadCreate(); + if (policy) + { + OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE))); + OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE); + + if (p & OC_SECURE) + { + uint16_t securePort = 0; + if (devAddr) + { + if (devAddr->adapter == OC_ADAPTER_IP) + { + if (devAddr->flags & OC_IP_USE_V6) + { + securePort = caglobals.ip.u6s.port; + } + else if (devAddr->flags & OC_IP_USE_V4) + { + securePort = caglobals.ip.u4s.port; + } + } + } + OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort); + +#ifdef TCP_ADAPTER +#ifdef __WITH_TLS__ + // tls + if (devAddr) + { + uint16_t tlsPort = 0; + GetTCPPortInfo(devAddr, &tlsPort, true); + OCRepPayloadSetPropInt(policy, OC_RSRVD_TLS_PORT, tlsPort); + } +#else + } + // tcp + if (devAddr) + { + uint16_t tcpPort = 0; + GetTCPPortInfo(devAddr, &tcpPort, false); + OCRepPayloadSetPropInt(policy, OC_RSRVD_TCP_PORT, tcpPort); +#endif +#endif + } + } + return policy; +} + +OCStackResult BuildCollectionLinksPayloadValue(const char* resourceUri, OCRepPayloadValue** linksRepPayloadValue, + OCDevAddr* devAddr) +{ + OCStackResult result = OC_STACK_ERROR; + + OCRepPayloadValue* createdPayloadValue = (OCRepPayloadValue*)OICCalloc(1, sizeof(OCRepPayloadValue)); + if (!createdPayloadValue) + { + return result; + } + createdPayloadValue->name = OC_RSRVD_LINKS; + createdPayloadValue->type = OCREP_PROP_ARRAY; + + const OCResourceHandle colResourceHandle = OCGetResourceHandleAtUri(resourceUri); + if (!colResourceHandle) + { + //in case input resource is not registered resource. + OICFree(createdPayloadValue); + return result; + } + + const OCChildResource* childResource = ((OCResource*)colResourceHandle)->rsrcChildResourcesHead; + if (!childResource) + { + //in case input resource is not collection resource. + OICFree(createdPayloadValue); + return result; + } + + //children resources count calculation + size_t childCount = 0; + const OCChildResource* childCountResource = childResource; + do { + childCount++; + childCountResource = childCountResource->next; + } while (childCountResource); + + OCRepPayload** arrayPayload = (OCRepPayload** )OICMalloc(sizeof(OCRepPayload*) * (childCount + 1)); + if (!arrayPayload) + { + OICFree(createdPayloadValue); + return result; + } + + OCResource* iterResource = (OCResource*) colResourceHandle; + for (size_t i = 0; i < childCount + 1; i++) + { + arrayPayload[i] = OCRepPayloadCreate(); + if (!arrayPayload[i]) + { + OICFree(createdPayloadValue); + OICFree(arrayPayload); + return result; + } + + OCRepPayloadSetUri(arrayPayload[i], iterResource->uri); + + for (OCResourceType* resType = iterResource->rsrcType; resType; + resType = resType->next) + { + OCRepPayloadAddResourceType(arrayPayload[i], resType->resourcetypename); + } + + for (OCResourceInterface* resInterface = iterResource->rsrcInterface; resInterface; + resInterface = resInterface->next) + { + OCRepPayloadAddInterface(arrayPayload[i], resInterface->name); + } + + //@todo selectively fill in the data between Policy Map for OIC and EP Array for OCF + if (!OCRepPayloadSetPropObjectAsOwner(arrayPayload[i], OC_RSRVD_POLICY, + addPolicyPayload((OCResourceHandle*)iterResource, devAddr))) + { + return result; + } + + if (i == 0) + { + iterResource = childResource->rsrcResource; + } + else + { + childResource = childResource->next; + if (childResource) + { + iterResource = childResource->rsrcResource; + } + } + } + + //create OCRepPayloadValue internal structure and pass + //createdPayloadValue:OCRepPayloadValue.createdPayloadValueArray:arr->arrayPayload:objArray + OCRepPayloadValueArray* createdPayloadValueArray = &createdPayloadValue->arr; + size_t linkDim[MAX_REP_ARRAY_DEPTH] = { childCount + 1, 0, 0 }; + OC_STATIC_ASSERT(sizeof(createdPayloadValueArray->dimensions) == sizeof(linkDim), "Array size mismatch!"); + memcpy(createdPayloadValueArray->dimensions, linkDim, sizeof(linkDim)); + createdPayloadValueArray->type = OCREP_PROP_OBJECT; + createdPayloadValueArray->objArray = arrayPayload; + + *linksRepPayloadValue = createdPayloadValue; + + result = OC_STACK_OK; + return result; +} diff --git a/resource/csdk/stack/src/ocpayload.c b/resource/csdk/stack/src/ocpayload.c index aefc908..957eeef 100644 --- a/resource/csdk/stack/src/ocpayload.c +++ b/resource/csdk/stack/src/ocpayload.c @@ -24,6 +24,7 @@ #include "iotivity_config.h" #include #include "ocpayload.h" +#include "occollection.h" #include "octypes.h" #include #include "oic_malloc.h" @@ -2135,3 +2136,15 @@ void OCPresencePayloadDestroy(OCPresencePayload* payload) OICFree(payload->resourceType); OICFree(payload); } + +OCStackResult OCLinksPayloadValueCreate(const char* resourceUri, OCRepPayloadValue** linksRepPayloadValue, + OCDevAddr* devAddr) +{ + OIC_LOG(DEBUG, TAG, "OCLinksPayloadValueCreate"); + OCStackResult result = OC_STACK_ERROR; + if ((resourceUri != NULL) & (linksRepPayloadValue != NULL) ) + { + result = BuildCollectionLinksPayloadValue(resourceUri, linksRepPayloadValue, devAddr); + } + return result; +} diff --git a/resource/csdk/stack/src/ocresource.c b/resource/csdk/stack/src/ocresource.c index 0a77f79..47002c8 100755 --- a/resource/csdk/stack/src/ocresource.c +++ b/resource/csdk/stack/src/ocresource.c @@ -48,7 +48,6 @@ #include "secureresourcemanager.h" #include "cacommon.h" #include "cainterface.h" -#include "ocpayload.h" #include "oickeepalive.h" #include "platform_features.h" #include "payload_logging.h" @@ -139,10 +138,15 @@ static OCStackResult GetSecurePortInfo(OCDevAddr *endpoint, uint16_t *port) #ifdef TCP_ADAPTER /* This method will retrieve the tcp port */ -static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port, bool secured) +OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port, bool secured) { - uint16_t p = 0; + if (NULL == endpoint) + { + OIC_LOG(ERROR, TAG, "GetTCPPortInfo failed!"); + return OC_STACK_ERROR; + } + uint16_t p = 0; if (endpoint->adapter == OC_ADAPTER_IP) { if (endpoint->flags & OC_IP_USE_V4) diff --git a/resource/csdk/stack/test/stacktests.cpp b/resource/csdk/stack/test/stacktests.cpp index b2cf0b3..f50ce70 100644 --- a/resource/csdk/stack/test/stacktests.cpp +++ b/resource/csdk/stack/test/stacktests.cpp @@ -2710,3 +2710,108 @@ TEST(StackZoneId, getZoneIdWithInvalidParams) EXPECT_EQ(OC_STACK_ERROR, OCGetLinkLocalZoneId(9999, &zoneId)); EXPECT_EQ(OC_STACK_ERROR, OCGetLinkLocalZoneId(UINT32_MAX, &zoneId)); } + +TEST(LinksPayloadValue, createLinksPayloadValue) +{ + itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT); + OIC_LOG(INFO, TAG, "Starting createLinksPayloadValue test"); + InitStack(OC_SERVER); + + size_t numResources = 0; + uint8_t inBitmap[3] = { OC_DISCOVERABLE | OC_OBSERVABLE, + OC_DISCOVERABLE | OC_OBSERVABLE, + OC_DISCOVERABLE }; + int64_t outBitmap[3] = {0}; + + OCResourceHandle containerHandle; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&containerHandle, + "core.led", + "core.col", + "/a/kitchen", + 0, + NULL, + inBitmap[0])); + ++numResources; + + OCResourceHandle handle0; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0, + "core.led", + "core.rw", + "/a/led0", + 0, + NULL, + inBitmap[1])); + ++numResources; + + OCResourceHandle handle1; + EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1, + "core.led", + "core.r", + "/a/led1", + 0, + NULL, + inBitmap[2])); + ++numResources; + + EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle0)); + EXPECT_EQ(OC_STACK_OK, OCBindResource(containerHandle, handle1)); + + EXPECT_EQ(handle0, OCGetResourceHandleFromCollection(containerHandle, 0)); + EXPECT_EQ(handle1, OCGetResourceHandleFromCollection(containerHandle, 1)); + + OCRepPayloadValue* linksRepPayloadValue; + OCDevAddr* devAddr = NULL; + EXPECT_EQ(OC_STACK_OK, OCLinksPayloadValueCreate("/a/kitchen", &linksRepPayloadValue, devAddr)); + ASSERT_TRUE(NULL != linksRepPayloadValue); + + OCRepPayload *collectionPayload = OCRepPayloadCreate(); + ASSERT_TRUE(NULL != collectionPayload); + + size_t dim[MAX_REP_ARRAY_DEPTH] = { numResources, 0, 0 }; + + ASSERT_TRUE(OCRepPayloadSetPropObjectArrayAsOwner(collectionPayload, OC_RSRVD_LINKS, + linksRepPayloadValue->arr.objArray, dim)); + + OCRepPayload *policyMap = NULL; + OCRepPayload **linksMap = NULL; + ASSERT_TRUE(OCRepPayloadGetPropObjectArray(collectionPayload, OC_RSRVD_LINKS, &linksMap, dim)); + + for (size_t i = 0; i < numResources; i++) + { + ASSERT_TRUE(OCRepPayloadGetPropObject(linksMap[i], OC_RSRVD_POLICY, &policyMap)); + ASSERT_TRUE(OCRepPayloadGetPropInt(policyMap, OC_RSRVD_BITMAP, &outBitmap[i])); + EXPECT_EQ(inBitmap[i], outBitmap[i]); + + if (devAddr) + { +#ifdef TCP_ADAPTER +#ifdef __WITH_TLS__ + // tls + int64_t outTlsPort = 0; + ASSERT_TRUE(OCRepPayloadGetPropInt(policyMap, OC_RSRVD_TLS_PORT, &outTlsPort)); + + uint16_t tlsPort = 0; + GetTCPPortInfo(devAddr, &tlsPort, true); + + EXPECT_EQ(tlsPort, outTlsPort); +#else + // tcp + int64_t outTcpPort = 0; + ASSERT_TRUE(OCRepPayloadGetPropInt(policyMap, OC_RSRVD_TCP_PORT, &outTcpPort)); + + uint16_t tcpPort = 0; + GetTCPPortInfo(devAddr, &tcpPort, false); + + EXPECT_EQ(tcpPort, outTcpPort); +#endif +#endif + } + OCRepPayloadDestroy(linksMap[i]); + } + + OICFree(linksMap); + OCRepPayloadDestroy(policyMap); + OCRepPayloadDestroy(collectionPayload); + + EXPECT_EQ(OC_STACK_OK, OCStop()); +} -- 2.7.4