[IOT-1671] Fixed base layer terminate logic
[platform/upstream/iotivity.git] / resource / csdk / stack / src / ocstack.c
index 8d8b420..66ac3bf 100644 (file)
@@ -544,11 +544,11 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat
     {
     case OC_OBSERVER_NOT_INTERESTED:
         OIC_LOG(DEBUG, TAG, "observer not interested in our notifications");
-        observer = GetObserverUsingToken (token, tokenLength);
-        if(observer)
+        observer = GetObserverUsingToken(token, tokenLength);
+        if (observer)
         {
             result = FormOCEntityHandlerRequest(&ehRequest,
-                                                (OCRequestHandle)NULL,
+                                                0,
                                                 OC_REST_NOMETHOD,
                                                 &observer->devAddr,
                                                 (OCResourceHandle)NULL,
@@ -557,16 +557,20 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat
                                                 OC_OBSERVE_DEREGISTER,
                                                 observer->observeId,
                                                 0);
-            if(result != OC_STACK_OK)
+            if (result != OC_STACK_OK)
             {
                 return result;
             }
-            observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest,
-                            observer->resource->entityHandlerCallbackParam);
+
+            if (observer->resource && observer->resource->entityHandler)
+            {
+                observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest,
+                                                  observer->resource->entityHandlerCallbackParam);
+            }
         }
 
-        result = DeleteObserverUsingToken (token, tokenLength);
-        if(result == OC_STACK_OK)
+        result = DeleteObserverUsingToken(token, tokenLength);
+        if (result == OC_STACK_OK)
         {
             OIC_LOG(DEBUG, TAG, "Removed observer successfully");
         }
@@ -579,8 +583,8 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat
 
     case OC_OBSERVER_STILL_INTERESTED:
         OIC_LOG(DEBUG, TAG, "observer still interested, reset the failedCount");
