[IOT-1413,IOT-1415] Fixed request handling bugs for /oic/ping resource
[platform/upstream/iotivity.git] / resource / csdk / stack / src / oickeepalive.c
index 6c5b07a..0e684d6 100644 (file)
@@ -44,15 +44,15 @@ static const uint64_t USECS_PER_SEC = 1000000;
 // Macros
 //-----------------------------------------------------------------------------
 #define VERIFY_SUCCESS(op, successCode) { if ((op) != (successCode)) \
-            {OC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
+            {OIC_LOG_V(FATAL, TAG, "%s failed!!", #op); goto exit;} }
 
-#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
+#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OIC_LOG((logLevel), \
              TAG, #arg " is NULL"); return (retVal); } }
 
-#define VERIFY_NON_NULL_NR(arg, logLevel) { if (!(arg)) { OC_LOG((logLevel), \
+#define VERIFY_NON_NULL_NR(arg, logLevel) { if (!(arg)) { OIC_LOG((logLevel), \
              TAG, #arg " is NULL"); return; } }
 
-#define VERIFY_NON_NULL_V(arg) { if (!arg) {OC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
+#define VERIFY_NON_NULL_V(arg) { if (!arg) {OIC_LOG_V(FATAL, TAG, "%s is NULL", #arg);\
     goto exit;} }
 
 /**
@@ -73,11 +73,21 @@ static const uint64_t USECS_PER_SEC = 1000000;
 #define KEEPALIVE_MAX_INTERVAL 64
 
 /**
+ * Default counts of interval value.
+ */
+#define DEFAULT_INTERVAL_COUNT  6
+
+/**
  * KeepAlive key to parser Payload Table.
  */
 static const char INTERVAL[] = "in";
 
 /**
+ * KeepAlive key to get interval values from Payload Table.
+ */
+static const char INTERVAL_ARRAY[] = "inarray";
+
+/**
  * To check if KeepAlive is initialized.
  */
 static bool g_isKeepAliveInitialized = false;
@@ -100,6 +110,9 @@ typedef struct
     OCMode mode;                    /**< host Mode of Operation. */
     CAEndpoint_t remoteAddr;        /**< destination Address. */
     uint32_t interval;              /**< time interval for KeepAlive. in seconds.*/
+    int32_t currIndex;              /**< current interval value index. */
+    size_t intervalSize;            /**< total interval counts. */
+    int64_t *intervalInfo;          /**< interval values for KeepAlive. */
     bool sentPingMsg;               /**< if oic client already sent ping message. */
     uint64_t timeStamp;             /**< last sent or received ping message. in microseconds. */
 } KeepAliveEntry_t;
@@ -115,6 +128,11 @@ static OCStackResult SendDisconnectMessage(const KeepAliveEntry_t *entry);
 static OCStackResult SendPingMessage(KeepAliveEntry_t *entry);
 
 /**
+ * Increase interval value to send next ping message.
+ */
+static void IncreaseInterval(KeepAliveEntry_t *entry);
+
+/**
  * Ping Message callback registered with RI for KeepAlive Request.
  */
 static OCStackApplicationResult PingRequestCallback(void* ctx, OCDoHandle handle,
@@ -134,31 +152,32 @@ static OCStackResult DeleteKeepAliveResource();
 
 /**
  * API to handle the GET request received for a KeepAlive resource.
- * @param[in]   endPoint        RemoteEndpoint which sent the packet.
- * @param[in]   requestInfo     Received coap packet.
+ * @param[in]   request     Request Received.
+ * @param[in]   resource    Resource handle used for sending the response.
  * @return  ::OC_STACK_OK or Appropriate error code.
  */
-static OCStackResult HandleKeepAliveGETRequest(const CAEndpoint_t* endPoint,
-                                        const CARequestInfo_t* requestInfo);
+static OCStackResult HandleKeepAliveGETRequest(OCServerRequest *request,
+                                               const OCResource *resource);
 
 /**
  * API to handle the PUT request received for a KeepAlive resource.
- * @param[in]   endPoint        RemoteEndpoint which sent the packet.
- * @param[in]   requestInfo     Received coap packet.
+ * @param[in]   request     Request Received.
+ * @param[in]   resource    Resource handle used for sending the response.
  * @return  ::OC_STACK_OK or Appropriate error code.
  */
-static OCStackResult HandleKeepAlivePUTRequest(const CAEndpoint_t* endPoint,
-                                        const CARequestInfo_t* requestInfo);
+static OCStackResult HandleKeepAlivePUTRequest(OCServerRequest *request,
+                                               const OCResource *resource);
 
 /**
  * API to handle the Response payload.
- * @param[in]   endpoint    RemoteEndpoint which sent the packet.
- * @param[in]   responseCode   Received reseponse code.
+ * @param[in]   endpoint        RemoteEndpoint which sent the packet.
+ * @param[in]   responseCode    Received reseponse code.
+ * @param[in]   respPayload     Response payload.
  * @return  ::OC_STACK_OK or Appropriate error code.
  */
-static OCStackResult HandleKeepAliveResponse(const CAEndpoint_t *endPoint,
-                                      OCStackResult responseCode);
-
+OCStackResult HandleKeepAliveResponse(const CAEndpoint_t *endPoint,
+                                      OCStackResult responseCode,
+                                      const OCRepPayload *respPayload);
 /**
  * Gets keepalive entry.
  * @param[in]   endpoint    Remote Endpoint information (like ipaddress,
@@ -174,9 +193,11 @@ static KeepAliveEntry_t *GetEntryFromEndpoint(const CAEndpoint_t *endpoint, uint
  * @param[in]   endpoint    Remote Endpoint information (like ipaddress,
  *                          port, reference uri and transport type).
  * @param[in]   mode        Whether it is OIC Server or OIC Client.
+ * @param[in]   intervalArray   Received interval values from cloud server.
  * @return  The KeepAlive entry added in KeepAlive Table.
  */
-static KeepAliveEntry_t *AddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode);
+KeepAliveEntry_t *AddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode,
+                                    int64_t *intervalArray);
 
 /**
  * Remove keepalive entry.
@@ -186,21 +207,24 @@ static KeepAliveEntry_t *AddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode
  */
 static OCStackResult RemoveKeepAliveEntry(const CAEndpoint_t *endpoint);
 
