Merge tizen_5.0 codes into tizen_4.0
[platform/upstream/iotivity.git] / resource / src / InProcClientWrapper.cpp
index e077f01..75b7b46 100644 (file)
 #include "OCResource.h"
 #include "ocpayload.h"
 #include <OCSerialization.h>
+#include "logger.h"
+#ifdef TCP_ADAPTER
+#include "oickeepalive.h"
+#endif
+
+#define TAG "OIC_CLIENT_WRAPPER"
+
 using namespace std;
 
 namespace OC
@@ -36,6 +43,24 @@ namespace OC
     {
         // if the config type is server, we ought to never get called.  If the config type
         // is both, we count on the server to run the thread and do the initialize
+        start();
+    }
+
+    InProcClientWrapper::~InProcClientWrapper()
+    {
+        try
+        {
+            stop();
+        }
+        catch (InitializeException &e)
+        {
+            oclog() << "Exception in stop"<< e.what() << std::flush;
+        }
+    }
+
+    OCStackResult InProcClientWrapper::start()
+    {
+        OIC_LOG_V(INFO, TAG, "start ocplatform for client : %d", m_cfg.transportType);
 
         if (m_cfg.mode == ModeType::Client)
         {
@@ -43,32 +68,45 @@ namespace OC
                             static_cast<OCTransportFlags>(m_cfg.serverConnectivity & CT_MASK_FLAGS);
             OCTransportFlags clientFlags =
                             static_cast<OCTransportFlags>(m_cfg.clientConnectivity & CT_MASK_FLAGS);
-            OCStackResult result = OCInit1(OC_CLIENT, serverFlags, clientFlags);
+            OCStackResult result = OCInit2(OC_CLIENT, serverFlags, clientFlags,
+                                           m_cfg.transportType);
 
             if (OC_STACK_OK != result)
             {
                 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
             }
 
-            m_threadRun = true;
-            m_listeningThread = std::thread(&InProcClientWrapper::listeningFunc, this);
+            if (false == m_threadRun)
+            {
+                m_threadRun = true;
+                m_listeningThread = std::thread(&InProcClientWrapper::listeningFunc, this);
+            }
         }
+        return OC_STACK_OK;
     }
 
-    InProcClientWrapper::~InProcClientWrapper()
+    OCStackResult InProcClientWrapper::stop()
     {
+        OIC_LOG(INFO, TAG, "stop ocplatform");
+
         if (m_threadRun && m_listeningThread.joinable())
         {
             m_threadRun = false;
             m_listeningThread.join();
         }
 
-        // only stop if we are the ones who actually called 'init'.  We are counting
+        // only stop if we are the ones who actually called 'start'.  We are counting
         // on the server to do the stop.
         if (m_cfg.mode == ModeType::Client)
         {
-            OCStop();
+            OCStackResult result = OCStop();
+
+            if (OC_STACK_OK != result)
+            {
+               throw InitializeException(OC::InitException::STACK_TERMINATE_ERROR, result);
+            }
         }
+        return OC_STACK_OK;
     }
 
     void InProcClientWrapper::listeningFunc()
@@ -101,19 +139,15 @@ namespace OC
     {
         if (clientResponse->payload == nullptr ||
                 (
-                    clientResponse->payload->type != PAYLOAD_TYPE_DEVICE &&
-                    clientResponse->payload->type != PAYLOAD_TYPE_PLATFORM &&
                     clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION
                 )
           )
         {
-            //OCPayloadDestroy(clientResponse->payload);
             return OCRepresentation();
         }
 
         MessageContainer oc;
         oc.setPayload(clientResponse->payload);
-        //OCPayloadDestroy(clientResponse->payload);
 
         std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
         if (it == oc.representations().end())
@@ -122,21 +156,25 @@ namespace OC
         }
 
         // first one is considered the root, everything else is considered a child of this one.
-        OCRepresentation root = *it;
-        root.setDevAddr(clientResponse->devAddr);
-        root.setUri(clientResponse->resourceUri);
-        ++it;
+       OCRepresentation root = *it;
+       root.setDevAddr(clientResponse->devAddr);
+       root.setUri(clientResponse->resourceUri);
+       ++it;
 
         std::for_each(it, oc.representations().end(),
                 [&root](const OCRepresentation& repItr)
                 {root.addChild(repItr);});
         return root;
