// 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_ARDUINO
+#include "iotivity_config.h"
+#ifdef HAVE_STRING_H
#include <string.h>
-#else
+#endif
+#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include "secureresourcemanager.h"
#include "cacommon.h"
#include "cainterface.h"
-#include "rdpayload.h"
#include "ocpayload.h"
-
-#ifdef WITH_RD
-#include "rd_server.h"
-#endif
-
+#include "platform_features.h"
+#include "payload_logging.h"
#ifdef ROUTING_GATEWAY
#include "routingmanager.h"
#endif
+#ifdef RD_SERVER
+#include "rd_database.h"
+#endif
+
/// Module Name
#define TAG "OIC_RI_RESOURCE"
#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
{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); } }
-
extern OCResource *headResource;
static OCPlatformInfo savedPlatformInfo = {0};
static OCDeviceInfo savedDeviceInfo = {0};
*/
static OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
OCDiscoveryPayload* payload,
- OCDevAddr *endpoint,
- bool rdResponse);
+ OCDevAddr *endpoint);
//-----------------------------------------------------------------------------
// Default resource entity handler function
return OC_STACK_OK;
}
+#ifdef TCP_ADAPTER
+/* This method will retrieve the tcp port */
+static OCStackResult GetTCPPortInfo(OCDevAddr *endpoint, uint16_t *port)
+{
+ uint16_t p = 0;
+
+ if (endpoint->adapter == OC_ADAPTER_IP)
+ {
+ if (endpoint->flags & OC_IP_USE_V4)
+ {
+ p = caglobals.tcp.ipv4.port;
+ }
+ else if (endpoint->flags & OC_IP_USE_V6)
+ {
+ p = caglobals.tcp.ipv6.port;
+ }
+ }
+
+ *port = p;
+ return OC_STACK_OK;
+}
+#endif
+
/*
* Function will extract 0, 1 or 2 filters from query.
* More than 2 filters or unsupported filters will result in error.
*/
static OCStackResult ExtractFiltersFromQuery(char *query, char **filterOne, char **filterTwo)
{
-
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)
{
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)
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;
}
}
OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
- OCDiscoveryPayload *payload, OCDevAddr *devAddr, bool rdResponse)
+ OCDiscoveryPayload *payload, OCDevAddr *devAddr)
{
if (!resourcePtr || !payload)
{
return OC_STACK_INVALID_PARAM;
}
- uint16_t port = 0;
+ uint16_t securePort = 0;
if (resourcePtr->resourceProperties & OC_SECURE)
{
- if (GetSecurePortInfo(devAddr, &port) != OC_STACK_OK)
+ if (GetSecurePortInfo(devAddr, &securePort) != OC_STACK_OK)
{
- port = 0;
+ securePort = 0;
}
}
- if (rdResponse)
+#ifdef TCP_ADAPTER
+ uint16_t tcpPort = 0;
+ if (GetTCPPortInfo(devAddr, &tcpPort) != OC_STACK_OK)
{
- port = devAddr->port;
+ tcpPort = 0;
}
+ OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort, tcpPort);
+#else
+ OCDiscoveryPayloadAddResource(payload, resourcePtr, securePort);
+#endif
- OCDiscoveryPayloadAddResource(payload, resourcePtr, port);
return OC_STACK_OK;
}
switch (ehResult)
{
case OC_EH_OK:
+ case OC_EH_CONTENT:
+ case OC_EH_VALID:
result = OC_STACK_OK;
break;
case OC_EH_SLOW:
result = OC_STACK_ERROR;
break;
case OC_EH_FORBIDDEN:
- result = OC_STACK_RESOURCE_ERROR;
+ result = OC_STACK_FORBIDDEN_REQ;
+ break;
+ case OC_EH_INTERNAL_SERVER_ERROR:
+ result = OC_STACK_INTERNAL_SERVER_ERROR;
break;
case OC_EH_RESOURCE_CREATED:
result = OC_STACK_RESOURCE_CREATED;
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;
while (interfacePtr)
{
- if ((strcmp (interfacePtr->name, interfaceFilter) == 0) &&
- (strcmp (OC_RSRVD_INTERFACE_LL, interfaceFilter) == 0 ||
- strcmp (OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter) == 0))
+ if (strcmp (interfacePtr->name, interfaceFilter) == 0 ||
+ strcmp (OC_RSRVD_INTERFACE_LL, interfaceFilter) == 0 ||
+ strcmp (OC_RSRVD_INTERFACE_DEFAULT, interfaceFilter) == 0)
{
return true;
}
return OCDoResponse(&response);
}
+#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 (OC_STACK_OK == OCRDDatabaseCheckResources(interfaceQuery, resourceTypeQuery, discPayload))
+ {
+ return OC_STACK_OK;
+ }
+ }
-#ifdef WITH_RD
-static OCStackResult checkResourceExistsAtRD(const char *interfaceType, const char *resourceType,
- OCResource **payload, OCDevAddr *devAddr)
+ return OC_STACK_NO_RESOURCE;
+}
+#endif
+
+/**
+ * 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)
{
- OCResourceCollectionPayload *repPayload;
- if (!payload)
+ if (*payload)
{
- return OC_STACK_ERROR;
+ OIC_LOG_V(DEBUG, TAG, "Payload is already allocated");
+ return OC_STACK_OK;
}
- if (OCRDCheckPublishedResource(interfaceType, resourceType, &repPayload, devAddr) == OC_STACK_OK)
+
+ *payload = (OCPayload *) OCDiscoveryPayloadCreate();
+ VERIFY_PARAM_NON_NULL(TAG, *payload, "Failed adding device id to discovery payload.");
+
{
- if (!repPayload)
- {
- return OC_STACK_ERROR;
- }
- OCResource *ptr = ((OCResource *) OICCalloc(1, sizeof(OCResource)));
- if (!ptr)
- {
- return OC_STACK_NO_MEMORY;
- }
+ 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.");
- ptr->uri = OICStrdup(repPayload->setLinks->href);
- if (!ptr->uri)
+ const char* uid = OCGetServerInstanceIDString();
+ if (uid)
{
- 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;
+ memcpy(discPayload->sid, uid, UUID_STRING_SIZE);
}
- OCStringLL *itf = repPayload->setLinks->itf;
- while (itf)
- {
- OCResourceInterface *temp = (OCResourceInterface *) OICCalloc(1, sizeof(OCResourceInterface));
- if (!temp)
- {
- OICFree(ptr->uri);
-
- 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;
- }
+ }
+ return OC_STACK_OK;
+exit:
+ OCPayloadDestroy(*payload);
+ return OC_STACK_NO_MEMORY;
+}
- ptr->resourceProperties = (OCResourceProperty) repPayload->tags->bitmap;
+/**
+ * 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)
+{
+ discPayload->uri = OICStrdup(OC_RSRVD_WELL_KNOWN_URI);
+ VERIFY_PARAM_NON_NULL(TAG, discPayload->uri, "Failed adding href to discovery payload.");
- OCFreeCollectionResource(repPayload);
- *payload = ptr;
- return OC_STACK_OK;
- }
- else
+ if (savedDeviceInfo.deviceName)
{
- OIC_LOG_V(ERROR, TAG, "The resource type or interface type doe not exist \
- on the resource directory");
+ discPayload->name = OICStrdup(savedDeviceInfo.deviceName);
+ VERIFY_PARAM_NON_NULL(TAG, discPayload->name, "Failed adding name to discovery payload.");
}
- return OC_STACK_ERROR;
+
+ 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;
}
-#endif
static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
{
}
OCStackResult discoveryResult = OC_STACK_ERROR;
-
- bool bMulticast = false; // Was the discovery request a multicast request?
OCPayload* payload = NULL;
+ char *interfaceQuery = NULL;
+ char *resourceTypeQuery = NULL;
+ char *dataModelVersions = 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)
+ if (virtualUriInRequest == OC_WELL_KNOWN_URI
+#ifdef MQ_BROKER
+ || virtualUriInRequest == OC_MQ_BROKER_URI
+#endif
+ )
{
- if (request->method == OC_REST_PUT || request->method == OC_REST_POST || request->method == OC_REST_DELETE)
+ 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;
+ OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
+ request->resourceUrl, request->method);
+ discoveryResult = OC_STACK_UNAUTHORIZED_REQ;
+ goto exit;
}
- char *interfaceQuery = NULL;
- char *resourceTypeQuery = NULL;
-
discoveryResult = getQueryParamsForFiltering (virtualUriInRequest, request->query,
&interfaceQuery, &resourceTypeQuery);
- bool interfaceQueryAllocated = false;
+ VERIFY_SUCCESS(discoveryResult, OC_STACK_OK);
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)
+ bool baselineQuery = false;
+ if (interfaceQuery && 0 != strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL))
{
- payload = (OCPayload *)OCDiscoveryPayloadCreate();
+ baselineQuery = true;
+ }
- if (payload)
- {
- 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)
- {
- memcpy(discPayload->sid, uid, UUID_STRING_SIZE);
- }
+ discoveryResult = discoveryPayloadCreateAndAddDeviceId(&payload);
+ VERIFY_PARAM_NON_NULL(TAG, payload, "Failed creating Discovery Payload.");
+ VERIFY_SUCCESS(discoveryResult, OC_STACK_OK);
- if (!resourceTypeQuery && interfaceQuery && (0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
+ OCDiscoveryPayload *discPayload = (OCDiscoveryPayload *)payload;
+ if (baselineQuery)
+ {
+ discoveryResult = addDiscoveryBaselineCommonProperties(discPayload);
+ VERIFY_SUCCESS(discoveryResult, OC_STACK_OK);
+ }
+ 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)
+ {
+ discoveryResult = OC_STACK_NO_RESOURCE;
+#ifdef RD_SERVER
+ discoveryResult = findResourceAtRD(resource, interfaceQuery, resourceTypeQuery,
+ discPayload);
+#endif
+ if (OC_STACK_NO_RESOURCE == discoveryResult)
+ {
+ if ((!baselineQuery && (resource->resourceProperties & prop)) ||
+ (baselineQuery && (includeThisResourceInResponse(resource, interfaceQuery,
+ resourceTypeQuery))))
{
- for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
- {
- bool result = false;
- if (resource->resourceProperties & OC_EXPLICIT_DISCOVERABLE)
- {
- if (resourceTypeQuery && resourceMatchesRTFilter(resource, resourceTypeQuery))
- {
- result = true;
- }
- }
- if (resource->resourceProperties & OC_DISCOVERABLE)
- {
- result = true;
- }
-
- if (result)
- {
- discoveryResult = BuildVirtualResourceResponse(resource,
- discPayload, &request->devAddr, false);
- }
- }
+ discoveryResult = BuildVirtualResourceResponse(resource, discPayload,
+ &request->devAddr);
}
else
{
- if ((interfaceQuery && (0 != strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL))) ||
- !interfaceQuery)
- {
- 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 = OICStrdup(OC_RSRVD_RESOURCE_TYPE_RES);
- VERIFY_NON_NULL(discPayload->type, ERROR, OC_STACK_NO_MEMORY);
- OCResourcePayloadAddStringLL(&discPayload->interface, OC_RSRVD_INTERFACE_LL);
- OCResourcePayloadAddStringLL(&discPayload->interface, OC_RSRVD_INTERFACE_DEFAULT);
- VERIFY_NON_NULL(discPayload->interface, 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 = OC_STACK_OK;
}
}
- else
- {
- discoveryResult = OC_STACK_NO_MEMORY;
- }
}
- else
+ if (discPayload->resources == NULL)
{
- OIC_LOG_V(ERROR, TAG, "Error (%d) parsing query.", discoveryResult);
- }
- if (interfaceQueryAllocated)
- {
- 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)
+ 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;
+ OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
+ request->resourceUrl, request->method);
+ discoveryResult = OC_STACK_UNAUTHORIZED_REQ;
+ goto exit;
}
const char* deviceId = OCGetServerInstanceIDString();
- if (!deviceId)
- {
- discoveryResult = OC_STACK_ERROR;
- }
- else
- {
- payload = (OCPayload*) OCDevicePayloadCreate(deviceId, savedDeviceInfo.deviceName,
- savedDeviceInfo.types, OC_SPEC_VERSION, OC_DATA_MODEL_VERSION);
- if (!payload)
- {
- discoveryResult = OC_STACK_NO_MEMORY;
- }
- else
- {
- discoveryResult = OC_STACK_OK;
- }
- }
+ VERIFY_PARAM_NON_NULL(TAG, deviceId, "Failed retrieving device id.");
+ discoveryResult = OC_STACK_NO_MEMORY;
+ dataModelVersions = OCCreateString(savedDeviceInfo.dataModelVersions);
+ VERIFY_PARAM_NON_NULL(TAG, dataModelVersions, "Failed adding data model version.");
+ payload = (OCPayload*) OCDevicePayloadCreate(deviceId, savedDeviceInfo.deviceName,
+ savedDeviceInfo.types, savedDeviceInfo.specVersion, dataModelVersions);
+ VERIFY_PARAM_NON_NULL(TAG, payload, "Failed adding device payload.");
+ discoveryResult = OC_STACK_OK;
}
else if (virtualUriInRequest == OC_PLATFORM_URI)
{
- if (request->method == OC_REST_PUT || request->method == OC_REST_POST || request->method == OC_REST_DELETE)
+ 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;
+ OIC_LOG_V(ERROR, TAG, "Resource : %s not permitted for method: %d",
+ request->resourceUrl, request->method);
+ discoveryResult = OC_STACK_UNAUTHORIZED_REQ;
+ goto exit;
}
- payload = (OCPayload*)OCPlatformPayloadCreate(&savedPlatformInfo);
- if (!payload)
- {
- discoveryResult = OC_STACK_NO_MEMORY;
- }
- else
- {
- discoveryResult = OC_STACK_OK;
- }
- }
+ discoveryResult = OC_STACK_NO_MEMORY;
+ payload = (OCPayload *)OCPlatformPayloadCreate(&savedPlatformInfo);
+ VERIFY_PARAM_NON_NULL(TAG, payload, "Failed adding platform payload.");
+ discoveryResult = OC_STACK_OK;
+ }
#ifdef ROUTING_GATEWAY
else if (OC_GATEWAY_URI == virtualUriInRequest)
{
// Received request for a gateway
OIC_LOG(INFO, TAG, "Request is for Gateway Virtual Request");
discoveryResult = RMHandleGatewayRequest(request, resource);
-
}
#endif
-
+#ifdef TCP_ADAPTER
+ else if (OC_KEEPALIVE_RESOURCE_URI == virtualUriInRequest)
+ {
+ // Received request for a keepalive
+ OIC_LOG(INFO, TAG, "Request is for KeepAlive Request");
+ discoveryResult = HandleKeepAliveRequest(request, resource);
+ }
+#endif
/**
* Step 2: Send the discovery response
*
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
{
- if(discoveryResult == OC_STACK_OK)
- {
- SendNonPersistantDiscoveryResponse(request, resource, payload, OC_EH_OK);
- }
- else if(bMulticast == 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
+#if TCP_ADAPTER
+ // KeepAlive uses the HandleKeepAliveRequest to respond to the request.
+ if (OC_KEEPALIVE_RESOURCE_URI != virtualUriInRequest)
+#endif
{
- // Ignoring the discovery request as per RFC 7252, Section #8.2
- OIC_LOG(INFO, TAG, "Silently ignoring the request since device does not have \
- any useful data to send");
+ 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
+ {
+ // 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);
+ }
}
}
- OCPayloadDestroy(payload);
+exit:
+ if (interfaceQuery)
+ {
+ OICFree(interfaceQuery);
+ }
- return OC_STACK_OK;
+ if (resourceTypeQuery)
+ {
+ OICFree(resourceTypeQuery);
+ }
+ OCPayloadDestroy(payload);
+ if (dataModelVersions)
+ {
+ OICFree(dataModelVersions);
+ }
+ return discoveryResult;
}
static OCStackResult
request->numRcvdVendorSpecificHeaderOptions,
request->rcvdVendorSpecificHeaderOptions,
(OCObserveAction)request->observationOption,
- (OCObservationId)0);
+ (OCObservationId)0,
+ request->coapID);
VERIFY_SUCCESS(result, OC_STACK_OK);
// At this point we know for sure that defaultDeviceHandler exists
OCResource *resource,
uint8_t collectionResource)
{
+ OC_UNUSED(collectionResource);
+
if(!request || ! resource)
{
return OC_STACK_INVALID_PARAM;
}
- if (request && strcmp(request->resourceUrl, OC_RSRVD_RD_URI) == 0)
- {
- type = PAYLOAD_TYPE_RD;
- }
-
result = FormOCEntityHandlerRequest(&ehRequest,
(OCRequestHandle)request,
request->method,
request->numRcvdVendorSpecificHeaderOptions,
request->rcvdVendorSpecificHeaderOptions,
(OCObserveAction)request->observationOption,
- 0);
+ 0,
+ request->coapID);
VERIFY_SUCCESS(result, OC_STACK_OK);
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");
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
{
- result = OC_STACK_OK;
-
// The error in observeResult for the request will be used when responding to this
// request by omitting the observation option/sequence number.
request->observeResult = OC_STACK_ERROR;
OIC_LOG(ERROR, TAG, "Observer Addition failed");
ehFlag = OC_REQUEST_FLAG;
+ FindAndDeleteServerRequest(request);
+ goto exit;
}
}
- else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER &&
- !collectionResource)
+ else if(ehRequest.obsInfo.action == OC_OBSERVE_DEREGISTER)
{
OIC_LOG(INFO, TAG, "Deregistering observation requested");
{
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
{
- result = OC_STACK_OK;
request->observeResult = OC_STACK_ERROR;
OIC_LOG(ERROR, TAG, "Observer Removal failed");
+ FindAndDeleteServerRequest(request);
+ goto exit;
}
}
else
request->numRcvdVendorSpecificHeaderOptions,
request->rcvdVendorSpecificHeaderOptions,
(OCObserveAction)request->observationOption,
- (OCObservationId)0);
+ (OCObservationId)0,
+ request->coapID);
if(result == OC_STACK_OK)
{
result = DefaultCollectionEntityHandler (OC_REQUEST_FLAG, &ehRequest);
OICFree(savedDeviceInfo.deviceName);
OCFreeOCStringLL(savedDeviceInfo.types);
+ OICFree(savedDeviceInfo.specVersion);
+ OCFreeOCStringLL(savedDeviceInfo.dataModelVersions);
savedDeviceInfo.deviceName = NULL;
-
+ savedDeviceInfo.specVersion = NULL;
+ savedDeviceInfo.dataModelVersions = NULL;
}
static OCStackResult DeepCopyDeviceInfo(OCDeviceInfo info)
if (info.types)
{
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)
+ {
+ // Append the oic.wk.d at the start of rt link parameter value.
+ OCStringLL *dest = (OCStringLL*)OICCalloc (1, sizeof (OCStringLL));
+ if (!dest)
+ {
+ DeleteDeviceInfo();
+ return OC_STACK_NO_MEMORY;
+ }
+ dest->value = OICStrdup (OC_RSRVD_RESOURCE_TYPE_DEVICE);
+ if (!dest->value)
+ {
+ DeleteDeviceInfo();
+ return OC_STACK_NO_MEMORY;
+ }
+ dest->next = savedDeviceInfo.types;
+ savedDeviceInfo.types = dest;
+ }
if(!savedDeviceInfo.types && info.types)
{
DeleteDeviceInfo();
return OC_STACK_NO_MEMORY;
}
}
+
+ if (info.specVersion)
+ {
+ savedDeviceInfo.specVersion = OICStrdup(info.specVersion);
+ if(!savedDeviceInfo.specVersion && info.specVersion)
+ {
+ DeleteDeviceInfo();
+ return OC_STACK_NO_MEMORY;
+ }
+ }
+ else
+ {
+ savedDeviceInfo.specVersion = OICStrdup(OC_SPEC_VERSION);
+ if(!savedDeviceInfo.specVersion && OC_SPEC_VERSION)
+ {
+ DeleteDeviceInfo();
+ return OC_STACK_NO_MEMORY;
+ }
+ }
+
+ if (info.dataModelVersions)
+ {
+ savedDeviceInfo.dataModelVersions = CloneOCStringLL(info.dataModelVersions);
+ if(!savedDeviceInfo.dataModelVersions && info.dataModelVersions)
+ {
+ DeleteDeviceInfo();
+ return OC_STACK_NO_MEMORY;
+ }
+ }
+ 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;
+ }
+ }
+
return OC_STACK_OK;
}