-OCStackResult InitializeKeepAlive()
+OCStackResult InitializeKeepAlive(OCMode mode)
 {
-    OC_LOG(DEBUG, TAG, "InitializeKeepAlive IN");
+    OIC_LOG(DEBUG, TAG, "InitializeKeepAlive IN");
     if (g_isKeepAliveInitialized)
     {
-        OC_LOG(DEBUG, TAG, "KeepAlive already initialized");
+        OIC_LOG(DEBUG, TAG, "KeepAlive already initialized");
         return OC_STACK_OK;
     }
 
-    // Create the KeepAlive Resource[/oic/ping].
-    OCStackResult result = CreateKeepAliveResource();
-    if (OC_STACK_OK != result)
+    if (OC_CLIENT != mode)
     {
-        OC_LOG_V(ERROR, TAG, "CreateKeepAliveResource failed[%d]", result);
-        return result;
+        // Create the KeepAlive Resource[/oic/ping].
+        OCStackResult result = CreateKeepAliveResource();
+        if (OC_STACK_OK != result)
+        {
+            OIC_LOG_V(ERROR, TAG, "CreateKeepAliveResource failed[%d]", result);
+            return result;
+        }
     }
 
     if (!g_keepAliveConnectionTable)
@@ -208,33 +232,36 @@ OCStackResult InitializeKeepAlive()
         g_keepAliveConnectionTable = u_arraylist_create();
         if (NULL == g_keepAliveConnectionTable)
         {
-            OC_LOG(ERROR, TAG, "Creating KeepAlive Table failed");
-            TerminateKeepAlive();
+            OIC_LOG(ERROR, TAG, "Creating KeepAlive Table failed");
+            TerminateKeepAlive(mode);
             return OC_STACK_ERROR;
         }
     }
 
     g_isKeepAliveInitialized = true;
 
-    OC_LOG(DEBUG, TAG, "InitializeKeepAlive OUT");
+    OIC_LOG(DEBUG, TAG, "InitializeKeepAlive OUT");
     return OC_STACK_OK;
 }
 