-
     }
 
     OCStackApplicationResult listenCallback(void* ctx, OCDoHandle /*handle*/,
         OCClientResponse* clientResponse)
     {
+        if (!ctx || !clientResponse)
+        {
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+
         ClientCallbackContext::ListenContext* context =
             static_cast<ClientCallbackContext::ListenContext*>(ctx);
 
@@ -197,18 +235,14 @@ namespace OC
 
         ClientCallbackContext::ListenErrorContext* context =
             static_cast<ClientCallbackContext::ListenErrorContext*>(ctx);
-        if (!context)
-        {
-            return OC_STACK_KEEP_TRANSACTION;
-        }
 
         OCStackResult result = clientResponse->result;
         if (result == OC_STACK_OK)
         {
             if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
             {
-                oclog() << "listenCallback(): clientResponse payload was null or the wrong type"
-                    << std::flush;
+                OIC_LOG_V(DEBUG, TAG, "%s: clientResponse payload was null or the wrong type",
+                          __func__);
                 return OC_STACK_KEEP_TRANSACTION;
             }
 
@@ -216,8 +250,8 @@ namespace OC
 
             if (!clientWrapper)
             {
-                oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
-                        << std::flush;
+                OIC_LOG_V(DEBUG, TAG, "%s: failed to get a shared_ptr to the client wrapper",
+                          __func__);
                 return OC_STACK_KEEP_TRANSACTION;
             }
 
@@ -232,10 +266,16 @@ namespace OC
             return OC_STACK_KEEP_TRANSACTION;
         }
 
-        std::string resourceURI = clientResponse->resourceUri;
+        OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
+        std::string resourceURI;
+        if(NULL != clientResponse->resourceUri)
+        {
+            resourceURI = clientResponse->resourceUri;
+        }
+
         std::thread exec(context->errorCallback, resourceURI, result);
         exec.detach();
-        return OC_STACK_DELETE_TRANSACTION;
+        return OC_STACK_KEEP_TRANSACTION;
     }
 
     OCStackResult InProcClientWrapper::ListenForResource(
@@ -327,6 +367,212 @@ namespace OC
         }
         return result;
     }
