[IOT-1413,IOT-1415] Fixed request handling bugs for /oic/ping resource
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocresource.c
index 44a2135..00ee331 100755 (executable)
 // 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 <string.h>
 #endif
-#ifdef WITH_STRINGS_H
+#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
-
 #ifdef ROUTING_GATEWAY
 #include "routingmanager.h"
 #endif
 
+#ifdef RD_SERVER
+#include "rd_database.h"
+#endif
+
 /// Module Name
 #define TAG "OIC_RI_RESOURCE"
 
@@ -76,8 +79,7 @@ static OCDeviceInfo savedDeviceInfo = {0};
  */
 static OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
                                                   OCDiscoveryPayload* payload,
-                                                  OCDevAddr *endpoint,
-                                                  bool rdResponse);
+                                                  OCDevAddr *endpoint);
 
 //-----------------------------------------------------------------------------
 // Default resource entity handler function
@@ -238,6 +240,14 @@ static OCVirtualResources GetTypeOfVirtualURI(const char *uriInRequest)
         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;
 }
 
@@ -324,7 +334,7 @@ OCStackResult BuildResponseRepresentation(const OCResource *resourcePtr,
 }
 
 OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
-                        OCDiscoveryPayload *payload, OCDevAddr *devAddr, bool rdResponse)
+                        OCDiscoveryPayload *payload, OCDevAddr *devAddr)
 {
     if (!resourcePtr || !payload)
     {
@@ -339,13 +349,8 @@ OCStackResult BuildVirtualResourceResponse(const OCResource *resourcePtr,
        }
     }
 
-    if (rdResponse)
-    {
-        securePort = devAddr->port;
-    }
-
-    uint16_t tcpPort = 0;
 #ifdef TCP_ADAPTER
+    uint16_t tcpPort = 0;
     if (GetTCPPortInfo(devAddr, &tcpPort) != OC_STACK_OK)
     {
         tcpPort = 0;
@@ -475,6 +480,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:
@@ -617,102 +624,6 @@ OCStackResult SendNonPersistantDiscoveryResponse(OCServerRequest *request, OCRes
     return OCDoResponse(&response);
 }
 
-#ifdef WITH_RD
-static OCStackResult checkResourceExistsAtRD(const char *interfaceType, const char *resourceType,
-     OCResource **payload, OCDevAddr *devAddr)
-{
-    OCResourceCollectionPayload *repPayload;
-    if (!payload)
-    {
-        return OC_STACK_ERROR;
-    }
-    if (OCRDCheckPublishedResource(interfaceType, resourceType, &repPayload, devAddr) == OC_STACK_OK)
-    {
-        if (!repPayload)
-        {
-            return OC_STACK_ERROR;
-        }
-        OCResource *ptr = ((OCResource *) OICCalloc(1, sizeof(OCResource)));
-        if (!ptr)
-        {
-           return OC_STACK_NO_MEMORY;
-        }
-
-        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;
-        }
-
-        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;
-        }
-
-        ptr->resourceProperties = (OCResourceProperty) repPayload->tags->bitmap;
-
-        OCFreeCollectionResource(repPayload);
-        *payload = ptr;
-        return OC_STACK_OK;
-    }
-    else
-    {
-        OIC_LOG_V(ERROR, TAG, "The resource type or interface type doe not exist \
-                             on the resource directory");
-    }
-    return OC_STACK_ERROR;
-}
-#endif
-
 static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource* resource)
 {
     if (!request || !resource)
@@ -759,14 +670,7 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
             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);
-                }
+                bool foundResourceAtRD = false;
 
                 if (!resourceTypeQuery && interfaceQuery && (0 == strcmp(interfaceQuery, OC_RSRVD_INTERFACE_LL)))
                 {
@@ -780,17 +684,20 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
 
                     for (; resource && discoveryResult == OC_STACK_OK; resource = resource->next)
                     {
-                        bool result = false;
-
-                        if (resource->resourceProperties & prop)
+                        foundResourceAtRD = false;
+#ifdef RD_SERVER
+                        if (strcmp(resource->uri, OC_RSRVD_RD_URI) == 0)
                         {
-                            result = true;
+                            if (OC_STACK_OK == OCRDDatabaseCheckResources(interfaceQuery, resourceTypeQuery, discPayload))
+                            {
+                                foundResourceAtRD = true;
+                                discoveryResult = OC_STACK_OK;
+                            }
                         }
-
-                        if (result)
+#endif
+                        if (!foundResourceAtRD && (resource->resourceProperties & prop))
                         {
-                            discoveryResult = BuildVirtualResourceResponse(resource,
-                            discPayload, &request->devAddr, false);
+                            discoveryResult = BuildVirtualResourceResponse(resource, discPayload, &request->devAddr);
                         }
                     }
                 }
@@ -813,49 +720,21 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
                         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
+#ifdef RD_SERVER
                         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; )
+                            if (OC_STACK_OK == OCRDDatabaseCheckResources(interfaceQuery, resourceTypeQuery, discPayload))
                             {
-                                rsrcNext = rsrcPtr->next;
-                                OICFree(rsrcPtr->name);
-                                OICFree(rsrcPtr);
-                                rsrcPtr = rsrcNext;
+                                foundResourceAtRD = true;
+                                discoveryResult = OC_STACK_OK;
                             }
-                            foundResourceAtRD = true;
                         }
 #endif
                         if (!foundResourceAtRD && includeThisResourceInResponse(resource, interfaceQuery, resourceTypeQuery))
                         {
-                            discoveryResult = BuildVirtualResourceResponse(resource,
-                                discPayload, &request->devAddr, false);
+                            discoveryResult = BuildVirtualResourceResponse(resource, discPayload, &request->devAddr);
                         }
                     }
                     // Set discoveryResult appropriately if no 'valid' resources are available
@@ -864,11 +743,23 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
                         discoveryResult = OC_STACK_NO_RESOURCE;
                     }
                 }
+                if (discoveryResult == OC_STACK_OK && foundResourceAtRD == false)
+                {
+                    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);
+                    }
+                }
             }
             else
             {
                 discoveryResult = OC_STACK_NO_MEMORY;
             }
+
         }
         else
         {
@@ -942,7 +833,14 @@ static OCStackResult HandleVirtualResource (OCServerRequest *request, OCResource
 
     }
 #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
      *
@@ -961,33 +859,53 @@ 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
     {
-        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
+#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 no useful data to send. ");
+            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);
+            }
         }
     }
 
@@ -1068,11 +986,6 @@ HandleResourceWithEntityHandler (OCServerRequest *request,
 
     }
 
-    if (request && strcmp(request->resourceUrl, OC_RSRVD_RD_URI) == 0)
-    {
-        type = PAYLOAD_TYPE_RD;
-    }
-
     result = FormOCEntityHandlerRequest(&ehRequest,
                                         (OCRequestHandle)request,
                                         request->method,
@@ -1131,6 +1044,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
@@ -1166,6 +1085,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
         {