-OCStackResult TerminateKeepAlive()
+OCStackResult TerminateKeepAlive(OCMode mode)
 {
-    OC_LOG(DEBUG, TAG, "TerminateKeepAlive IN");
+    OIC_LOG(DEBUG, TAG, "TerminateKeepAlive IN");
     if (!g_isKeepAliveInitialized)
     {
-        OC_LOG(ERROR, TAG, "KeepAlive not initialized");
+        OIC_LOG(ERROR, TAG, "KeepAlive not initialized");
         return OC_STACK_ERROR;
     }
 
-    // Delete the KeepAlive Resource[/oic/ping].
-    OCStackResult result = DeleteKeepAliveResource();
-    if (OC_STACK_OK != result)
+    if (OC_CLIENT != mode)
     {
-        OC_LOG_V(ERROR, TAG, "DeleteKeepAliveResource failed[%d]", result);
-        return result;
+        // Delete the KeepAlive Resource[/oic/ping].
+        OCStackResult result = DeleteKeepAliveResource();
+        if (OC_STACK_OK != result)
+        {
+            OIC_LOG_V(ERROR, TAG, "DeleteKeepAliveResource failed[%d]", result);
+            return result;
+        }
     }
 
     if (NULL != g_keepAliveConnectionTable)
@@ -245,13 +272,13 @@ OCStackResult TerminateKeepAlive()
 
     g_isKeepAliveInitialized = false;
 
-    OC_LOG(DEBUG, TAG, "TerminateKeepAlive OUT");
+    OIC_LOG(DEBUG, TAG, "TerminateKeepAlive OUT");
     return OC_STACK_OK;
 }
 
 OCStackResult CreateKeepAliveResource()
 {
-    OC_LOG(DEBUG, TAG, "InitKeepAliveResource IN");
+    OIC_LOG(DEBUG, TAG, "InitKeepAliveResource IN");
 
     // Create a KeepAlive resource
     OCStackResult result = OCCreateResource(&g_keepAliveHandle,
@@ -264,153 +291,190 @@ OCStackResult CreateKeepAliveResource()
 
     if (OC_STACK_OK != result)
     {
-        OC_LOG_V(ERROR, TAG, "Create resource for KeepAlive failed[%d]", result);
+        OIC_LOG_V(ERROR, TAG, "Create resource for KeepAlive failed[%d]", result);
     }
 
-    OC_LOG(DEBUG, TAG, "InitKeepAliveResource OUT");
+    OIC_LOG(DEBUG, TAG, "InitKeepAliveResource OUT");
     return result;
 }
 
 OCStackResult DeleteKeepAliveResource()
 {
-    OC_LOG(DEBUG, TAG, "DeleteKeepAliveResource IN");
+    OIC_LOG(DEBUG, TAG, "DeleteKeepAliveResource IN");
 
     // Create a KeepAlive resource
     OCStackResult result = OCDeleteResource(g_keepAliveHandle);
 
     if (OC_STACK_OK != result)
     {
-        OC_LOG_V(ERROR, TAG, "Delete resource for KeepAlive failed[%d]", result);
+        OIC_LOG_V(ERROR, TAG, "Delete resource for KeepAlive failed[%d]", result);
     }
 
-    OC_LOG(DEBUG, TAG, "DeleteKeepAliveResource OUT");
+    OIC_LOG(DEBUG, TAG, "DeleteKeepAliveResource OUT");
     return result;
 }
 
-OCStackResult HandleKeepAliveRequest(const CAEndpoint_t* endPoint,
-                                     const CARequestInfo_t* requestInfo)
+OCStackResult HandleKeepAliveRequest(OCServerRequest *request,
+                                     const OCResource *resource)
 {
-    VERIFY_NON_NULL(endPoint, FATAL, OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(requestInfo, FATAL, OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(request, FATAL, OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(resource, FATAL, OC_STACK_INVALID_PARAM);
 
-    OC_LOG(DEBUG, TAG, "HandleKeepAliveRequest IN");
+    OIC_LOG(DEBUG, TAG, "HandleKeepAliveRequest IN");
 
-    OCStackResult result = OC_STACK_OK;
-    if (CA_PUT == requestInfo->method)
+    OCStackResult result = OC_STACK_ERROR;
+    if (OC_REST_GET == request->method)
     {
-        result = HandleKeepAlivePUTRequest(endPoint, requestInfo);
+        switch ((OCObserveAction)request->observationOption)
+        {
+            case OC_OBSERVE_NO_OPTION:
+                OIC_LOG(DEBUG, TAG, "Received GET request");
+                result = HandleKeepAliveGETRequest(request, resource);
+                break;
+            default:
+                OIC_LOG(DEBUG, TAG, "Not Supported by KeepAlive");
+                result = OC_STACK_UNAUTHORIZED_REQ;
+        }
     }
-    else if (CA_GET == requestInfo->method)
+    else if (OC_REST_PUT == request->method)
     {
-        result = HandleKeepAliveGETRequest(endPoint, requestInfo);
+        OIC_LOG(DEBUG, TAG, "Received PUT request");
+        result = HandleKeepAlivePUTRequest(request, resource);
+    }
+    else
+    {
+        OIC_LOG(DEBUG, TAG, "Not Supported by KeepAlive");
+        result = OC_STACK_UNAUTHORIZED_REQ;
     }
 
-    OC_LOG(DEBUG, TAG, "HandleKeepAliveRequest OUT");
-    return result;
+    // convert OCStackResult to CAResponseResult_t.
+    CAResponseResult_t caResult = OCToCAStackResult(result, request->method);
+    CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
+    CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
+
+    // Send response message.
+    SendDirectStackResponse(&endpoint, request->coapID, caResult,
+                           qualityOfServiceToMessageType(request->qos),
+                           request->numRcvdVendorSpecificHeaderOptions,
+                           request->rcvdVendorSpecificHeaderOptions,
+                           request->requestToken, request->tokenLength,
+                           request->resourceUrl, CA_RESPONSE_DATA);
+
+    OIC_LOG(DEBUG, TAG, "HandleKeepAliveRequest OUT");
+    return OC_STACK_OK;
 }
 
-OCStackResult HandleKeepAliveGETRequest(const CAEndpoint_t* endPoint,
-                                        const CARequestInfo_t* requestInfo)
+OCStackResult HandleKeepAliveGETRequest(OCServerRequest *request,
+                                        const OCResource *resource)
 {
-    VERIFY_NON_NULL(endPoint, FATAL, OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(requestInfo, FATAL, OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(request, FATAL, OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(resource, FATAL, OC_STACK_INVALID_PARAM);
 
-    OC_LOG_V(DEBUG, TAG, "Find Ping resource [%s]", requestInfo->info.resourceUri);
+    OIC_LOG_V(DEBUG, TAG, "Find Ping resource [%s]", request->resourceUrl);
 
-    CAResponseResult_t result = CA_VALID;
-    OCResource *resourcePtr = FindResourceByUri(requestInfo->info.resourceUri);
+    CAResponseResult_t result = CA_CONTENT;
+    OCResource *resourcePtr = FindResourceByUri(request->resourceUrl);
     if (!resourcePtr)
     {
         // Resource URL not specified
-        OC_LOG_V(DEBUG, TAG, "There is no Ping resource [%s]", requestInfo->info.resourceUri);
-        result = CA_NOT_FOUND;
+        OIC_LOG_V(DEBUG, TAG, "There is no Ping resource [%s]", request->resourceUrl);
+        return OC_STACK_NO_RESOURCE;
     }
 
-    SendDirectStackResponse(endPoint, requestInfo->info.messageId, result, requestInfo->info.type,
-                            requestInfo->info.numOptions, requestInfo->info.options,
-                            requestInfo->info.token, requestInfo->info.tokenLength,
-                            requestInfo->info.resourceUri);
-
     return OC_STACK_OK;
 }
 
-OCStackResult HandleKeepAlivePUTRequest(const CAEndpoint_t* endPoint,
-                                        const CARequestInfo_t* requestInfo)
+OCStackResult HandleKeepAlivePUTRequest(OCServerRequest *request,
+                                        const OCResource *resource)
 {
-    VERIFY_NON_NULL(endPoint, FATAL, OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(requestInfo, FATAL, OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(request, FATAL, OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(resource, FATAL, OC_STACK_INVALID_PARAM);
 
     // Get entry from KeepAlive table.
+    CAEndpoint_t endpoint = { .adapter = CA_DEFAULT_ADAPTER };
+    CopyDevAddrToEndpoint(&request->devAddr, &endpoint);
+
     uint32_t index = 0;
-    KeepAliveEntry_t *entry = GetEntryFromEndpoint(endPoint, &index);
+    KeepAliveEntry_t *entry = GetEntryFromEndpoint(&endpoint, &index);
     if (!entry)
     {
-        OC_LOG(ERROR, TAG, "Received the first keepalive message from client");
-        entry = AddKeepAliveEntry(endPoint, OC_SERVER);
+        OIC_LOG(ERROR, TAG, "Received the first keepalive message from client");
+        entry = AddKeepAliveEntry(&endpoint, OC_SERVER, NULL);
         if (!entry)
         {
-            OC_LOG(ERROR, TAG, "Failed to add new keepalive entry");
+            OIC_LOG(ERROR, TAG, "Failed to add new keepalive entry");
             return OC_STACK_ERROR;
         }
     }
 
     OCPayload *ocPayload = NULL;
     OCParsePayload(&ocPayload, PAYLOAD_TYPE_REPRESENTATION,
-                   requestInfo->info.payload, requestInfo->info.payloadSize);
+                   request->payload, request->payloadSize);
     OCRepPayload *repPayload = (OCRepPayload *)ocPayload;
 
-    uint32_t interval = 0;
+    int64_t interval = 0;
     OCRepPayloadGetPropInt(repPayload, INTERVAL, &interval);
     entry->interval = interval;
-    OC_LOG_V(DEBUG, TAG, "Received interval is [%d]", entry->interval);
+    OIC_LOG_V(DEBUG, TAG, "Received interval is [%d]", entry->interval);
     entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
 
-    // Send response message.
-    SendDirectStackResponse(endPoint, requestInfo->info.messageId, CA_VALID, requestInfo->info.type,
-                            requestInfo->info.numOptions, requestInfo->info.options,
-                            requestInfo->info.token, requestInfo->info.tokenLength,
-                            requestInfo->info.resourceUri);
+    OCPayloadDestroy(ocPayload);
 
     return OC_STACK_OK;
 }
 
 OCStackResult HandleKeepAliveResponse(const CAEndpoint_t *endPoint,
-                                      OCStackResult responseCode)
+                                      OCStackResult responseCode,
+                                      const OCRepPayload *respPayload)
 {
     VERIFY_NON_NULL(endPoint, FATAL, OC_STACK_INVALID_PARAM);
 
-    OC_LOG(DEBUG, TAG, "HandleKeepAliveResponse IN");
+    OIC_LOG(DEBUG, TAG, "HandleKeepAliveResponse IN");
 
     // Get entry from KeepAlive table.
     uint32_t index = 0;
     KeepAliveEntry_t *entry = GetEntryFromEndpoint(endPoint, &index);
     if (!entry)
     {
-        OC_LOG(ERROR, TAG, "There is no connection info in KeepAlive table");
+        // Receive response message about find /oic/ping request.
+        OIC_LOG(ERROR, TAG, "There is no connection info in KeepAlive table");
 
         if (OC_STACK_NO_RESOURCE == responseCode)
         {
-            OC_LOG(ERROR, TAG, "Server doesn't have a ping resource");
+            OIC_LOG(ERROR, TAG, "Server doesn't have a ping resource");
             return OC_STACK_ERROR;
         }
         else if (OC_STACK_OK == responseCode)
         {
-            entry = AddKeepAliveEntry(endPoint, OC_CLIENT);
+            int64_t *recvInterval = NULL;
+            size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
+            OCRepPayloadGetIntArray(respPayload, INTERVAL_ARRAY, &recvInterval, dimensions);
+            size_t serverIntervalSize = calcDimTotal(dimensions);
+
+            entry = AddKeepAliveEntry(endPoint, OC_CLIENT, recvInterval);
             if (!entry)
             {
-                OC_LOG(ERROR, TAG, "Failed to add new KeepAlive entry");
+                OIC_LOG(ERROR, TAG, "Failed to add new KeepAlive entry");
                 return OC_STACK_ERROR;
             }
 
+            if (serverIntervalSize)
+            {
+                // update interval size with received size of server.
+                entry->intervalSize = serverIntervalSize;
+            }
+
             // Send first ping message
             return SendPingMessage(entry);
         }
     }
+    else
+    {
+        // Set sentPingMsg values with false.
+        entry->sentPingMsg = false;
+    }
 
-    // Set sentPingMsg values with false.
-    entry->sentPingMsg = false;
-
-    OC_LOG(DEBUG, TAG, "HandleKeepAliveResponse OUT");
+    OIC_LOG(DEBUG, TAG, "HandleKeepAliveResponse OUT");
     return OC_STACK_OK;
 }
 
@@ -418,7 +482,7 @@ void ProcessKeepAlive()
 {
     if (!g_isKeepAliveInitialized)
     {
-        OC_LOG(ERROR, TAG, "KeepAlive not initialized");
+        OIC_LOG(ERROR, TAG, "KeepAlive not initialized");
         return;
     }
 
@@ -426,7 +490,8 @@ void ProcessKeepAlive()
 
     for (uint32_t i = 0; i < len; i++)
     {
-        KeepAliveEntry_t *entry = u_arraylist_get(g_keepAliveConnectionTable, i);
+        KeepAliveEntry_t *entry = (KeepAliveEntry_t *)u_arraylist_get(g_keepAliveConnectionTable,
+                                                                      i);
         if (NULL == entry)
         {
             continue;
@@ -444,7 +509,7 @@ void ProcessKeepAlive()
                  */
                 if ((KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC) <= currentTime - entry->timeStamp)
                 {
-                    OC_LOG(DEBUG, TAG, "Client does not receive the response within 1 minutes.");
+                    OIC_LOG(DEBUG, TAG, "Client does not receive the response within 1 minutes.");
 
                     // Send message to disconnect session.
                     SendDisconnectMessage(entry);
@@ -456,15 +521,12 @@ void ProcessKeepAlive()
                         <= currentTime - entry->timeStamp)
                 {
                     // Increase interval value.
-                    if (KEEPALIVE_MAX_INTERVAL > entry->interval)
-                    {
-                        entry->interval = entry->interval << 1;
-                    }
+                    IncreaseInterval(entry);
 
                     OCStackResult result = SendPingMessage(entry);
                     if (OC_STACK_OK != result)
                     {
-                        OC_LOG(ERROR, TAG, "Failed to send ping request");
+                        OIC_LOG(ERROR, TAG, "Failed to send ping request");
                         continue;
                     }
                 }
@@ -480,13 +542,26 @@ void ProcessKeepAlive()
             if ((entry->interval * KEEPALIVE_RESPONSE_TIMEOUT_SEC * USECS_PER_SEC)
                     <= currentTime - entry->timeStamp)
             {
-                OC_LOG(DEBUG, TAG, "Server does not receive a PUT request.");
+                OIC_LOG(DEBUG, TAG, "Server does not receive a PUT request.");
                 SendDisconnectMessage(entry);
             }
         }
     }
 }
 
+void IncreaseInterval(KeepAliveEntry_t *entry)
+{
+    VERIFY_NON_NULL_NR(entry, FATAL);
+
+    OIC_LOG_V(DEBUG, TAG, "Total interval counts: %zu", entry->intervalSize);
+    if (entry->intervalSize > (size_t)entry->currIndex + 1)
+    {
+        entry->currIndex++;
+        entry->interval = entry->intervalInfo[entry->currIndex];
+        OIC_LOG_V(DEBUG, TAG, "increase interval value [%d]", entry->interval);
+    }
+}
+
 OCStackResult SendDisconnectMessage(const KeepAliveEntry_t *entry)
 {
     VERIFY_NON_NULL(entry, FATAL, OC_STACK_INVALID_PARAM);
@@ -495,8 +570,16 @@ OCStackResult SendDisconnectMessage(const KeepAliveEntry_t *entry)
      * Send empty message to disconnect a connection.
      * If CA get the empty message from RI, CA will disconnect a connection.
      */
+
+    OCStackResult result = RemoveKeepAliveEntry(&entry->remoteAddr);
+    if (result != OC_STACK_OK)
+    {
+        return result;
+    }
+
     CARequestInfo_t requestInfo = { .method = CA_PUT };
-    return CASendRequest(&entry->remoteAddr, &requestInfo);
+    result = CASendRequest(&entry->remoteAddr, &requestInfo);
+    return CAResultToOCResult(result);
 }
 
 OCStackResult SendPingMessage(KeepAliveEntry_t *entry)
@@ -504,27 +587,33 @@ OCStackResult SendPingMessage(KeepAliveEntry_t *entry)
     VERIFY_NON_NULL(entry, FATAL, OC_STACK_INVALID_PARAM);
 
     // Send ping message.
-    OCCallbackData pingData = { .cb = PingRequestCallback };
+    OCCallbackData pingData = { .context = NULL, .cb = PingRequestCallback };
     OCDevAddr devAddr = { .adapter = OC_ADAPTER_TCP };
     CopyEndpointToDevAddr(&(entry->remoteAddr), &devAddr);
 
     OCRepPayload *payload = OCRepPayloadCreate();
     if (!payload)
     {
-        OC_LOG(ERROR, TAG, "Failed to allocate Payload");
+        OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
         return OC_STACK_ERROR;
     }
     payload->base.type = PAYLOAD_TYPE_REPRESENTATION;
     OCRepPayloadSetPropInt(payload, INTERVAL, entry->interval);
 
-    OCDoResource(NULL, OC_REST_PUT, KEEPALIVE_RESOURCE_URI, &devAddr,
-                 (OCPayload *) payload, CT_ADAPTER_TCP, OC_LOW_QOS, &pingData, NULL, 0);
+    OCStackResult result = OCDoResource(NULL, OC_REST_PUT, KEEPALIVE_RESOURCE_URI, &devAddr,
+                                        (OCPayload *) payload, CT_ADAPTER_TCP, OC_LOW_QOS,
+                                        &pingData, NULL, 0);
+    if (OC_STACK_OK != result)
+    {
+        OIC_LOG(ERROR, TAG, "OCDoResource has failed");
+        return result;
+    }
 
     // Update timeStamp with time sent ping message for next ping message.
     entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
     entry->sentPingMsg = true;
 
-    OC_LOG_V(DEBUG, TAG, "Client sent ping message, interval [%d]", entry->interval);
+    OIC_LOG_V(DEBUG, TAG, "Client sent ping message, interval [%d]", entry->interval);
 
     return OC_STACK_OK;
 }
@@ -532,29 +621,30 @@ OCStackResult SendPingMessage(KeepAliveEntry_t *entry)
 OCStackApplicationResult PingRequestCallback(void* ctx, OCDoHandle handle,
                                              OCClientResponse *clientResponse)
 {
-    OC_LOG(DEBUG, TAG, "PingRequestCallback IN");
+    OIC_LOG(DEBUG, TAG, "PingRequestCallback IN");
     (void) ctx;
     (void) handle;
     if (NULL == clientResponse)
     {
-        OC_LOG(ERROR, TAG, "clientResponse is NULL");
-        return OC_STACK_KEEP_TRANSACTION;
+        OIC_LOG(ERROR, TAG, "clientResponse is NULL");
+        return OC_STACK_DELETE_TRANSACTION;
     }
 
     CAEndpoint_t endpoint = { .adapter = CA_ADAPTER_TCP };
     CopyDevAddrToEndpoint(&(clientResponse->devAddr), &endpoint);
 
-    HandleKeepAliveResponse(&endpoint, clientResponse->result);
+    HandleKeepAliveResponse(&endpoint, clientResponse->result,
+                            (OCRepPayload *)clientResponse->payload);
 
-    OC_LOG(DEBUG, TAG, "PingRequestCallback OUT");
-    return OC_STACK_KEEP_TRANSACTION;
+    OIC_LOG(DEBUG, TAG, "PingRequestCallback OUT");
+    return OC_STACK_DELETE_TRANSACTION;
 }
 
 KeepAliveEntry_t *GetEntryFromEndpoint(const CAEndpoint_t *endpoint, uint32_t *index)
 {
     if (!g_keepAliveConnectionTable)
     {
-        OC_LOG(ERROR, TAG, "KeepAlive Table was not Created.");
+        OIC_LOG(ERROR, TAG, "KeepAlive Table was not Created.");
         return NULL;
     }
 
@@ -562,7 +652,8 @@ KeepAliveEntry_t *GetEntryFromEndpoint(const CAEndpoint_t *endpoint, uint32_t *i
 
     for (uint32_t i = 0; i < len; i++)
     {
-        KeepAliveEntry_t *entry = u_arraylist_get(g_keepAliveConnectionTable, i);
+        KeepAliveEntry_t *entry = (KeepAliveEntry_t *)u_arraylist_get(g_keepAliveConnectionTable,
+                                                                      i);
         if (NULL == entry)
         {
             continue;
@@ -571,7 +662,7 @@ KeepAliveEntry_t *GetEntryFromEndpoint(const CAEndpoint_t *endpoint, uint32_t *i
         if (!strncmp(entry->remoteAddr.addr, endpoint->addr, sizeof(entry->remoteAddr.addr))
                 && (entry->remoteAddr.port == endpoint->port))
         {
-            OC_LOG(DEBUG, TAG, "Connection Info found in KeepAlive table");
+            OIC_LOG(DEBUG, TAG, "Connection Info found in KeepAlive table");
             *index = i;
             return entry;
         }
@@ -580,40 +671,53 @@ KeepAliveEntry_t *GetEntryFromEndpoint(const CAEndpoint_t *endpoint, uint32_t *i
     return NULL;
 }
 
-KeepAliveEntry_t *AddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode)
+KeepAliveEntry_t *AddKeepAliveEntry(const CAEndpoint_t *endpoint, OCMode mode,
+                                    int64_t *intervalInfo)
 {
     if (!endpoint)
     {
-        OC_LOG(ERROR, TAG, "endpoint is NULL");
+        OIC_LOG(ERROR, TAG, "endpoint is NULL");
         return NULL;
     }
 
     if (!g_keepAliveConnectionTable)
     {
-        OC_LOG(ERROR, TAG, "KeepAlive Table was not Created.");
+        OIC_LOG(ERROR, TAG, "KeepAlive Table was not Created.");
         return NULL;
     }
 
     KeepAliveEntry_t *entry = (KeepAliveEntry_t *) OICCalloc(1, sizeof(KeepAliveEntry_t));
     if (NULL == entry)
     {
-        OC_LOG(ERROR, TAG, "Failed to Calloc KeepAlive Entry");
+        OIC_LOG(ERROR, TAG, "Failed to Calloc KeepAlive Entry");
         return NULL;
     }
 
     entry->mode = mode;
     entry->timeStamp = OICGetCurrentTime(TIME_IN_US);
-    entry->interval = KEEPALIVE_MIN_INTERVAL;
     entry->remoteAddr.adapter = endpoint->adapter;
     entry->remoteAddr.flags = endpoint->flags;
-    entry->remoteAddr.interface = endpoint->interface;
+    entry->remoteAddr.ifindex = endpoint->ifindex;
     entry->remoteAddr.port = endpoint->port;
     strncpy(entry->remoteAddr.addr, endpoint->addr, sizeof(entry->remoteAddr.addr));
 
+    entry->intervalSize = DEFAULT_INTERVAL_COUNT;
+    entry->intervalInfo = intervalInfo;
+    if (!entry->intervalInfo)
+    {
+        entry->intervalInfo = (int64_t*) OICMalloc(entry->intervalSize * sizeof(int64_t));
+        for (size_t i = 0; i < entry->intervalSize; i++)
+        {
+            entry->intervalInfo[i] = KEEPALIVE_MIN_INTERVAL << i;
+        }
+    }
+    entry->interval = entry->intervalInfo[0];
+
     bool result = u_arraylist_add(g_keepAliveConnectionTable, (void *)entry);
     if (!result)
     {
-        OC_LOG(ERROR, TAG, "Adding node to head failed");
+        OIC_LOG(ERROR, TAG, "Adding node to head failed");
+        OICFree(entry->intervalInfo);
         OICFree(entry);
         return NULL;
     }
@@ -629,50 +733,58 @@ OCStackResult RemoveKeepAliveEntry(const CAEndpoint_t *endpoint)
     KeepAliveEntry_t *entry = GetEntryFromEndpoint(endpoint, &index);
     if (!entry)
     {
-        OC_LOG(ERROR, TAG, "There is no entry in keepalive table.");
+        OIC_LOG(ERROR, TAG, "There is no entry in keepalive table.");
         return OC_STACK_ERROR;
     }
 
-    KeepAliveEntry_t *removedEntry = u_arraylist_remove(g_keepAliveConnectionTable, index);
+    KeepAliveEntry_t *removedEntry = (KeepAliveEntry_t *)
+                                        u_arraylist_remove(g_keepAliveConnectionTable, index);
     if (NULL == removedEntry)
     {
-        OC_LOG(ERROR, TAG, "Removed Entry is NULL");
+        OIC_LOG(ERROR, TAG, "Removed Entry is NULL");
         return OC_STACK_ERROR;
     }
 
-    OC_LOG_V(DEBUG, TAG, "Remove Connection Info from KeepAlive table, "
+    OIC_LOG_V(DEBUG, TAG, "Remove Connection Info from KeepAlive table, "
              "remote addr=%s port:%d", removedEntry->remoteAddr.addr,
              removedEntry->remoteAddr.port);
 
+    OICFree(entry->intervalInfo);
     OICFree(removedEntry);
 
     return OC_STACK_OK;
 }
 
-void HandleKeepAliveConnCB(const CAEndpoint_t *endpoint)
+void HandleKeepAliveConnCB(const CAEndpoint_t *endpoint, bool isConnected)
 {
     VERIFY_NON_NULL_NR(endpoint, FATAL);
 
-    OC_LOG(DEBUG, TAG, "Received the connected device information from CA");
-
-    // Send discover message to find ping resource
-    OCCallbackData pingData = { .cb = PingRequestCallback };
-    OCDevAddr devAddr = { .adapter = OC_ADAPTER_TCP };
-    CopyEndpointToDevAddr(endpoint, &devAddr);
-    return OCDoResource(NULL, OC_REST_DISCOVER, KEEPALIVE_RESOURCE_URI, &devAddr, NULL,
-                        OC_ADAPTER_TCP, OC_HIGH_QOS, &pingData, NULL, 0);
-}
-
-void HandleKeepAliveDisconnCB(const CAEndpoint_t *endpoint)
-{
-    VERIFY_NON_NULL_NR(endpoint, FATAL);
+    if (isConnected)
+    {
+        OIC_LOG(DEBUG, TAG, "Received the connected device information from CA");
 
-    OC_LOG(DEBUG, TAG, "Received the disconnected device information from CA");
+        // Send discover message to find ping resource
+        OCCallbackData pingData = {.context = NULL, .cb = PingRequestCallback };
+        OCDevAddr devAddr = { .adapter = OC_ADAPTER_TCP };
+        CopyEndpointToDevAddr(endpoint, &devAddr);
 
-    OCStackResult result = RemoveKeepAliveEntry(endpoint);
-    if(result != OC_STACK_OK)
+        OCStackResult result = OCDoResource(NULL, OC_REST_DISCOVER, KEEPALIVE_RESOURCE_URI,
+                                            &devAddr, NULL, CT_ADAPTER_TCP, OC_HIGH_QOS,
+                                            &pingData, NULL, 0);
+        if (OC_STACK_OK != result)
+        {
+            OIC_LOG(ERROR, TAG, "OCDoResource has failed");
+            return;
+        }
+    }
+    else
     {
-        OC_LOG(ERROR, TAG, "Failed to remove entry");
-        return;
+        OIC_LOG(DEBUG, TAG, "Received the disconnected device information from CA");
+
+        OCStackResult result = RemoveKeepAliveEntry(endpoint);
+        if(result != OC_STACK_OK)
+        {
+            return;
+        }
     }
 }