+
+    OCStackApplicationResult listenResListCallback(void* ctx, OCDoHandle /*handle*/,
+        OCClientResponse* clientResponse)
+    {
+        if (!ctx || !clientResponse)
+        {
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+
+        ClientCallbackContext::ListenResListContext* context =
+            static_cast<ClientCallbackContext::ListenResListContext*>(ctx);
+
+        if (clientResponse->result != OC_STACK_OK)
+        {
+            oclog() << "listenResListCallback(): failed to create resource. clientResponse: "
+                    << clientResponse->result
+                    << std::flush;
+
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+
+        if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
+        {
+            oclog() << "listenResListCallback(): clientResponse payload was null or the wrong type"
+                << std::flush;
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+
+        auto clientWrapper = context->clientWrapper.lock();
+
+        if (!clientWrapper)
+        {
+            oclog() << "listenResListCallback(): failed to get a shared_ptr to the client wrapper"
+                    << std::flush;
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+
+        try
+        {
+            ListenOCContainer container(clientWrapper, clientResponse->devAddr,
+                                    reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
+
+            OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
+            std::thread exec(context->callback, container.Resources());
+            exec.detach();
+        }
+        catch (std::exception &e)
+        {
+            oclog() << "Exception in listenResListCallback(), ignoring response: "
+                    << e.what() << std::flush;
+        }
+
+        return OC_STACK_KEEP_TRANSACTION;
+    }
+
+    OCStackResult InProcClientWrapper::ListenForResourceList(
+            const std::string& serviceUrl,
+            const std::string& resourceType,
+            OCConnectivityType connectivityType,
+            FindResListCallback& callback, QualityOfService QoS)
+    {
+        if (!callback)
+        {
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCStackResult result;
+        ostringstream resourceUri;
+        resourceUri << serviceUrl << resourceType;
+
+        ClientCallbackContext::ListenResListContext* context =
+            new ClientCallbackContext::ListenResListContext(callback, shared_from_this());
+        OCCallbackData cbdata;
+        cbdata.context = static_cast<void*>(context),
+        cbdata.cb      = listenResListCallback;
+        cbdata.cd      = [](void* c){delete (ClientCallbackContext::ListenResListContext*)c;};
+
+        auto cLock = m_csdkLock.lock();
+        if (cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCDoResource(nullptr, OC_REST_DISCOVER,
+                                  resourceUri.str().c_str(),
+                                  nullptr, nullptr, connectivityType,
+                                  static_cast<OCQualityOfService>(QoS),
+                                  &cbdata,
+                                  nullptr, 0);
+        }
+        else
+        {
+            delete context;
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+
+    OCStackApplicationResult listenResListWithErrorCallback(void* ctx, OCDoHandle /*handle*/,
+        OCClientResponse* clientResponse)
+    {
+        if (!ctx || !clientResponse)
+        {
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+
+        ClientCallbackContext::ListenResListWithErrorContext* context =
+                static_cast<ClientCallbackContext::ListenResListWithErrorContext*>(ctx);
+
+        OCStackResult result = clientResponse->result;
+        if (result != OC_STACK_OK)
+        {
+            oclog() << "listenResListWithErrorCallback(): failed to create resource. clientResponse: "
+                    << result << std::flush;
+
+            //send the error callback
+            std::string uri;
+            if(NULL != clientResponse->resourceUri)
+            {
+                uri = clientResponse->resourceUri;
+            }
+            std::thread exec(context->errorCallback, uri, result);
+            exec.detach();
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+
+        if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
+        {
+            oclog() << "listenResListWithErrorCallback(): clientResponse payload was null or the wrong type"
+                << std::flush;
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+
+        auto clientWrapper = context->clientWrapper.lock();
+
+        if (!clientWrapper)
+        {
+            oclog() << "listenResListWithErrorCallback(): failed to get a shared_ptr to the client wrapper"
+                    << std::flush;
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+
+        try
+        {
+            ListenOCContainer container(clientWrapper, clientResponse->devAddr,
+                            reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
+
+            OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
+            std::thread exec(context->callback, container.Resources());
+            exec.detach();
+        }
+        catch (std::exception &e)
+        {
+            oclog() << "Exception in listenResListWithErrorCallback(), ignoring response: "
+            << e.what() << std::flush;
+        }
+
+        return OC_STACK_KEEP_TRANSACTION;
+    }
+
+    OCStackResult InProcClientWrapper::ListenForResourceListWithError(
+            const std::string& serviceUrl,
+            const std::string& resourceType,
+            OCConnectivityType connectivityType,
+            FindResListCallback& callback,
+            FindErrorCallback& errorCallback, QualityOfService QoS)
+    {
+        if (!callback)
+        {
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCStackResult result;
+        ostringstream resourceUri;
+        resourceUri << serviceUrl << resourceType;
+
+        ClientCallbackContext::ListenResListWithErrorContext* context =
+            new ClientCallbackContext::ListenResListWithErrorContext(callback, errorCallback,
+                                                          shared_from_this());
+        if (!context)
+        {
+            return OC_STACK_ERROR;
+        }
+
+        OCCallbackData cbdata;
+        cbdata.context = static_cast<void*>(context),
+        cbdata.cb      = listenResListWithErrorCallback;
+        cbdata.cd      = [](void* c){delete (ClientCallbackContext::ListenResListWithErrorContext*)c;};
+
+        auto cLock = m_csdkLock.lock();
+        if (cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCDoResource(nullptr, OC_REST_DISCOVER,
+                                  resourceUri.str().c_str(),
+                                  nullptr, nullptr, connectivityType,
+                                  static_cast<OCQualityOfService>(QoS),
+                                  &cbdata,
+                                  nullptr, 0);
+        }
+        else
+        {
+            delete context;
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+
 #ifdef WITH_MQ
     OCStackApplicationResult listenMQCallback(void* ctx, OCDoHandle /*handle*/,
                                               OCClientResponse* clientResponse)
@@ -339,6 +585,12 @@ namespace OC
             return OC_STACK_DELETE_TRANSACTION;
         }
 
+        std::string resourceURI;
+        if(NULL != clientResponse->resourceUri)
+        {
+            resourceURI  = clientResponse->resourceUri;
+        }
+
         if (clientResponse->result != OC_STACK_OK)
         {
             oclog() << "listenMQCallback(): failed to create resource. clientResponse: "
@@ -346,7 +598,7 @@ namespace OC
                     << std::flush;
 
             std::thread exec(context->callback, clientResponse->result,
-                             std::string(clientResponse->resourceUri), nullptr);
+                             resourceURI, nullptr);
             exec.detach();
 
             return OC_STACK_DELETE_TRANSACTION;
@@ -369,7 +621,7 @@ namespace OC
             for (auto resource : container.Resources())
             {
                 std::thread exec(context->callback, clientResponse->result,
-                                 std::string(clientResponse->resourceUri), resource);
+                                 resourceURI, resource);
                 exec.detach();
             }
         }
@@ -396,6 +648,12 @@ namespace OC
             return OC_STACK_INVALID_PARAM;
         }
 
+        if (headerOptions.size() > MAX_HEADER_OPTIONS)
+        {
+            oclog() << "ListenForMQTopic: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
+            return OC_STACK_INVALID_PARAM;
+        }
+
         ClientCallbackContext::MQTopicContext* context =
             new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
         OCCallbackData cbdata;
@@ -410,7 +668,7 @@ namespace OC
         if (cLock)
         {
             std::lock_guard<std::recursive_mutex> lock(*cLock);
-            OCHeaderOption options[MAX_HEADER_OPTIONS];
+            OCHeaderOption *options = assembleHeaderOptions(headerOptions);
             result = OCDoResource(
                                   nullptr, OC_REST_GET,
                                   uri.c_str(),
@@ -418,8 +676,9 @@ namespace OC
                                   CT_DEFAULT,
                                   static_cast<OCQualityOfService>(QoS),
                                   &cbdata,
-                                  assembleHeaderOptions(options, headerOptions),
+                                  options,
                                   headerOptions.size());
+            delete[] options;
         }
         else
         {
@@ -439,6 +698,7 @@ namespace OC
 
         try
         {
+            OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
             OCRepresentation rep = parseGetSetCallback(clientResponse);
             std::thread exec(context->callback, rep);
             exec.detach();
@@ -555,7 +815,7 @@ namespace OC
             }
         }
 
-        if (!isLocationOption)
+        if (!isLocationOption && NULL != clientResponse->resourceUri)
         {
             createdUri = std::string(clientResponse->resourceUri);
         }
@@ -586,6 +846,7 @@ namespace OC
             }
             else
             {
+                OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
                 std::thread exec(context->callback, result,
                                  createdUri,
                                  nullptr);
@@ -611,6 +872,13 @@ namespace OC
         {
             return OC_STACK_INVALID_PARAM;
         }
+
+        if (headerOptions.size() > MAX_HEADER_OPTIONS)
+        {
+            oclog() << "PutMQTopicRepresentation: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
+            return OC_STACK_INVALID_PARAM;
+        }
+
         OCStackResult result;
         ClientCallbackContext::MQTopicContext* ctx =
                 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
@@ -626,7 +894,7 @@ namespace OC
         if (cLock)
         {
             std::lock_guard<std::recursive_mutex> lock(*cLock);
-            OCHeaderOption options[MAX_HEADER_OPTIONS];
+            OCHeaderOption *options = assembleHeaderOptions(headerOptions);
 
             result = OCDoResource(nullptr, OC_REST_PUT,
                                   url.c_str(), &devAddr,
@@ -634,8 +902,9 @@ namespace OC
                                   CT_DEFAULT,
                                   static_cast<OCQualityOfService>(QoS),
                                   &cbdata,
-                                  assembleHeaderOptions(options, headerOptions),
+                                  options,
                                   headerOptions.size());
+             delete[] options;
         }
         else
         {
@@ -652,23 +921,21 @@ namespace OC
     {
         ClientCallbackContext::GetContext* context =
             static_cast<ClientCallbackContext::GetContext*>(ctx);
-
         OCRepresentation rep;
         HeaderOptions serverHeaderOptions;
         OCStackResult result = clientResponse->result;
-        if (result == OC_STACK_OK)
+
+        parseServerHeaderOptions(clientResponse, serverHeaderOptions);
+        try
         {
-            parseServerHeaderOptions(clientResponse, serverHeaderOptions);
-            try
-            {
-                rep = parseGetSetCallback(clientResponse);
-            }
-            catch(OC::OCException& e)
-            {
-                result = e.code();
-            }
+            rep = parseGetSetCallback(clientResponse);
+        }
+        catch(OC::OCException& e)
+        {
+            result = e.code();
         }
 
+        OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
         std::thread exec(context->callback, serverHeaderOptions, rep, result);
         exec.detach();
         return OC_STACK_DELETE_TRANSACTION;
@@ -685,15 +952,22 @@ namespace OC
         {
             return OC_STACK_INVALID_PARAM;
         }
+
+        if (headerOptions.size() > MAX_HEADER_OPTIONS)
+        {
+            oclog() << "GetResourceRepresentation: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
+            return OC_STACK_INVALID_PARAM;
+        }
+
         OCStackResult result;
         ClientCallbackContext::GetContext* ctx =
             new ClientCallbackContext::GetContext(callback);
+
         OCCallbackData cbdata;
-        cbdata.context = static_cast<void*>(ctx),
+        cbdata.context = static_cast<void*>(ctx);
         cbdata.cb      = getResourceCallback;
         cbdata.cd      = [](void* c){delete (ClientCallbackContext::GetContext*)c;};
 
-
         std::string uri = assembleSetResourceUri(resourceUri, queryParams);
 
         auto cLock = m_csdkLock.lock();
@@ -701,7 +975,7 @@ namespace OC
         if (cLock)
         {
             std::lock_guard<std::recursive_mutex> lock(*cLock);
-            OCHeaderOption options[MAX_HEADER_OPTIONS];
+            OCHeaderOption *options = assembleHeaderOptions(headerOptions);
 
             result = OCDoResource(
                                   nullptr, OC_REST_GET,
@@ -710,8 +984,9 @@ namespace OC
                                   connectivityType,
                                   static_cast<OCQualityOfService>(QoS),
                                   &cbdata,
-                                  assembleHeaderOptions(options, headerOptions),
+                                  options,
                                   headerOptions.size());
+            delete[] options;
         }
         else
         {
@@ -732,22 +1007,18 @@ namespace OC
         HeaderOptions serverHeaderOptions;
 
         OCStackResult result = clientResponse->result;
-        if (OC_STACK_OK               == result ||
-            OC_STACK_RESOURCE_CREATED == result ||
-            OC_STACK_RESOURCE_DELETED == result ||
-            OC_STACK_RESOURCE_CHANGED == result)
+
+        parseServerHeaderOptions(clientResponse, serverHeaderOptions);
+        try
         {
-            parseServerHeaderOptions(clientResponse, serverHeaderOptions);
-            try
-            {
-                attrs = parseGetSetCallback(clientResponse);
-            }
-            catch(OC::OCException& e)
-            {
-                result = e.code();
-            }
+            attrs = parseGetSetCallback(clientResponse);
+        }
+        catch(OC::OCException& e)
+        {
+            result = e.code();
         }
 
+        OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
         std::thread exec(context->callback, serverHeaderOptions, attrs, result);
         exec.detach();
         return OC_STACK_DELETE_TRANSACTION;
@@ -856,6 +1127,13 @@ namespace OC
         {
             return OC_STACK_INVALID_PARAM;
         }
+
+        if (headerOptions.size() > MAX_HEADER_OPTIONS)
+        {
+            oclog() << "PostResourceRepresentation: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
+            return OC_STACK_INVALID_PARAM;
+        }
+
         OCStackResult result;
         ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
         OCCallbackData cbdata;
@@ -871,7 +1149,7 @@ namespace OC
         if (cLock)
         {
             std::lock_guard<std::recursive_mutex> lock(*cLock);
-            OCHeaderOption options[MAX_HEADER_OPTIONS];
+            OCHeaderOption *options = assembleHeaderOptions(headerOptions);
 
             result = OCDoResource(nullptr, OC_REST_POST,
                                   url.c_str(), &devAddr,
@@ -879,8 +1157,9 @@ namespace OC
                                   connectivityType,
                                   static_cast<OCQualityOfService>(QoS),
                                   &cbdata,
-                                  assembleHeaderOptions(options, headerOptions),
+                                  options,
                                   headerOptions.size());
+            delete[] options;
         }
         else
         {
@@ -902,6 +1181,13 @@ namespace OC
         {
             return OC_STACK_INVALID_PARAM;
         }
+
+        if (headerOptions.size() > MAX_HEADER_OPTIONS)
+        {
+            oclog() << "PutResourceRepresentation: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
+            return OC_STACK_INVALID_PARAM;
+        }
+
         OCStackResult result;
         ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
         OCCallbackData cbdata;
@@ -918,7 +1204,7 @@ namespace OC
         {
             std::lock_guard<std::recursive_mutex> lock(*cLock);
             OCDoHandle handle;
-            OCHeaderOption options[MAX_HEADER_OPTIONS];
+            OCHeaderOption *options = assembleHeaderOptions(headerOptions);
 
             result = OCDoResource(&handle, OC_REST_PUT,
                                   url.c_str(), &devAddr,
@@ -926,8 +1212,9 @@ namespace OC
                                   CT_DEFAULT,
                                   static_cast<OCQualityOfService>(QoS),
                                   &cbdata,
-                                  assembleHeaderOptions(options, headerOptions),
+                                  options,
                                   headerOptions.size());
+            delete[] options;
         }
         else
         {
@@ -946,10 +1233,9 @@ namespace OC
             static_cast<ClientCallbackContext::DeleteContext*>(ctx);
         HeaderOptions serverHeaderOptions;
 
-        if (clientResponse->result == OC_STACK_OK)
-        {
-            parseServerHeaderOptions(clientResponse, serverHeaderOptions);
-        }
+        parseServerHeaderOptions(clientResponse, serverHeaderOptions);
+
+        OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
         std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
         exec.detach();
         return OC_STACK_DELETE_TRANSACTION;
@@ -967,6 +1253,13 @@ namespace OC
         {
             return OC_STACK_INVALID_PARAM;
         }
+
+        if (headerOptions.size() > MAX_HEADER_OPTIONS)
+        {
+            oclog() << "DeleteResource: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
+            return OC_STACK_INVALID_PARAM;
+        }
+
         OCStackResult result;
         ClientCallbackContext::DeleteContext* ctx =
             new ClientCallbackContext::DeleteContext(callback);
@@ -980,7 +1273,7 @@ namespace OC
 
         if (cLock)
         {
-            OCHeaderOption options[MAX_HEADER_OPTIONS];
+            OCHeaderOption *options = assembleHeaderOptions(headerOptions);
 
             std::lock_guard<std::recursive_mutex> lock(*cLock);
 
@@ -990,8 +1283,9 @@ namespace OC
                                   connectivityType,
                                   static_cast<OCQualityOfService>(m_cfg.QoS),
                                   &cbdata,
-                                  assembleHeaderOptions(options, headerOptions),
+                                  options,
                                   headerOptions.size());
+            delete[] options;
         }
         else
         {
@@ -1012,21 +1306,25 @@ namespace OC
         HeaderOptions serverHeaderOptions;
         uint32_t sequenceNumber = clientResponse->sequenceNumber;
         OCStackResult result = clientResponse->result;
-        if (clientResponse->result == OC_STACK_OK)
+
+        parseServerHeaderOptions(clientResponse, serverHeaderOptions);
+        try
         {
-            parseServerHeaderOptions(clientResponse, serverHeaderOptions);
-            try
-            {
-                attrs = parseGetSetCallback(clientResponse);
-            }
-            catch(OC::OCException& e)
-            {
-                result = e.code();
-            }
+            attrs = parseGetSetCallback(clientResponse);
         }
+        catch(OC::OCException& e)
+        {
+            result = e.code();
+        }
+
+        OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
         std::thread exec(context->callback, serverHeaderOptions, attrs,
                     result, sequenceNumber);
         exec.detach();
+        if (sequenceNumber == MAX_SEQUENCE_NUMBER + 1)
+        {
+            return OC_STACK_DELETE_TRANSACTION;
+        }
 
         return OC_STACK_KEEP_TRANSACTION;
     }
@@ -1041,6 +1339,13 @@ namespace OC
         {
             return OC_STACK_INVALID_PARAM;
         }
+
+        if (headerOptions.size() > MAX_HEADER_OPTIONS)
+        {
+            oclog() << "ObserveResource: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
+            return OC_STACK_INVALID_PARAM;
+        }
+
         OCStackResult result;
 
         ClientCallbackContext::ObserveContext* ctx =
@@ -1072,7 +1377,7 @@ namespace OC
         if (cLock)
         {
             std::lock_guard<std::recursive_mutex> lock(*cLock);
-            OCHeaderOption options[MAX_HEADER_OPTIONS];
+            OCHeaderOption *options = assembleHeaderOptions(headerOptions);
 
             result = OCDoResource(handle, method,
                                   url.c_str(), &devAddr,
@@ -1080,8 +1385,9 @@ namespace OC
                                   CT_DEFAULT,
                                   static_cast<OCQualityOfService>(QoS),
                                   &cbdata,
-                                  assembleHeaderOptions(options, headerOptions),
+                                  options,
                                   headerOptions.size());
+            delete[] options;
         }
         else
         {
@@ -1099,18 +1405,25 @@ namespace OC
             const HeaderOptions& headerOptions,
             QualityOfService QoS)
     {
+        if (headerOptions.size() > MAX_HEADER_OPTIONS)
+        {
+            oclog() << "CancelObserveResource: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
+            return OC_STACK_INVALID_PARAM;
+        }
+
         OCStackResult result;
         auto cLock = m_csdkLock.lock();
 
         if (cLock)
         {
             std::lock_guard<std::recursive_mutex> lock(*cLock);
-            OCHeaderOption options[MAX_HEADER_OPTIONS];
+            OCHeaderOption *options = assembleHeaderOptions(headerOptions);
 
             result = OCCancel(handle,
                     static_cast<OCQualityOfService>(QoS),
-                    assembleHeaderOptions(options, headerOptions),
+                    options,
                     headerOptions.size());
+            delete[] options;
         }
         else
         {
@@ -1120,6 +1433,7 @@ namespace OC
         return result;
     }
 
+#ifdef WITH_PRESENCE
     OCStackApplicationResult subscribePresenceCallback(void* ctx,
                                                        OCDoHandle /*handle*/,
             OCClientResponse* clientResponse)
@@ -1132,6 +1446,7 @@ namespace OC
          */
         std::string url = clientResponse->devAddr.addr;
 
+        OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
         std::thread exec(context->callback, clientResponse->result,
                     clientResponse->sequenceNumber, url);
 
@@ -1139,11 +1454,13 @@ namespace OC
 
         return OC_STACK_KEEP_TRANSACTION;
     }
+#endif
 
     OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
         const std::string& host, const std::string& resourceType,
         OCConnectivityType connectivityType, SubscribeCallback& presenceHandler)
     {
+#ifdef WITH_PRESENCE
         if (!presenceHandler)
         {
             return OC_STACK_INVALID_PARAM;
@@ -1177,10 +1494,14 @@ namespace OC
                             os.str().c_str(), nullptr,
                             nullptr, connectivityType,
                             OC_LOW_QOS, &cbdata, NULL, 0);
+#else
+        return OC_STACK_NOT_IMPLEMENTED;
+#endif
     }
 
     OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
     {
+#ifdef WITH_PRESENCE
         OCStackResult result;
         auto cLock = m_csdkLock.lock();
 
@@ -1195,6 +1516,9 @@ namespace OC
         }
 
         return result;
+#else
+        return OC_STACK_NOT_IMPLEMENTED;
+#endif
     }
 
 #ifdef WITH_CLOUD
@@ -1250,24 +1574,26 @@ namespace OC
         return OC_STACK_OK;
     }
 
-    OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[],
-           const HeaderOptions& headerOptions)
+    OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(const HeaderOptions& headerOptions)
     {
-        int i = 0;
-
         if ( headerOptions.size() == 0)
         {
             return nullptr;
         }
 
+        OCHeaderOption* options = new OCHeaderOption[headerOptions.size()]();
+
+        size_t numOptions = 0;
         for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
         {
-            options[i] = OCHeaderOption();
-            options[i].protocolID = OC_COAP_ID;
-            options[i].optionID = it->getOptionID();
-            options[i].optionLength = it->getOptionData().length() + 1;
-            strcpy((char*)options[i].optionData, (it->getOptionData().c_str()));
-            i++;
+            OCStackResult ret = OCSetHeaderOption(options, &numOptions, it->getOptionID(),
+                                    it->getOptionData().c_str(), it->getOptionData().length());
+            if (OC_STACK_OK != ret)
+            {
+                OIC_LOG_V(ERROR, TAG, "Failed to convert vnd header options! (error=%d)", ret);
+                delete[] options;
+                return nullptr;
+            }
         }
 
         return options;
@@ -1321,6 +1647,7 @@ namespace OC
                     << std::flush;
             }
             else {
+                OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
                 convert(list, dpDeviceList);
                 std::thread exec(callback, dpDeviceList);
                 exec.detach();
@@ -1356,10 +1683,10 @@ namespace OC
             if (NULL == list)
             {
                 result = OC_STACK_NO_RESOURCE;
-                oclog() << "findDirectPairingDevices(): No device found for direct pairing"
-                    << std::flush;
+                OIC_LOG_V(DEBUG, TAG, "%s: No device found for direct pairing", __func__);
             }
             else {
+                OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
                 convert(list, dpDeviceList);
                 std::thread exec(callback, dpDeviceList);
                 exec.detach();
@@ -1381,6 +1708,7 @@ namespace OC
         ClientCallbackContext::DirectPairingContext* context =
             static_cast<ClientCallbackContext::DirectPairingContext*>(ctx);
 
+        OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
         std::thread exec(context->callback, cloneDevice(peer), result);
         exec.detach();
     }
@@ -1412,4 +1740,96 @@ namespace OC
         }
         return result;
     }
+#ifdef TCP_ADAPTER
+    OCStackApplicationResult KeepAliveRespCallback(void* ctx,
+                                                 OCDoHandle /*handle*/,
+        OCClientResponse* clientResponse)
+    {
+        ClientCallbackContext::KeepAliveContext* context =
+            static_cast<ClientCallbackContext::KeepAliveContext*>(ctx);
+        OCRepresentation attrs;
+        OCStackResult result = clientResponse->result;
+
+        try
+        {
+            attrs = parseGetSetCallback(clientResponse);
+        }
+        catch(OC::OCException& e)
+        {
+            result = e.code();
+        }
+
+        OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
+        std::thread exec(context->callback, result, attrs);
+        exec.detach();
+        return OC_STACK_DELETE_TRANSACTION;
+    }
+
+    OCStackResult InProcClientWrapper::findKeepAliveResource(std::string host,
+                                                             KeepAliveCallback resultCallback)
+    {
+        if (host.empty() || !resultCallback)
+        {
+            oclog() << "Invalid parameters" << std::flush;
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCStackResult result = OC_STACK_ERROR;
+
+        ClientCallbackContext::KeepAliveContext* ctx =
+                       new ClientCallbackContext::KeepAliveContext(resultCallback);
+        OCCallbackData cbdata;
+        cbdata.context = static_cast<void*>(ctx),
+        cbdata.cb      = KeepAliveRespCallback;
+        cbdata.cd      = [](void* c){delete (ClientCallbackContext::KeepAliveContext*)c;};
+
+        auto cLock = m_csdkLock.lock();
+
+        if (cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            result = OCFindKeepAliveResource(nullptr, host.c_str(), &cbdata);
+        }
+        else
+        {
+            delete ctx;
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+
+    OCStackResult InProcClientWrapper::sendKeepAliveRequest(std::string host,
+                                                            const OCRepresentation& rep,
+                                                            KeepAliveCallback resultCallback)
+    {
+        if (!resultCallback)
+        {
+            oclog() << "Invalid parameters" << std::flush;
+            return OC_STACK_INVALID_PARAM;
+        }
+
+        OCStackResult result = OC_STACK_ERROR;
+
+        ClientCallbackContext::KeepAliveContext* ctx = new ClientCallbackContext::KeepAliveContext(resultCallback);
+        OCCallbackData cbdata;
+        cbdata.context = static_cast<void*>(ctx),
+        cbdata.cb      = KeepAliveRespCallback;
+        cbdata.cd      = [](void* c){delete (ClientCallbackContext::KeepAliveContext*)c;};
+
+        auto cLock = m_csdkLock.lock();
+
+        if (cLock)
+        {
+            std::lock_guard<std::recursive_mutex> lock(*cLock);
+            OCRepPayload *payload = rep.getPayload();
+            result = OCSendKeepAliveRequest (nullptr, host.c_str(), (OCPayload*)payload, &cbdata);
+        }
+        else
+        {
+            delete ctx;
+            result = OC_STACK_ERROR;
+        }
+        return result;
+    }
+#endif
 }