-        observer = GetObserverUsingToken (token, tokenLength);
-        if(observer)
+        observer = GetObserverUsingToken(token, tokenLength);
+        if (observer)
         {
             observer->forceHighQos = 0;
             observer->failedCommCount = 0;
@@ -595,12 +599,12 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat
     case OC_OBSERVER_FAILED_COMM:
         OIC_LOG(DEBUG, TAG, "observer is unreachable");
         observer = GetObserverUsingToken (token, tokenLength);
-        if(observer)
+        if (observer)
         {
-            if(observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
+            if (observer->failedCommCount >= MAX_OBSERVER_FAILED_COMM)
             {
                 result = FormOCEntityHandlerRequest(&ehRequest,
-                                                    (OCRequestHandle)NULL,
+                                                    0,
                                                     OC_REST_NOMETHOD,
                                                     &observer->devAddr,
                                                     (OCResourceHandle)NULL,
@@ -609,15 +613,19 @@ OCStackResult OCStackFeedBack(CAToken_t token, uint8_t tokenLength, uint8_t stat
                                                     OC_OBSERVE_DEREGISTER,
                                                     observer->observeId,
                                                     0);
-                if(result != OC_STACK_OK)
+                if (result != OC_STACK_OK)
                 {
                     return OC_STACK_ERROR;
                 }
-                observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest,
-                                    observer->resource->entityHandlerCallbackParam);
 
-                result = DeleteObserverUsingToken (token, tokenLength);
-                if(result == OC_STACK_OK)
+                if (observer->resource && observer->resource->entityHandler)
+                {
+                    observer->resource->entityHandler(OC_OBSERVE_FLAG, &ehRequest,
+                                        observer->resource->entityHandlerCallbackParam);
+                }
+
+                result = DeleteObserverUsingToken(token, tokenLength);
+                if (result == OC_STACK_OK)
                 {
                     OIC_LOG(DEBUG, TAG, "Removed observer successfully");
                 }
@@ -1295,12 +1303,13 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp
 #endif
                     else if (strcmp(cbNode->requestUri, OC_RSRVD_DEVICE_URI) == 0)
                     {
-                        type = PAYLOAD_TYPE_DEVICE;
+                        type = PAYLOAD_TYPE_REPRESENTATION;
                     }
                     else if (strcmp(cbNode->requestUri, OC_RSRVD_PLATFORM_URI) == 0)
                     {
-                        type = PAYLOAD_TYPE_PLATFORM;
+                        type = PAYLOAD_TYPE_REPRESENTATION;
                     }
+
 #ifdef ROUTING_GATEWAY
                     else if (strcmp(cbNode->requestUri, OC_RSRVD_GATEWAY_URI) == 0)
                     {
@@ -1309,10 +1318,10 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp
 #endif
                     else if (strcmp(cbNode->requestUri, OC_RSRVD_RD_URI) == 0)
                     {
-                        type = PAYLOAD_TYPE_REPRESENTATION ;
+                        type = PAYLOAD_TYPE_REPRESENTATION;
                     }
 #ifdef TCP_ADAPTER
-                    else if (strcmp(cbNode->requestUri, KEEPALIVE_RESOURCE_URI) == 0)
+                    else if (strcmp(cbNode->requestUri, OC_RSRVD_KEEPALIVE_URI) == 0)
                     {
                         type = PAYLOAD_TYPE_REPRESENTATION;
                     }
@@ -1333,13 +1342,13 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp
                 {
                     if (cbNode->requestUri)
                     {
-                        if (strcmp(OC_RSRVD_PLATFORM_URI, cbNode->requestUri) == 0)
+                        if (0 == strcmp(OC_RSRVD_PLATFORM_URI, cbNode->requestUri))
                         {
-                            type = PAYLOAD_TYPE_PLATFORM;
+                            type = PAYLOAD_TYPE_REPRESENTATION;
                         }
-                        else if (strcmp(OC_RSRVD_DEVICE_URI, cbNode->requestUri) == 0)
+                        else if (0 == strcmp(OC_RSRVD_DEVICE_URI, cbNode->requestUri))
                         {
-                            type = PAYLOAD_TYPE_DEVICE;
+                            type = PAYLOAD_TYPE_REPRESENTATION;
                         }
                         if (type == PAYLOAD_TYPE_INVALID)
                         {
@@ -1377,7 +1386,8 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp
             {
                 int start = 0;
                 //First option always with option ID is COAP_OPTION_OBSERVE if it is available.
-                if(responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
+                if(responseInfo->info.options
+                   && responseInfo->info.options[0].optionID == COAP_OPTION_OBSERVE)
                 {
                     size_t i;
                     uint32_t observationOption;
@@ -1407,8 +1417,11 @@ void OCHandleResponse(const CAEndpoint_t* endPoint, const CAResponseInfo_t* resp
 
                 for (uint8_t i = start; i < responseInfo->info.numOptions; i++)
                 {
-                    memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
-                            &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
+                    if(&(responseInfo->info.options[i]))
+                    {
+                        memcpy (&(response.rcvdVendorSpecificHeaderOptions[i-start]),
+                                &(responseInfo->info.options[i]), sizeof(OCHeaderOption));
+                    }
                 }
             }
 
@@ -1952,7 +1965,7 @@ void OCHandleRequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque
         return;
     }
     serverRequest.numRcvdVendorSpecificHeaderOptions = tempNum;
-    if (serverRequest.numRcvdVendorSpecificHeaderOptions)
+    if (serverRequest.numRcvdVendorSpecificHeaderOptions && requestInfo->info.options)
     {
         memcpy (&(serverRequest.rcvdVendorSpecificHeaderOptions), requestInfo->info.options,
             sizeof(CAHeaderOption_t)*tempNum);
@@ -2064,42 +2077,6 @@ void HandleCARequests(const CAEndpoint_t* endPoint, const CARequestInfo_t* reque
     OIC_LOG(INFO, TAG, "Exit HandleCARequests");
 }
 
-bool validatePlatformInfo(OCPlatformInfo info)
-{
-
-    if (!info.platformID)
-    {
-        OIC_LOG(ERROR, TAG, "No platform ID found.");
-        return false;
-    }
-
-    if (info.manufacturerName)
-    {
-        size_t lenManufacturerName = strlen(info.manufacturerName);
-
-        if(lenManufacturerName == 0 || lenManufacturerName > MAX_MANUFACTURER_NAME_LENGTH)
-        {
-            OIC_LOG(ERROR, TAG, "Manufacturer name fails length requirements.");
-            return false;
-        }
-    }
-    else
-    {
-        OIC_LOG(ERROR, TAG, "No manufacturer name present");
-        return false;
-    }
-
-    if (info.manufacturerUrl)
-    {
-        if(strlen(info.manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH)
-        {
-            OIC_LOG(ERROR, TAG, "Manufacturer url fails length requirements.");
-            return false;
-        }
-    }
-    return true;
-}
-
 //-----------------------------------------------------------------------------
 // Public APIs
 //-----------------------------------------------------------------------------
@@ -2269,9 +2246,9 @@ exit:
     if(result != OC_STACK_OK)
     {
         OIC_LOG(ERROR, TAG, "Stack initialization error");
+        TerminateScheduleResourceList();
         deleteAllResources();
         CATerminate();
-        TerminateScheduleResourceList();
         stackState = OC_STACK_UNINITIALIZED;
     }
     return result;
@@ -2294,6 +2271,9 @@ OCStackResult OCStop()
 
     stackState = OC_STACK_UNINIT_IN_PROGRESS;
 
+    CAUnregisterNetworkMonitorHandler(OCDefaultAdapterStateChangedHandler,
+                                      OCDefaultConnectionStateChangedHandler);
+
 #ifdef WITH_PRESENCE
     // Ensure that the TTL associated with ANY and ALL presence notifications originating from
     // here send with the code "OC_STACK_PRESENCE_STOPPED" result.
@@ -2311,22 +2291,20 @@ OCStackResult OCStop()
     TerminateKeepAlive(myStackMode);
 #endif
 
-    // Free memory dynamically allocated for resources
-    deleteAllResources();
-    DeleteDeviceInfo();
-    DeletePlatformInfo();
-    CATerminate();
     TerminateScheduleResourceList();
     // Remove all observers
     DeleteObserverList();
+    // Free memory dynamically allocated for resources
+    deleteAllResources();
     // Remove all the client callbacks
     DeleteClientCBList();
+    // Terminate connectivity-abstraction layer.
+    CATerminate();
 
     // De-init the SRM Policy Engine
     // TODO after BeachHead delivery: consolidate into single SRMDeInit()
     SRMDeInitPolicyEngine();
 
-
     stackState = OC_STACK_UNINITIALIZED;
     return OC_STACK_OK;
 }
@@ -3217,55 +3195,6 @@ OCStackResult OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandler entityHandle
     return OC_STACK_OK;
 }
 
-OCStackResult OCSetPlatformInfo(OCPlatformInfo platformInfo)
-{
-    OIC_LOG(INFO, TAG, "Entering OCSetPlatformInfo");
-
-    if(myStackMode ==  OC_SERVER || myStackMode == OC_CLIENT_SERVER || myStackMode == OC_GATEWAY)
-    {
-        if (validatePlatformInfo(platformInfo))
-        {
-            return SavePlatformInfo(platformInfo);
-        }
-        else
-        {
-            return OC_STACK_INVALID_PARAM;
-        }
-    }
-    else
-    {
-        return OC_STACK_ERROR;
-    }
-}
-
-OCStackResult OCSetDeviceInfo(OCDeviceInfo deviceInfo)
-{
-    OIC_LOG(INFO, TAG, "Entering OCSetDeviceInfo");
-
-    if (!deviceInfo.deviceName || deviceInfo.deviceName[0] == '\0')
-    {
-        OIC_LOG(ERROR, TAG, "Null or empty device name.");
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    if (deviceInfo.types)
-    {
-        OCStringLL *type =  deviceInfo.types;
-        OCResource *resource = findResource((OCResource *) deviceResource);
-        if (!resource)
-        {
-            return OC_STACK_INVALID_PARAM;
-        }
-
-        while (type)
-        {
-            OCBindResourceTypeToResource(deviceResource, type->value);
-            type = type->next;
-        }
-    }
-    return SaveDeviceInfo(deviceInfo);
-}
-
 OCStackResult OCCreateResource(OCResourceHandle *handle,
         const char *resourceTypeName,
         const char *resourceInterfaceName,
@@ -4116,7 +4045,7 @@ OCStackResult OCDoResponse(OCEntityHandlerResponse *ehResponse)
 
     // Normal response
     // Get pointer to request info
-    serverRequest = GetServerRequestUsingHandle((OCServerRequest *)ehResponse->requestHandle);
+    serverRequest = GetServerRequestUsingHandle(ehResponse->requestHandle);
     if(serverRequest)
     {
         // response handler in ocserverrequest.c. Usually HandleSingleResponse.
@@ -4414,6 +4343,7 @@ void deleteResourceElements(OCResource *resource)
     OICFree(resource->uri);
     deleteResourceType(resource->rsrcType);
     deleteResourceInterface(resource->rsrcInterface);
+    OCDeleteResourceAttributes(resource->rsrcAttributes);
 }
 
 void deleteResourceType(OCResourceType *resourceType)
@@ -4444,6 +4374,25 @@ void deleteResourceInterface(OCResourceInterface *resourceInterface)
     }
 }
 
+void OCDeleteResourceAttributes(OCAttribute *rsrcAttributes)
+{
+    OCAttribute *next = NULL;
+    for (OCAttribute *pointer = rsrcAttributes; pointer; pointer = next)
+    {
+        next = pointer->next;
+        if (pointer->attrName && 0 == strcmp(OC_RSRVD_DATA_MODEL_VERSION, pointer->attrName))
+        {
+            OCFreeOCStringLL((OCStringLL *)pointer->attrValue);
+        }
+        else
+        {
+            OICFree(pointer->attrValue);
+        }
+        OICFree(pointer->attrName);
+        OICFree(pointer);
+    }
+}
+
 void insertResourceType(OCResource *resource, OCResourceType *resourceType)
 {
     OCResourceType *pointer = NULL;
@@ -4722,13 +4671,13 @@ const char* OCGetServerInstanceIDString(void)
     static bool generated = false;
     static char sidStr[UUID_STRING_SIZE];
 
-    if(generated)
+    if (generated)
     {
         return sidStr;
     }
 
     const OicUuid_t *sid = OCGetServerInstanceID();
-    if(OCConvertUuidToString(sid->id, sidStr) != RAND_UUID_OK)
+    if (sid && OCConvertUuidToString(sid->id, sidStr) != RAND_UUID_OK)
     {
         OIC_LOG(FATAL, TAG, "Generate UUID String for Server Instance failed!");
         return NULL;
@@ -5104,6 +5053,21 @@ void OCDefaultConnectionStateChangedHandler(const CAEndpoint_t *info, bool isCon
     {
        g_connectionHandler(info, isConnected);
     }
+
+    /*
+     * If the client observes one or more resources over a reliable connection,
+     * then the CoAP server (or intermediary in the role of the CoAP server)
+     * MUST remove all entries associated with the client endpoint from the lists
+     * of observers when the connection is either closed or times out.
+     */
+    if (!isConnected)
+    {
+        OCDevAddr devAddr = { OC_DEFAULT_ADAPTER };
+        CopyEndpointToDevAddr(info, &devAddr);
+
+        // remove observer list with remote device address.
+        DeleteObserverUsingDevAddr(&devAddr);
+    }
 }
 
 void OCSetNetworkMonitorHandler(CAAdapterStateChangedCB adapterHandler,