X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fstack%2Fsrc%2Focresource.c;h=16579f8ffb922bcd27fbb166ea19db45638a86c9;hb=7f00f942c39b7bc27c7eeecf213a239c3fe4173c;hp=fbd7bd6a455e3522e1350894ee36c1264a592900;hpb=fdbdbceee131f8c39af5af7e61a2b87876e6f26d;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/stack/src/ocresource.c b/resource/csdk/stack/src/ocresource.c index fbd7bd6..16579f8 100755 --- a/resource/csdk/stack/src/ocresource.c +++ b/resource/csdk/stack/src/ocresource.c @@ -25,11 +25,15 @@ // For POSIX.1-2001 base specification, // Refer http://pubs.opengroup.org/onlinepubs/009695399/ #define _POSIX_C_SOURCE 200112L +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif -#ifdef WITH_STRING_H +#include "iotivity_config.h" +#ifdef HAVE_STRING_H #include #endif -#ifdef WITH_STRINGS_H +#ifdef HAVE_STRINGS_H #include #endif @@ -40,18 +44,14 @@ #include "oic_malloc.h" #include "oic_string.h" #include "logger.h" -#include "cJSON.h" #include "ocpayload.h" #include "secureresourcemanager.h" #include "cacommon.h" #include "cainterface.h" -#include "rdpayload.h" #include "ocpayload.h" - -#ifdef WITH_RD -#include "rd_server.h" -#endif - +#include "oickeepaliveinternal.h" +#include "platform_features.h" +#include "payload_logging.h" #ifdef ROUTING_GATEWAY #include "routingmanager.h" #endif @@ -59,25 +59,17 @@ /// Module Name #define TAG "OIC_RI_RESOURCE" -#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \ +#define VERIFY_SUCCESS(op) { if (op != (OC_STACK_OK)) \ {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} } -#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \ - TAG, #arg " is NULL"); return (retVal); } } - -#include "platform_features.h" - extern OCResource *headResource; -static OCPlatformInfo savedPlatformInfo = {0}; -static OCDeviceInfo savedDeviceInfo = {0}; /** * Prepares a Payload for response. */ static OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr, OCDiscoveryPayload* payload, - OCDevAddr *endpoint, - bool rdResponse); + OCDevAddr *endpoint); //----------------------------------------------------------------------------- // Default resource entity handler function @@ -116,7 +108,7 @@ 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) +static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port, bool secured) { uint16_t p = 0; @@ -124,11 +116,11 @@ static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port) { if (endpoint->flags & OC_IP_USE_V4) { - p = caglobals.tcp.ipv4.port; + p = secured ? caglobals.tcp.ipv4s.port : caglobals.tcp.ipv4.port; } else if (endpoint->flags & OC_IP_USE_V6) { - p = caglobals.tcp.ipv6.port; + p = secured ? caglobals.tcp.ipv6s.port : caglobals.tcp.ipv6.port; } } @@ -144,34 +136,54 @@ static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port) * Resource and device filters in the SAME query are NOT validated * and resources will likely not clear filters. */ -static OCStackResult ExtractFiltersFromQuery(char *query, char **filterOne, char **filterTwo) +OCStackResult ExtractFiltersFromQuery(const char *query, char **filterOne, char **filterTwo) { - + if (!query) + { + OIC_LOG_V(ERROR, TAG, "Query is empty!"); + return OC_STACK_INVALID_QUERY; + } char *key = NULL; char *value = NULL; + char *queryDup = NULL; char *restOfQuery = NULL; + char *keyValuePair = NULL; int numKeyValuePairsParsed = 0; *filterOne = NULL; *filterTwo = NULL; - OIC_LOG_V(INFO, TAG, "Extracting params from %s", query); + queryDup = OICStrdup(query); + if (NULL == queryDup) + { + OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!"); + return OC_STACK_NO_MEMORY; + } + + OIC_LOG_V(INFO, TAG, "Extracting params from %s", queryDup); - char *keyValuePair = strtok_r (query, OC_QUERY_SEPARATOR, &restOfQuery); + OCStackResult eCode = OC_STACK_INVALID_QUERY; + if (strnlen(queryDup, MAX_QUERY_LENGTH) >= MAX_QUERY_LENGTH) + { + OIC_LOG(ERROR, TAG, "Query exceeds maximum length."); + goto exit; + } + + keyValuePair = strtok_r (queryDup, OC_QUERY_SEPARATOR, &restOfQuery); while(keyValuePair) { if (numKeyValuePairsParsed >= 2) { OIC_LOG(ERROR, TAG, "More than 2 queries params in URI."); - return OC_STACK_INVALID_QUERY; + goto exit; } key = strtok_r(keyValuePair, OC_KEY_VALUE_DELIMITER, &value); if (!key || !value) { - return OC_STACK_INVALID_QUERY; + goto exit; } else if (strncasecmp(key, OC_RSRVD_INTERFACE, sizeof(OC_RSRVD_INTERFACE) - 1) == 0) { @@ -184,15 +196,45 @@ static OCStackResult ExtractFiltersFromQuery(char *query, char **filterOne, char else { OIC_LOG_V(ERROR, TAG, "Unsupported query key: %s", key); - return OC_STACK_INVALID_QUERY; + goto exit; } ++numKeyValuePairsParsed; keyValuePair = strtok_r(NULL, OC_QUERY_SEPARATOR, &restOfQuery); } + if (*filterOne) + { + *filterOne = OICStrdup(*filterOne); + if (NULL == *filterOne) + { + OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!"); + eCode = OC_STACK_NO_MEMORY; + goto exit; + } + } + + if (*filterTwo) + { + *filterTwo = OICStrdup(*filterTwo); + if (NULL == *filterTwo) + { + OIC_LOG_V(ERROR, TAG, "Creating duplicate string failed!"); + OICFree(*filterOne); + eCode = OC_STACK_NO_MEMORY; + goto exit; + } + } + + OICFree(queryDup); OIC_LOG_V(INFO, TAG, "Extracted params if: %s and rt: %s.", *filterOne, *filterTwo); return OC_STACK_OK; + +exit: + *filterOne = NULL; + *filterTwo = NULL; + OICFree(queryDup); + return eCode; } static OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest) @@ -225,6 +267,21 @@ static OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest) return OC_PRESENCE; } #endif //WITH_PRESENCE + +#ifdef MQ_BROKER + else if (0 == strcmp(uriInRequest, OC_RSRVD_WELL_KNOWN_MQ_URI)) + { + return OC_MQ_BROKER_URI; + } +#endif //MQ_BROKER + +#ifdef TCP_ADAPTER + else if (strcmp(uriInRequest, OC_RSRVD_KEEPALIVE_URI) == 0) + { + return OC_KEEPALIVE_RESOURCE_URI; + } +#endif + return OC_UNKNOWN_URI; } @@ -239,14 +296,14 @@ static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *q *filterOne = NULL; *filterTwo = NULL; - #ifdef WITH_PRESENCE +#ifdef WITH_PRESENCE if (uri == OC_PRESENCE) { //Nothing needs to be done, except for pass a OC_PRESENCE query through as OC_STACK_OK. OIC_LOG(INFO, TAG, "OC_PRESENCE Request for virtual resource."); return OC_STACK_OK; } - #endif +#endif OCStackResult result = OC_STACK_OK; @@ -258,23 +315,57 @@ static OCStackResult getQueryParamsForFiltering (OCVirtualResources uri, char *q return result; } -OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr, - OCRepPayload** payload) +bool appendOCStringLL(OCRepPayload *device, OCStringLL *dmv) { - OCRepPayload *tempPayload = OCRepPayloadCreate(); + int size = 0; + for (OCStringLL *ll = dmv; ll; ll = ll->next, size++); + size_t dim[MAX_REP_ARRAY_DEPTH] = {size, 0, 0}; + char **dt = (char **)OICMalloc(sizeof(char *) * size); + int i = 0; + VERIFY_PARAM_NON_NULL(TAG, dt, "Data Model Version allocation failed."); + for (OCStringLL *ll = dmv; ll; ll = ll->next, i++) + { + dt[i] = OICStrdup(ll->value); + VERIFY_PARAM_NON_NULL(TAG, dt[i], "Data Model Version adding failed."); + } + if (!OCRepPayloadSetStringArrayAsOwner(device, OC_RSRVD_DATA_MODEL_VERSION, dt, dim)) + { + goto exit; + } + return true; + +exit: + for (int i = 0; i < size; i++) + { + OICFree(dt[i]); + } + OICFree(dt); + return false; +} +static OCStackResult BuildDevicePlatformPayload(const OCResource *resourcePtr, OCRepPayload** payload, bool addDeviceId) +{ if (!resourcePtr) { - OCRepPayloadDestroy(tempPayload); return OC_STACK_INVALID_PARAM; } - if(!tempPayload) + OCRepPayload *tempPayload = OCRepPayloadCreate(); + if (!tempPayload) { return OC_STACK_NO_MEMORY; } - OCRepPayloadSetUri(tempPayload, resourcePtr->uri); + if (addDeviceId) + { + const char *deviceId = OCGetServerInstanceIDString(); + if (!deviceId) + { + OIC_LOG(ERROR, TAG, "Failed retrieving device id."); + return OC_STACK_ERROR; + } + OCRepPayloadSetPropString(tempPayload, OC_RSRVD_DEVICE_ID, deviceId); + } OCResourceType *resType = resourcePtr->rsrcType; while(resType) @@ -293,8 +384,22 @@ OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr, OCAttribute *resAttrib = resourcePtr->rsrcAttributes; while(resAttrib) { - OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, - resAttrib->attrValue); + if (resAttrib->attrName && resAttrib->attrValue) + { + if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName)) + { + char *dmv = OCCreateString((OCStringLL *)resAttrib->attrValue); + if (dmv) + { + OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, dmv); + OICFree(dmv); + } + } + else + { + OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue); + } + } resAttrib = resAttrib->next; } @@ -310,54 +415,143 @@ OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr, return OC_STACK_OK; } -OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr, - OCDiscoveryPayload *payload, OCDevAddr *devAddr, bool rdResponse) +OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr, + OCRepPayload** payload, OCDevAddr *devAddr) { - if (!resourcePtr || !payload) + if (!resourcePtr) { return OC_STACK_INVALID_PARAM; } - uint16_t securePort = 0; - if (resourcePtr->resourceProperties & OC_SECURE) + + OCRepPayload *tempPayload = OCRepPayloadCreate(); + if(!tempPayload) { - if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK) - { - securePort = 0; - } + return OC_STACK_NO_MEMORY; } - if (rdResponse) + OCRepPayloadSetPropString(tempPayload, OC_RSRVD_HREF, resourcePtr->uri); + + uint8_t numElement = 0; + if (OC_STACK_OK == OCGetNumberOfResourceTypes((OCResource *)resourcePtr, &numElement)) { - securePort = devAddr->port; + size_t rtDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0}; + char **rt = (char **)OICMalloc(sizeof(char *) * numElement); + if (!rt) + { + OIC_LOG(ERROR, TAG, "Resource type allocation failed."); + OCRepPayloadDestroy(tempPayload); + return OC_STACK_NO_MEMORY; + } + for (uint8_t i = 0; i < numElement; ++i) + { + const char *value = OCGetResourceTypeName((OCResource *)resourcePtr, i); + OIC_LOG_V(DEBUG, TAG, "value: %s", value); + rt[i] = OICStrdup(value); + } + OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_RESOURCE_TYPE, rt, rtDim); } - uint16_t tcpPort = 0; -#ifdef TCP_ADAPTER - if (GetTCPPortInfo(devAddr, &tcpPort) != OC_STACK_OK) + numElement = 0; + if (OC_STACK_OK == OCGetNumberOfResourceInterfaces((OCResource *)resourcePtr, &numElement)) { - tcpPort = 0; + size_t ifDim[MAX_REP_ARRAY_DEPTH] = {numElement, 0, 0}; + char **itf = (char **)OICMalloc(sizeof(char *) * numElement); + if (!itf) + { + OIC_LOG(ERROR, TAG, "Resource interface allocation failed."); + OCRepPayloadDestroy(tempPayload); + return OC_STACK_NO_MEMORY; + } + for (uint8_t i = 0; i < numElement; ++i) + { + const char *value = OCGetResourceInterfaceName((OCResource *)resourcePtr, i); + OIC_LOG_V(DEBUG, TAG, "value: %s", value); + itf[i] = OICStrdup(value); + } + OCRepPayloadSetStringArrayAsOwner(tempPayload, OC_RSRVD_INTERFACE, itf, ifDim); + } + + for (OCAttribute *resAttrib = resourcePtr->rsrcAttributes; resAttrib; resAttrib = resAttrib->next) + { + if (resAttrib->attrName && resAttrib->attrValue) + { + if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName)) + { + char *dmv = OCCreateString((OCStringLL *)resAttrib->attrValue); + if (dmv) + { + OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, dmv); + OICFree(dmv); + } + } + else + { + OCRepPayloadSetPropString(tempPayload, resAttrib->attrName, (char *)resAttrib->attrValue); + } + } + } + + if (devAddr) + { + OCResourceProperty p = OCGetResourceProperties((OCResourceHandle *)resourcePtr); + OCRepPayload *policy = OCRepPayloadCreate(); + if (!policy) + { + OCPayloadDestroy((OCPayload *)tempPayload); + return OC_STACK_NO_MEMORY; + } + OCRepPayloadSetPropInt(policy, OC_RSRVD_BITMAP, ((p & OC_DISCOVERABLE) | (p & OC_OBSERVABLE))); + if (p & OC_SECURE) + { + OCRepPayloadSetPropBool(policy, OC_RSRVD_SECURE, p & OC_SECURE); + uint16_t securePort = 0; + if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK) + { + securePort = 0; + } + OCRepPayloadSetPropInt(policy, OC_RSRVD_HOSTING_PORT, securePort); + } + OCRepPayloadSetPropObjectAsOwner(tempPayload, OC_RSRVD_POLICY, policy); + } + + if (!*payload) + { + *payload = tempPayload; + } + else + { + OCRepPayloadAppend(*payload, tempPayload); } - OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort, tcpPort); -#else - OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort); -#endif return OC_STACK_OK; } -uint8_t IsCollectionResource (OCResource *resource) +OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr, + OCDiscoveryPayload *payload, OCDevAddr *devAddr) { - if(!resource) + if (!resourcePtr || !payload) { - return 0; + return OC_STACK_INVALID_PARAM; } - - if(resource->rsrcChildResourcesHead != NULL) + uint16_t securePort = 0; + if (resourcePtr->resourceProperties & OC_SECURE) { - return 1; + if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK) + { + securePort = 0; + } } - return 0; +#ifdef TCP_ADAPTER + uint16_t tcpPort = 0; + GetTCPPortInfo(devAddr, &tcpPort, (resourcePtr->resourceProperties & OC_SECURE)); + + OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort, tcpPort); +#else + OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort); +#endif + + return OC_STACK_OK; } OCResource *FindResourceByUri(const char* resourceUri) @@ -380,7 +574,6 @@ OCResource *FindResourceByUri(const char* resourceUri) return NULL; } - OCStackResult DetermineResourceHandling (const OCServerRequest *request, ResourceHandling *handling, OCResource **resource) @@ -424,7 +617,7 @@ OCStackResult DetermineResourceHandling (const OCServerRequest *request, return OC_STACK_NO_RESOURCE; } - if (IsCollectionResource (resourcePtr)) + if (resourcePtr && resourcePtr->rsrcChildResourcesHead != NULL) { // Collection resource if (resourcePtr->entityHandler != defaultResourceEHandler) @@ -462,6 +655,8 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult) switch (ehResult) { case OC_EH_OK: + case OC_EH_CONTENT: + case OC_EH_VALID: result = OC_STACK_OK; break; case OC_EH_SLOW: @@ -471,7 +666,7 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult) result = OC_STACK_ERROR; break; case OC_EH_FORBIDDEN: - result = OC_STACK_RESOURCE_ERROR; + result = OC_STACK_FORBIDDEN_REQ; break; case OC_EH_RESOURCE_CREATED: result = OC_STACK_RESOURCE_CREATED; @@ -479,9 +674,30 @@ OCStackResult EntityHandlerCodeToOCStackCode(OCEntityHandlerResult ehResult) case OC_EH_RESOURCE_DELETED: result = OC_STACK_RESOURCE_DELETED; break; + case OC_EH_CHANGED: + result = OC_STACK_RESOURCE_CHANGED; + break; case OC_EH_RESOURCE_NOT_FOUND: result = OC_STACK_NO_RESOURCE; break; + case OC_EH_INTERNAL_SERVER_ERROR: + result = OC_STACK_INTERNAL_SERVER_ERROR; + break; + case OC_EH_NOT_IMPLEMENTED: + result = OC_STACK_NOT_IMPLEMENTED; + break; + case OC_EH_BAD_GATEWAY: + result = OC_STACK_BAD_GATEWAY; + break; + case OC_EH_SERVICE_UNAVAILABLE: + result = OC_STACK_SERVICE_UNAVAILABLE; + break; + case OC_EH_RETRANSMIT_TIMEOUT: + result = OC_STACK_GATEWAY_TIMEOUT; + break; + case OC_EH_PROXY_NOT_SUPPORTED: + result = OC_STACK_PROXY_NOT_SUPPORTED; + break; default: result = OC_STACK_ERROR; } @@ -496,21 +712,24 @@ static bool resourceMatchesRTFilter(OCResource *resource, char *resourceTypeFilt return false; } - // Null or empty is analogous to no filter. - if (resourceTypeFilter == NULL || *resourceTypeFilter == 0) + // Null is analogous to no filter. + if (NULL == resourceTypeFilter) { return true; } - OCResourceType *resourceTypePtr = resource->rsrcType; + // Empty resourceType filter is analogous to error query + if (0 == strlen(resourceTypeFilter)) + { + return false; + } - while (resourceTypePtr) + for (OCResourceType *rtPtr = resource->rsrcType; rtPtr; rtPtr = rtPtr->next) { - if (strcmp (resourceTypePtr->resourcetypename, resourceTypeFilter) == 0) + if (0 == strcmp(rtPtr->resourcetypename, resourceTypeFilter)) { return true; } - resourceTypePtr = resourceTypePtr->next; } OIC_LOG_V(INFO, TAG, "%s does not contain rt=%s.", resource->uri, resourceTypeFilter); @@ -524,23 +743,26 @@ static bool resourceMatchesIFFilter(OCResource *resource, char *interfaceFilter) return false; } - // Null or empty is analogous to no filter. - if (interfaceFilter == NULL || *interfaceFilter == 0) + // Null is analogous to no filter. + if (NULL == interfaceFilter) { return true; } - OCResourceInterface *interfacePtr = resource->rsrcInterface; + // Empty interface filter is analogous to error query + if (0 == strlen(interfaceFilter)) + { + return false; + } - while (interfacePtr) + for (OCResourceInterface *ifPtr = resource->rsrcInterface; ifPtr; ifPtr = ifPtr->next) { - if ((strcmp (interfacePtr->name, interfaceFilter) == 0) && - (strcmp (OC_RSRVD_INTERFACE_LL, interfaceFilter) == 0 || - strcmp (OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter) == 0)) + if (0 == strcmp(ifPtr->name, interfaceFilter) || + 0 == strcmp(OC_RSRVD_INTERFACE_LL, interfaceFilter) || + 0 == strcmp(OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter)) { return true; } - interfacePtr = interfacePtr->next; } OIC_LOG_V(INFO, TAG, "%s does not contain if=%s.", resource->uri, interfaceFilter); @@ -570,12 +792,12 @@ static bool includeThisResourceInResponse(OCResource *resource, */ if (!(resourceTypeFilter && *resourceTypeFilter)) { - OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE \ + OIC_LOG_V(INFO, TAG, "%s no query string for EXPLICIT_DISCOVERABLE\ resource", resource->uri); return false; } } - else if ( !(resource->resourceProperties & OC_ACTIVE) || + else if (!(resource->resourceProperties & OC_ACTIVE) || !(resource->resourceProperties & OC_DISCOVERABLE)) { OIC_LOG_V(INFO, TAG, "%s not ACTIVE or DISCOVERABLE", resource->uri); @@ -584,7 +806,6 @@ static bool includeThisResourceInResponse(OCResource *resource, return resourceMatchesIFFilter(resource, interfaceFilter) && resourceMatchesRTFilter(resource, resourceTypeFilter); - } OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCResource *resource, @@ -595,107 +816,137 @@ OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCRes response.ehResult = ehResult; response.payload = discoveryPayload; response.persistentBufferFlag = 0; - response.requestHandle = (OCRequestHandle) request; + response.requestHandle = (OCRequestHandle) request->requestId; response.resourceHandle = (OCResourceHandle) resource; return OCDoResponse(&response); } -#ifdef WITH_RD -static OCStackResult checkResourceExistsAtRD(const char *interfaceType, const char *resourceType, - OCResource **payload, OCDevAddr *devAddr) +static OCStackResult EHRequest(OCEntityHandlerRequest *ehRequest, OCPayloadType type, + OCServerRequest *request, OCResource *resource) { - OCResourceCollectionPayload *repPayload; - if (!payload) - { - return OC_STACK_ERROR; - } - if (OCRDCheckPublishedResource(interfaceType, resourceType, &repPayload, devAddr) == OC_STACK_OK) + return FormOCEntityHandlerRequest(ehRequest, + (OCRequestHandle)request->requestId, + request->method, + &request->devAddr, + (OCResourceHandle)resource, + request->query, + type, + request->payload, + request->payloadSize, + request->numRcvdVendorSpecificHeaderOptions, + request->rcvdVendorSpecificHeaderOptions, + (OCObserveAction)request->observationOption, + (OCObservationId)0, + request->coapID); +} + +#ifdef RD_SERVER +/** + * Find resource at the resource directory server. This resource is not local resource but a + * remote resource. + * + * @param resource The resource to check the matching resource URI. + * @param interfaceQuery The interface query parameter. + * @param resourceTypeQuery The resourceType query parameter. + * @param discPayload The payload that will be added with the resource information if found at RD. + * + * @return ::OC_STACK_OK if the resource is found else ::OC_STACK_NO_RESOURCE. + * In case if build is not with flag RD_SERVER, it returns ::OC_STACK_NO_RESOURCE. + */ +static OCStackResult findResourceAtRD(const OCResource* resource, const char *interfaceQuery, + const char *resourceTypeQuery, OCDiscoveryPayload *discPayload) +{ + if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0) { - if (!repPayload) + if (OC_STACK_OK == OCRDDatabaseCheckResources(interfaceQuery, resourceTypeQuery, discPayload)) { - return OC_STACK_ERROR; - } - OCResource *ptr = ((OCResource *) OICCalloc(1, sizeof(OCResource))); - if (!ptr) - { - return OC_STACK_NO_MEMORY; + return OC_STACK_OK; } + } - ptr->uri = OICStrdup(repPayload->setLinks->href); - if (!ptr->uri) - { - return OC_STACK_NO_MEMORY; - } - OCStringLL *rt = repPayload->setLinks->rt; - while (rt) - { - OCResourceType *temp = (OCResourceType *) OICCalloc(1, sizeof(OCResourceType)); - if(!temp) - { - OICFree(ptr->uri); - return OC_STACK_NO_MEMORY; - } - temp->next = NULL; - temp->resourcetypename = OICStrdup(rt->value); - if (!ptr->rsrcType) - { - ptr->rsrcType = temp; - } - else - { - OCResourceType *type = ptr->rsrcType; - while (type->next) - { - type = type->next; - } - type->next = temp; - } - rt = rt->next; - } + return OC_STACK_NO_RESOURCE; +} +#endif - OCStringLL *itf = repPayload->setLinks->itf; - while (itf) - { - OCResourceInterface *temp = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface)); - if (!temp) - { - OICFree(ptr->uri); +/** + * Creates a discovery payload and add device id information. This information is included in all + * /oic/res response. + * + * @param payload payload that will have memory alllocated and device id information added. + * + * @return ::OC_STACK_OK if successful in allocating memory and adding ID information. + * ::OC_STACK_NO_MEMORY if failed allocating the memory. + */ +static OCStackResult discoveryPayloadCreateAndAddDeviceId(OCPayload **payload) +{ + if (*payload) + { + OIC_LOG(DEBUG, TAG, "Payload is already allocated"); + return OC_STACK_OK; + } - return OC_STACK_NO_MEMORY; - } - temp->next = NULL; - temp->name = OICStrdup(itf->value); - if (!ptr->rsrcInterface) - { - ptr->rsrcInterface = temp; - } - else - { - OCResourceInterface *type = ptr->rsrcInterface; - while (type->next) - { - type = type->next; - } - type->next = temp; - } - itf = itf->next; - } + *payload = (OCPayload *) OCDiscoveryPayloadCreate(); + VERIFY_PARAM_NON_NULL(TAG, *payload, "Failed adding device id to discovery payload."); - ptr->resourceProperties = (OCResourceProperty) repPayload->tags->bitmap; + { + OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)*payload; + discPayload->sid = (char *)OICCalloc(1, UUID_STRING_SIZE); + VERIFY_PARAM_NON_NULL(TAG, discPayload->sid, "Failed adding device id to discovery payload."); + + const char* uid = OCGetServerInstanceIDString(); + if (uid) + { + memcpy(discPayload->sid, uid, UUID_STRING_SIZE); + } - OCFreeCollectionResource(repPayload); - *payload = ptr; - return OC_STACK_OK; } - else + return OC_STACK_OK; +exit: + OCPayloadDestroy(*payload); + return OC_STACK_NO_MEMORY; +} + +/** + * Add the common properties to the payload, they are only included in case of oic.if.baseline response. + * + * @param discPayload payload that will have the baseline information included. + * + * @return ::OC_STACK_OK if successful in adding all the information. ::OC_STACK_NO_MEMORY if failed + * allocating the memory for the baseline information. + */ +static OCStackResult addDiscoveryBaselineCommonProperties(OCDiscoveryPayload *discPayload) +{ + if (!discPayload) { - OIC_LOG_V(ERROR, TAG, "The resource type or interface type doe not exist \ - on the resource directory"); + OIC_LOG(ERROR, TAG, "Payload is not allocated"); + return OC_STACK_ERROR; } - return OC_STACK_ERROR; + + OCGetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, (void **)&discPayload->name); + + discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL)); + VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt to discovery payload."); + discPayload->type->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES); + VERIFY_PARAM_NON_NULL(TAG, discPayload->type, "Failed adding rt value to discovery payload."); + + OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_LL); + OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_DEFAULT); + VERIFY_PARAM_NON_NULL(TAG, discPayload->iface, "Failed adding if to discovery payload."); + + return OC_STACK_OK; + +exit: + return OC_STACK_NO_MEMORY; +} + +static bool isUnicast(OCServerRequest *request) +{ + bool isMulticast = request->devAddr.flags & OC_MULTICAST; + return (isMulticast == false && + (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) && + (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE)); } -#endif static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource) { @@ -704,205 +955,101 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource return OC_STACK_INVALID_PARAM; } - OCStackResult discoveryResult = OC_STACK_ERROR; OCPayload* payload = NULL; + char *interfaceQuery = NULL; + char *resourceTypeQuery = NULL; OIC_LOG(INFO, TAG, "Entering HandleVirtualResource"); OCVirtualResources virtualUriInRequest = GetTypeOfVirtualURI (request->resourceUrl); - // Step 1: Generate the response to discovery request - if (virtualUriInRequest == OC_WELL_KNOWN_URI) +#ifdef TCP_ADAPTER + if (OC_KEEPALIVE_RESOURCE_URI == virtualUriInRequest) { - if (request->method == OC_REST_PUT || request->method == OC_REST_POST || request->method == OC_REST_DELETE) - { - OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d", request->resourceUrl, request->method); - return OC_STACK_UNAUTHORIZED_REQ; - } + // Received request for a keepalive + OIC_LOG(INFO, TAG, "Request is for KeepAlive Request"); + return OCHandleKeepAliveRequest(request, resource); + } +#endif - char *interfaceQuery = NULL; - char *resourceTypeQuery = NULL; + OCStackResult discoveryResult = OC_STACK_ERROR; + if (request->method == OC_REST_PUT || request->method == OC_REST_POST || + request->method == OC_REST_DELETE) + { + OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d", + request->resourceUrl, request->method); + return OC_STACK_UNAUTHORIZED_REQ; + } - discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query, + // Step 1: Generate the response to discovery request + if (virtualUriInRequest == OC_WELL_KNOWN_URI +#ifdef MQ_BROKER + || virtualUriInRequest == OC_MQ_BROKER_URI +#endif + ) + { + discoveryResult = getQueryParamsForFiltering(virtualUriInRequest, request->query, &interfaceQuery, &resourceTypeQuery); - bool interfaceQueryAllocated = false; + VERIFY_SUCCESS(discoveryResult); + if (!interfaceQuery && !resourceTypeQuery) { - interfaceQueryAllocated = true; + // If no query is sent, default interface is used i.e. oic.if.ll. interfaceQuery = OICStrdup(OC_RSRVD_INTERFACE_LL); } - if (discoveryResult == OC_STACK_OK) - { - payload = (OCPayload *)OCDiscoveryPayloadCreate(); + discoveryResult = discoveryPayloadCreateAndAddDeviceId(&payload); + VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating Discovery Payload."); + VERIFY_SUCCESS(discoveryResult); - if (payload) + OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload; + if (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_DEFAULT)) + { + discoveryResult = addDiscoveryBaselineCommonProperties(discPayload); + VERIFY_SUCCESS(discoveryResult); + } + OCResourceProperty prop = OC_DISCOVERABLE; +#ifdef MQ_BROKER + prop = (OC_MQ_BROKER_URI == virtualUriInRequest) ? OC_MQ_BROKER : prop; +#endif + for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next) + { + // This case will handle when no resource type and it is oic.if.ll. + // Do not assume check if the query is ll + if (!resourceTypeQuery && + (interfaceQuery && 0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL))) { - OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload; - discPayload->sid = (char *)OICCalloc(1, UUID_STRING_SIZE); - VERIFY_NON_NULL(discPayload->sid, ERROR, OC_STACK_NO_MEMORY); - - const char* uid = OCGetServerInstanceIDString(); - if (uid) + // Only include discoverable type + if (resource->resourceProperties & prop) { - memcpy(discPayload->sid, uid, UUID_STRING_SIZE); - } - - if (!resourceTypeQuery && interfaceQuery && (0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL))) - { - for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next) - { - bool result = false; - if (resource->resourceProperties & OC_DISCOVERABLE) - { - result = true; - } - - if (result) - { - discoveryResult = BuildVirtualResourceResponse(resource, - discPayload, &request->devAddr, false); - } - } - } - else - { - if (interfaceQuery && (0 != strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL))) - { - discPayload->uri = OICStrdup(OC_RSRVD_WELL_KNOWN_URI); - VERIFY_NON_NULL(discPayload->uri, ERROR, OC_STACK_NO_MEMORY); - if (savedDeviceInfo.deviceName) - { - discPayload->name = OICStrdup(savedDeviceInfo.deviceName); - VERIFY_NON_NULL(discPayload->name, ERROR, OC_STACK_NO_MEMORY); - } - discPayload->type = (OCStringLL*)OICCalloc(1, sizeof(OCStringLL)); - VERIFY_NON_NULL(discPayload->type, ERROR, OC_STACK_NO_MEMORY); - discPayload->type->value = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES); - VERIFY_NON_NULL(discPayload->type->value, ERROR, OC_STACK_NO_MEMORY); - OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_LL); - OCResourcePayloadAddStringLL(&discPayload->iface, OC_RSRVD_INTERFACE_DEFAULT); - VERIFY_NON_NULL(discPayload->iface, ERROR, OC_STACK_NO_MEMORY); - } - bool foundResourceAtRD = false; - for (;resource && discoveryResult == OC_STACK_OK; resource = resource->next) - { -#ifdef WITH_RD - if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0) - { - OCResource *resource1 = NULL; - OCDevAddr devAddr; - discoveryResult = checkResourceExistsAtRD(interfaceQuery, - resourceTypeQuery, &resource1, &devAddr); - if (discoveryResult != OC_STACK_OK) - { - break; - } - discoveryResult = BuildVirtualResourceResponse(resource1, - discPayload, &devAddr, true); - if (payload) - { - discPayload->baseURI = OICStrdup(devAddr.addr); - } - OICFree(resource1->uri); - for (OCResourceType *rsrcRt = resource1->rsrcType, *rsrcRtNext = NULL; rsrcRt; ) - { - rsrcRtNext = rsrcRt->next; - OICFree(rsrcRt->resourcetypename); - OICFree(rsrcRt); - rsrcRt = rsrcRtNext; - } - - for (OCResourceInterface *rsrcPtr = resource1->rsrcInterface, *rsrcNext = NULL; rsrcPtr; ) - { - rsrcNext = rsrcPtr->next; - OICFree(rsrcPtr->name); - OICFree(rsrcPtr); - rsrcPtr = rsrcNext; - } - foundResourceAtRD = true; - } -#endif - if (!foundResourceAtRD && includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery)) - { - discoveryResult = BuildVirtualResourceResponse(resource, - discPayload, &request->devAddr, false); - } - } - // Set discoveryResult appropriately if no 'valid' resources are available - if (discPayload->resources == NULL && !foundResourceAtRD) - { - discoveryResult = OC_STACK_NO_RESOURCE; - } + discoveryResult = BuildVirtualResourceResponse(resource, discPayload, &request->devAddr); } } + else if (includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery)) + { + discoveryResult = BuildVirtualResourceResponse(resource, discPayload, &request->devAddr); + } else { - discoveryResult = OC_STACK_NO_MEMORY; + discoveryResult = OC_STACK_OK; } } - else - { - OIC_LOG_V(ERROR, TAG, "Error (%d) parsing query.", discoveryResult); - } - if (interfaceQueryAllocated) + if (discPayload->resources == NULL) { - OICFree(interfaceQuery); + discoveryResult = OC_STACK_NO_RESOURCE; } } else if (virtualUriInRequest == OC_DEVICE_URI) { - if (request->method == OC_REST_PUT || request->method == OC_REST_POST || request->method == OC_REST_DELETE) - { - OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d", request->resourceUrl, request->method); - return OC_STACK_UNAUTHORIZED_REQ; - } - - const char* deviceId = OCGetServerInstanceIDString(); - if (!deviceId) - { - discoveryResult = OC_STACK_ERROR; - } - else - { - char *dataModelVersions = OCCreateString(savedDeviceInfo.dataModelVersions); - if (!dataModelVersions) - { - discoveryResult = OC_STACK_NO_MEMORY; - } - else - { - payload = (OCPayload*) OCDevicePayloadCreate(deviceId, savedDeviceInfo.deviceName, - savedDeviceInfo.types, savedDeviceInfo.specVersion, dataModelVersions); - if (!payload) - { - discoveryResult = OC_STACK_NO_MEMORY; - } - else - { - discoveryResult = OC_STACK_OK; - } - OICFree(dataModelVersions); - } - } + OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_DEVICE_URI); + VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Device URI not found."); + discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, true); } else if (virtualUriInRequest == OC_PLATFORM_URI) { - if (request->method == OC_REST_PUT || request->method == OC_REST_POST || request->method == OC_REST_DELETE) - { - OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d", request->resourceUrl, request->method); - return OC_STACK_UNAUTHORIZED_REQ; - } - - payload = (OCPayload*)OCPlatformPayloadCreate(&savedPlatformInfo); - if (!payload) - { - discoveryResult = OC_STACK_NO_MEMORY; - } - else - { - discoveryResult = OC_STACK_OK; - } + OCResource *resourcePtr = FindResourceByUri(OC_RSRVD_PLATFORM_URI); + VERIFY_PARAM_NON_NULL(TAG, resourcePtr, "Platform URI not found."); + discoveryResult = BuildDevicePlatformPayload(resourcePtr, (OCRepPayload **)&payload, false); } #ifdef ROUTING_GATEWAY else if (OC_GATEWAY_URI == virtualUriInRequest) @@ -910,7 +1057,6 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource // Received request for a gateway OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request"); discoveryResult = RMHandleGatewayRequest(request, resource); - } #endif @@ -932,68 +1078,83 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource if ((virtualUriInRequest == OC_PRESENCE) && (resource->resourceProperties & OC_ACTIVE)) { + // Need to send ACK when the request is CON. + if (request->qos == OC_HIGH_QOS) + { + CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER }; + CopyDevAddrToEndpoint(&request->devAddr, &endpoint); + SendDirectStackResponse(&endpoint, request->coapID, CA_EMPTY, CA_MSG_ACKNOWLEDGE, + 0, NULL, NULL, 0, NULL, CA_RESPONSE_FOR_RES); + } + FindAndDeleteServerRequest(request); + // Presence uses observer notification api to respond via SendPresenceNotification. SendPresenceNotification(resource->rsrcType, OC_PRESENCE_TRIGGER_CHANGE); } else - #endif -#ifdef ROUTING_GATEWAY +#endif +#if ROUTING_GATEWAY // Gateway uses the RMHandleGatewayRequest to respond to the request. if (OC_GATEWAY_URI != virtualUriInRequest) #endif { + OIC_LOG_PAYLOAD(DEBUG, payload); if(discoveryResult == OC_STACK_OK) { + SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK); } - else if(((request->devAddr.flags & OC_MULTICAST) == false) && - (request->devAddr.adapter != OC_ADAPTER_RFCOMM_BTEDR) && - (request->devAddr.adapter != OC_ADAPTER_GATT_BTLE)) - { - OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request", - discoveryResult, virtualUriInRequest); - SendNonPersistantDiscoveryResponse(request, resource, NULL, - (discoveryResult == OC_STACK_NO_RESOURCE) ? OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR); - } - else + else // Error handling { - // Ignoring the discovery request as per RFC 7252, Section #8.2 - OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send. "); + if (isUnicast(request)) + { + OIC_LOG_V(ERROR, TAG, "Sending a (%d) error to (%d) discovery request", + discoveryResult, virtualUriInRequest); + SendNonPersistantDiscoveryResponse(request, resource, NULL, + (discoveryResult == OC_STACK_NO_RESOURCE) ? + OC_EH_RESOURCE_NOT_FOUND : OC_EH_ERROR); + } + else // Multicast + { + // Ignoring the discovery request as per RFC 7252, Section #8.2 + OIC_LOG(INFO, TAG, "Silently ignoring the request since no useful data to send."); + // the request should be removed. + // since it never remove and causes a big memory waste. + FindAndDeleteServerRequest(request); + } + discoveryResult = OC_STACK_CONTINUE; } } +exit: + if (interfaceQuery) + { + OICFree(interfaceQuery); + } + + if (resourceTypeQuery) + { + OICFree(resourceTypeQuery); + } OCPayloadDestroy(payload); - return OC_STACK_OK; + // To ignore the message, OC_STACK_CONTINUE is sent + return discoveryResult; } static OCStackResult -HandleDefaultDeviceEntityHandler (OCServerRequest *request) +HandleDefaultDeviceEntityHandler(OCServerRequest *request) { - if(!request) + if (!request) { return OC_STACK_INVALID_PARAM; } - OCStackResult result = OC_STACK_OK; OCEntityHandlerResult ehResult = OC_EH_ERROR; OCEntityHandlerRequest ehRequest = {0}; - OIC_LOG(INFO, TAG, "Entering HandleResourceWithDefaultDeviceEntityHandler"); - result = FormOCEntityHandlerRequest(&ehRequest, - (OCRequestHandle) request, - request->method, - &request->devAddr, - (OCResourceHandle) NULL, request->query, - PAYLOAD_TYPE_REPRESENTATION, - request->payload, - request->payloadSize, - request->numRcvdVendorSpecificHeaderOptions, - request->rcvdVendorSpecificHeaderOptions, - (OCObserveAction)request->observationOption, - (OCObservationId)0, - request->coapID); - VERIFY_SUCCESS(result, OC_STACK_OK); + OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, NULL); + VERIFY_SUCCESS(result); // At this point we know for sure that defaultDeviceHandler exists ehResult = defaultDeviceHandler(OC_REQUEST_FLAG, &ehRequest, @@ -1014,9 +1175,8 @@ exit: } static OCStackResult -HandleResourceWithEntityHandler (OCServerRequest *request, - OCResource *resource, - uint8_t collectionResource) +HandleResourceWithEntityHandler(OCServerRequest *request, + OCResource *resource) { if(!request || ! resource) { @@ -1036,36 +1196,17 @@ HandleResourceWithEntityHandler (OCServerRequest *request, if (request && request->resourceUrl && SRMIsSecurityResourceURI(request->resourceUrl)) { type = PAYLOAD_TYPE_SECURITY; - - } - - if (request && strcmp(request->resourceUrl, OC_RSRVD_RD_URI) == 0) - { - type = PAYLOAD_TYPE_RD; } - result = FormOCEntityHandlerRequest(&ehRequest, - (OCRequestHandle)request, - request->method, - &request->devAddr, - (OCResourceHandle)resource, - request->query, - type, - request->payload, - request->payloadSize, - request->numRcvdVendorSpecificHeaderOptions, - request->rcvdVendorSpecificHeaderOptions, - (OCObserveAction)request->observationOption, - 0, - request->coapID); - VERIFY_SUCCESS(result, OC_STACK_OK); + result = EHRequest(&ehRequest, type, request, resource); + VERIFY_SUCCESS(result); if(ehRequest.obsInfo.action == OC_OBSERVE_NO_OPTION) { OIC_LOG(INFO, TAG, "No observation requested"); ehFlag = OC_REQUEST_FLAG; } - else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER && !collectionResource) + else if(ehRequest.obsInfo.action == OC_OBSERVE_REGISTER) { OIC_LOG(INFO, TAG, "Observation registration requested"); @@ -1088,7 +1229,7 @@ HandleResourceWithEntityHandler (OCServerRequest *request, } result = GenerateObserverId(&ehRequest.obsInfo.obsId); - VERIFY_SUCCESS(result, OC_STACK_OK); + VERIFY_SUCCESS(result); result = AddObserver ((const char*)(request->resourceUrl), (const char *)(request->query), @@ -1102,6 +1243,12 @@ HandleResourceWithEntityHandler (OCServerRequest *request, request->observeResult = OC_STACK_OK; ehFlag = (OCEntityHandlerFlag)(OC_REQUEST_FLAG | OC_OBSERVE_FLAG); } + else if (result == OC_STACK_RESOURCE_ERROR) + { + OIC_LOG(INFO, TAG, "The Resource is not active, discoverable or observable"); + request->observeResult = OC_STACK_ERROR; + ehFlag = OC_REQUEST_FLAG; + } else { // The error in observeResult for the request will be used when responding to this @@ -1114,8 +1261,7 @@ HandleResourceWithEntityHandler (OCServerRequest *request, } } - else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER && - !collectionResource) + else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER) { OIC_LOG(INFO, TAG, "Deregistering observation requested"); @@ -1125,7 +1271,7 @@ HandleResourceWithEntityHandler (OCServerRequest *request, { // Stack does not contain this observation request // Either token is incorrect or observation list is corrupted - result = OC_STACK_ERROR; + result = OC_STACK_NO_RESOURCE; goto exit; } ehRequest.obsInfo.obsId = resObs->observeId; @@ -1137,6 +1283,9 @@ HandleResourceWithEntityHandler (OCServerRequest *request, { OIC_LOG(INFO, TAG, "Removed observer successfully"); request->observeResult = OC_STACK_OK; + // There should be no observe option header for de-registration response. + // Set as an invalid value here so we can detect it later and remove the field in response. + request->observationOption = MAX_SEQUENCE_NUMBER + 1; } else { @@ -1168,32 +1317,16 @@ exit: return result; } -static OCStackResult -HandleCollectionResourceDefaultEntityHandler (OCServerRequest *request, - OCResource *resource) +static OCStackResult HandleCollectionResourceDefaultEntityHandler(OCServerRequest *request, + OCResource *resource) { - if(!request || !resource) + if (!request || !resource) { return OC_STACK_INVALID_PARAM; } - OCStackResult result = OC_STACK_ERROR; OCEntityHandlerRequest ehRequest = {0}; - - result = FormOCEntityHandlerRequest(&ehRequest, - (OCRequestHandle)request, - request->method, - &request->devAddr, - (OCResourceHandle)resource, - request->query, - PAYLOAD_TYPE_REPRESENTATION, - request->payload, - request->payloadSize, - request->numRcvdVendorSpecificHeaderOptions, - request->rcvdVendorSpecificHeaderOptions, - (OCObserveAction)request->observationOption, - (OCObservationId)0, - request->coapID); + OCStackResult result = EHRequest(&ehRequest, PAYLOAD_TYPE_REPRESENTATION, request, resource); if(result == OC_STACK_OK) { result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest); @@ -1227,12 +1360,12 @@ ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerReque } case OC_RESOURCE_NOT_COLLECTION_WITH_ENTITYHANDLER: { - ret = HandleResourceWithEntityHandler (request, resource, 0); + ret = HandleResourceWithEntityHandler (request, resource); break; } case OC_RESOURCE_COLLECTION_WITH_ENTITYHANDLER: { - ret = HandleResourceWithEntityHandler (request, resource, 1); + ret = HandleResourceWithEntityHandler (request, resource); break; } case OC_RESOURCE_COLLECTION_DEFAULT_ENTITYHANDLER: @@ -1254,224 +1387,242 @@ ProcessRequest(ResourceHandling resHandling, OCResource *resource, OCServerReque return ret; } -void DeletePlatformInfo() +OCStackResult OCSetPlatformInfo(OCPlatformInfo info) { - OIC_LOG(INFO, TAG, "Deleting platform info."); - - OICFree(savedPlatformInfo.platformID); - savedPlatformInfo.platformID = NULL; - - OICFree(savedPlatformInfo.manufacturerName); - savedPlatformInfo.manufacturerName = NULL; - - OICFree(savedPlatformInfo.manufacturerUrl); - savedPlatformInfo.manufacturerUrl = NULL; - - OICFree(savedPlatformInfo.modelNumber); - savedPlatformInfo.modelNumber = NULL; - - OICFree(savedPlatformInfo.dateOfManufacture); - savedPlatformInfo.dateOfManufacture = NULL; - - OICFree(savedPlatformInfo.platformVersion); - savedPlatformInfo.platformVersion = NULL; - - OICFree(savedPlatformInfo.operatingSystemVersion); - savedPlatformInfo.operatingSystemVersion = NULL; - - OICFree(savedPlatformInfo.hardwareVersion); - savedPlatformInfo.hardwareVersion = NULL; - - OICFree(savedPlatformInfo.firmwareVersion); - savedPlatformInfo.firmwareVersion = NULL; - - OICFree(savedPlatformInfo.supportUrl); - savedPlatformInfo.supportUrl = NULL; - - OICFree(savedPlatformInfo.systemTime); - savedPlatformInfo.systemTime = NULL; -} - -static OCStackResult DeepCopyPlatFormInfo(OCPlatformInfo info) -{ - savedPlatformInfo.platformID = OICStrdup(info.platformID); - savedPlatformInfo.manufacturerName = OICStrdup(info.manufacturerName); - savedPlatformInfo.manufacturerUrl = OICStrdup(info.manufacturerUrl); - savedPlatformInfo.modelNumber = OICStrdup(info.modelNumber); - savedPlatformInfo.dateOfManufacture = OICStrdup(info.dateOfManufacture); - savedPlatformInfo.platformVersion = OICStrdup(info.platformVersion); - savedPlatformInfo.operatingSystemVersion = OICStrdup(info.operatingSystemVersion); - savedPlatformInfo.hardwareVersion = OICStrdup(info.hardwareVersion); - savedPlatformInfo.firmwareVersion = OICStrdup(info.firmwareVersion); - savedPlatformInfo.supportUrl = OICStrdup(info.supportUrl); - savedPlatformInfo.systemTime = OICStrdup(info.systemTime); - - if ((!savedPlatformInfo.platformID && info.platformID)|| - (!savedPlatformInfo.manufacturerName && info.manufacturerName)|| - (!savedPlatformInfo.manufacturerUrl && info.manufacturerUrl)|| - (!savedPlatformInfo.modelNumber && info.modelNumber)|| - (!savedPlatformInfo.dateOfManufacture && info.dateOfManufacture)|| - (!savedPlatformInfo.platformVersion && info.platformVersion)|| - (!savedPlatformInfo.operatingSystemVersion && info.operatingSystemVersion)|| - (!savedPlatformInfo.hardwareVersion && info.hardwareVersion)|| - (!savedPlatformInfo.firmwareVersion && info.firmwareVersion)|| - (!savedPlatformInfo.supportUrl && info.supportUrl)|| - (!savedPlatformInfo.systemTime && info.systemTime)) - { - DeletePlatformInfo(); - return OC_STACK_INVALID_PARAM; + OCResource *resource = NULL; + if (!info.platformID || !info.manufacturerName) + { + OIC_LOG(ERROR, TAG, "No value specified."); + goto exit; + } + if (0 == strlen(info.platformID) || 0 == strlen(info.manufacturerName)) + { + OIC_LOG(ERROR, TAG, "The passed value cannot be empty"); + goto exit; + } + if ((info.manufacturerName && strlen(info.manufacturerName) > MAX_PLATFORM_NAME_LENGTH) || + (info.manufacturerUrl && strlen(info.manufacturerUrl) > MAX_PLATFORM_URL_LENGTH) || + (info.modelNumber && strlen(info.modelNumber) > MAX_PLATFORM_NAME_LENGTH) || + (info.platformVersion && strlen(info.platformVersion) > MAX_PLATFORM_NAME_LENGTH) || + (info.operatingSystemVersion && strlen(info.operatingSystemVersion) > MAX_PLATFORM_NAME_LENGTH) || + (info.hardwareVersion && strlen(info.hardwareVersion) > MAX_PLATFORM_NAME_LENGTH) || + (info.firmwareVersion && strlen(info.firmwareVersion) > MAX_PLATFORM_NAME_LENGTH) || + (info.supportUrl && strlen(info.supportUrl) > MAX_PLATFORM_URL_LENGTH)) + { + OIC_LOG(ERROR, TAG, "The passed value is bigger than permitted."); + goto exit; } + resource = FindResourceByUri(OC_RSRVD_PLATFORM_URI); + if (!resource) + { + OIC_LOG(ERROR, TAG, "Platform Resource does not exist."); + goto exit; + } + OIC_LOG(INFO, TAG, "Entering OCSetPlatformInfo"); + VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_ID, info.platformID)); + VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_NAME, info.manufacturerName)); + OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_URL, info.manufacturerUrl); + OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MODEL_NUM, info.modelNumber); + OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_MFG_DATE, info.dateOfManufacture); + OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_PLATFORM_VERSION, info.platformVersion); + OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_OS_VERSION, info.operatingSystemVersion); + OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_HARDWARE_VERSION, info.hardwareVersion); + OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_FIRMWARE_VERSION, info.firmwareVersion); + OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SUPPORT_URL, info.supportUrl); + OCSetPropertyValue(PAYLOAD_TYPE_PLATFORM, OC_RSRVD_SYSTEM_TIME, info.systemTime); + OIC_LOG(INFO, TAG, "Platform parameter initialized successfully."); return OC_STACK_OK; +exit: + return OC_STACK_INVALID_PARAM; } -OCStackResult SavePlatformInfo(OCPlatformInfo info) +OCStackResult OCSetDeviceInfo(OCDeviceInfo info) { - DeletePlatformInfo(); + OCStringLL *dataModelVersion = NULL; + OCResource *resource = FindResourceByUri(OC_RSRVD_DEVICE_URI); + if (!resource) + { + OIC_LOG(ERROR, TAG, "Device Resource does not exist."); + goto exit; + } + if (!info.deviceName || info.deviceName[0] == '\0') + { + OIC_LOG(ERROR, TAG, "Null or empty device name."); + return OC_STACK_INVALID_PARAM; + } - OCStackResult res = DeepCopyPlatFormInfo(info); + if (OCGetServerInstanceIDString() == NULL) + { + OIC_LOG(INFO, TAG, "Device ID generation failed"); + goto exit; + } - if (res != OC_STACK_OK) + VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DEVICE_NAME, info.deviceName)); + for (OCStringLL *temp = info.types; temp; temp = temp->next) { - OIC_LOG_V(ERROR, TAG, "Failed to save platform info. errno(%d)", res); + if (temp->value) + { + VERIFY_SUCCESS(OCBindResourceTypeToResource(resource, temp->value)); + } + } + VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_SPEC_VERSION, info.specVersion ? + info.specVersion: OC_SPEC_VERSION)); + if (info.dataModelVersions) + { + VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, info.dataModelVersions)); } else { - OIC_LOG(INFO, TAG, "Platform info saved."); + dataModelVersion = OCCreateOCStringLL(OC_DATA_MODEL_VERSION); + VERIFY_SUCCESS(OCSetPropertyValue(PAYLOAD_TYPE_DEVICE, OC_RSRVD_DATA_MODEL_VERSION, dataModelVersion)); +#ifdef __TIZENRT__ + OCFreeOCStringLL(dataModelVersion); +#endif } + OIC_LOG(INFO, TAG, "Device parameter initialized successfully."); + return OC_STACK_OK; - return res; -} - -void DeleteDeviceInfo() -{ - OIC_LOG(INFO, TAG, "Deleting device info."); - - OICFree(savedDeviceInfo.deviceName); - OCFreeOCStringLL(savedDeviceInfo.types); - OICFree(savedDeviceInfo.specVersion); - OCFreeOCStringLL(savedDeviceInfo.dataModelVersions); - savedDeviceInfo.deviceName = NULL; - savedDeviceInfo.specVersion = NULL; - savedDeviceInfo.dataModelVersions = NULL; +exit: + if (dataModelVersion) + { + OCFreeOCStringLL(dataModelVersion); + } + return OC_STACK_ERROR; } -static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info) +OCStackResult OCGetAttribute(const OCResource *resource, const char *attribute, void **value) { - savedDeviceInfo.deviceName = OICStrdup(info.deviceName); - - if(!savedDeviceInfo.deviceName && info.deviceName) + if (!resource || !attribute) { - DeleteDeviceInfo(); - return OC_STACK_NO_MEMORY; + return OC_STACK_INVALID_PARAM; } - - if (info.types) + if (0 == strlen(attribute)) { - savedDeviceInfo.types = CloneOCStringLL(info.types); - OCStringLL *type = info.types; - bool found = false; - while (type) - { - if (type && type->value && 0 == strcmp(type->value, OC_RSRVD_RESOURCE_TYPE_DEVICE)) - { - found = true; - } - type = type->next; - } - if (!found) + return OC_STACK_INVALID_PARAM; + } + for (OCAttribute *temp = resource->rsrcAttributes; temp; temp = temp->next) + { + if (0 == strcmp(attribute, temp->attrName)) { - // Append the oic.wk.d at the start of rt link parameter value. - OCStringLL *dest = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL)); - if (!dest) + // A special case as this type return OCStringLL + if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute)) { - DeleteDeviceInfo(); - return OC_STACK_NO_MEMORY; + *value = CloneOCStringLL((OCStringLL *)temp->attrValue); + return OC_STACK_OK; } - dest->value = OICStrdup (OC_RSRVD_RESOURCE_TYPE_DEVICE); - if (!dest->value) + else { - DeleteDeviceInfo(); - return OC_STACK_NO_MEMORY; + *value = OICStrdup((char *)temp->attrValue); + return OC_STACK_OK; } - dest->next = savedDeviceInfo.types; - savedDeviceInfo.types = dest; - } - if(!savedDeviceInfo.types && info.types) - { - DeleteDeviceInfo(); - return OC_STACK_NO_MEMORY; } } + return OC_STACK_NO_RESOURCE; +} - if (info.specVersion) +OCStackResult OCGetPropertyValue(OCPayloadType type, const char *prop, void **value) +{ + if (!prop || *value) { - savedDeviceInfo.specVersion = OICStrdup(info.specVersion); - if(!savedDeviceInfo.specVersion && info.specVersion) - { - DeleteDeviceInfo(); - return OC_STACK_NO_MEMORY; - } + return OC_STACK_INVALID_PARAM; } - else + if (strlen(prop) == 0) { - savedDeviceInfo.specVersion = OICStrdup(OC_SPEC_VERSION); - if(!savedDeviceInfo.specVersion && OC_SPEC_VERSION) + return OC_STACK_INVALID_PARAM; + } + OCStackResult res = OC_STACK_NO_RESOURCE; + if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type) + { + const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI; + OCResource *resource = FindResourceByUri(pathType); + if (!resource) { - DeleteDeviceInfo(); - return OC_STACK_NO_MEMORY; + return OC_STACK_NO_RESOURCE; } + + res = OCGetAttribute(resource, prop, value); } + return res; +} - if (info.dataModelVersions) +OCStackResult OCSetAttribute(OCResource* resource, const char* attribute, const void* value) +{ + // See if the attribute already exists in the list. + OCAttribute *resAttrib; + for (resAttrib = resource->rsrcAttributes; resAttrib; resAttrib = resAttrib->next) { - savedDeviceInfo.dataModelVersions = CloneOCStringLL(info.dataModelVersions); - if(!savedDeviceInfo.dataModelVersions && info.dataModelVersions) + if (0 == strcmp(attribute, resAttrib->attrName)) { - DeleteDeviceInfo(); - return OC_STACK_NO_MEMORY; + // Found, free the old value. + if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, resAttrib->attrName)) + { + OCFreeOCStringLL((OCStringLL *)resAttrib->attrValue); + } + else + { + OICFree((char *)resAttrib->attrValue); + } + break; } } + + // If not already in the list, add it. + if (NULL == resAttrib) + { + resAttrib = (OCAttribute *)OICCalloc(1, sizeof(OCAttribute)); + VERIFY_PARAM_NON_NULL(TAG, resAttrib, "Failed allocating OCAttribute"); + resAttrib->attrName = OICStrdup(attribute); + VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrName, "Failed allocating attribute name"); + resAttrib->next = resource->rsrcAttributes; + resource->rsrcAttributes = resAttrib; + } + + // Fill in the new value. + if (0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, attribute)) + { + resAttrib->attrValue = CloneOCStringLL((OCStringLL *)value); + } else { - savedDeviceInfo.dataModelVersions = (OCStringLL *)OICCalloc(1,sizeof(OCStringLL)); - if (!savedDeviceInfo.dataModelVersions) - { - return OC_STACK_NO_MEMORY; - } - savedDeviceInfo.dataModelVersions->value = OICStrdup(OC_DATA_MODEL_VERSION); - if(!savedDeviceInfo.dataModelVersions->value && OC_DATA_MODEL_VERSION) - { - DeleteDeviceInfo(); - return OC_STACK_NO_MEMORY; - } + resAttrib->attrValue = OICStrdup((char *)value); } + VERIFY_PARAM_NON_NULL(TAG, resAttrib->attrValue, "Failed allocating attribute value"); return OC_STACK_OK; -} -OCStackResult SaveDeviceInfo(OCDeviceInfo info) -{ - OCStackResult res = OC_STACK_OK; - - DeleteDeviceInfo(); - - res = DeepCopyDeviceInfo(info); +exit: + OCDeleteResourceAttributes(resAttrib); + return OC_STACK_NO_MEMORY; - VERIFY_SUCCESS(res, OC_STACK_OK); +} - if (OCGetServerInstanceIDString() == NULL) +OCStackResult OCSetPropertyValue(OCPayloadType type, const char *prop, const void *value) +{ + if (!prop || !value) { - OIC_LOG(INFO, TAG, "Device ID generation failed"); - res = OC_STACK_ERROR; - goto exit; + return OC_STACK_INVALID_PARAM; + } + if (strlen(prop) == 0) + { + return OC_STACK_INVALID_PARAM; } - OIC_LOG(INFO, TAG, "Device initialized successfully."); - return OC_STACK_OK; + OCStackResult res = OC_STACK_ERROR; + if (PAYLOAD_TYPE_DEVICE == type || PAYLOAD_TYPE_PLATFORM == type) + { + const char *pathType = (type == PAYLOAD_TYPE_DEVICE) ? OC_RSRVD_DEVICE_URI : OC_RSRVD_PLATFORM_URI; + OCResource *resource = FindResourceByUri(pathType); + if (!resource) + { + OIC_LOG(ERROR, TAG, "Resource does not exist."); + } + else + { + res = OCSetAttribute(resource, prop, value); + } + } -exit: - DeleteDeviceInfo(); return res; }