modify "is_observable->properties", & remove tizen_info
[platform/core/iot/iotcon.git] / daemon / icd-ioty-ocprocess.c
index 5a30f39..6cc3787 100644 (file)
  * limitations under the License.
  */
 
+#include <stdint.h>
 #include <stdlib.h>
-#include <unistd.h> /* for usleep() */
+#include <unistd.h>
 #include <glib.h>
-#include <json-glib/json-glib.h>
 
 #include <ocstack.h>
+#include <octypes.h>
+#include <ocpayload.h>
 
 #include "iotcon.h"
 #include "ic-utils.h"
 #include "icd.h"
+#include "icd-payload.h"
 #include "icd-dbus.h"
 #include "icd-ioty.h"
+#include "icd-ioty-type.h"
 #include "icd-ioty-ocprocess.h"
 
 static int icd_ioty_alive;
 
-typedef int (*_ocprocess_fn)(void *user_data);
+typedef int (*_ocprocess_cb)(void *user_data);
 
 struct icd_ioty_worker
 {
        void *ctx;
-       _ocprocess_fn fn;
-};
-
-
-enum _icd_secure_type
-{
-       ICD_TRANSPORT_IPV4_SECURE,
-       ICD_TRANSPORT_IPV4
+       _ocprocess_cb cb;
 };
 
 
 struct icd_req_context {
-       unsigned int signum;
+       int64_t signal_number;
        char *bus_name;
-       char *payload;
-       int types;
-       int observer_id;
-       int observe_action;
+       int request_type;
+       int observe_id;
+       int observe_type;
        OCRequestHandle request_h;
        OCResourceHandle resource_h;
+       GVariant *payload;
        GVariantBuilder *options;
        GVariantBuilder *query;
+       OCDevAddr *dev_addr;
 };
 
 
 struct icd_find_context {
-       unsigned int signum;
+       int64_t signal_number;
        char *bus_name;
-       char *payload;
-       OCDevAddr *dev_addr;
        int conn_type;
+       GVariant **payload;
 };
 
 
-struct icd_get_context {
+struct icd_crud_context {
        int res;
-       char *payload;
+       int crud_type;
+       GVariant *payload;
        GVariantBuilder *options;
        GDBusMethodInvocation *invocation;
 };
 
 
+struct icd_info_context {
+       int64_t signal_number;
+       int info_type;
+       char *bus_name;
+       GVariant *payload;
+};
+
+
+struct icd_observe_context {
+       int64_t signal_number;
+       int res;
+       int seqnum;
+       char *bus_name;
+       GVariant *payload;
+       GVariantBuilder *options;
+};
+
+
+struct icd_presence_context {
+       OCDoHandle handle;
+       int result;
+       unsigned int nonce;
+       OCDevAddr *dev_addr;
+       iotcon_presence_trigger_e trigger;
+       char *resource_type;
+};
+
+
+struct icd_encap_context {
+       int64_t signal_number;
+       OCRepPayload *oic_payload;
+       OCStackResult ret;
+       icd_encap_info_s *encap_info;
+};
+
+
 void icd_ioty_ocprocess_stop()
 {
        icd_ioty_alive = 0;
 }
 
+
 static void* _ocprocess_worker_thread(void *data)
 {
        int ret;
@@ -92,9 +127,9 @@ static void* _ocprocess_worker_thread(void *data)
                return NULL;
        }
 
-       ret = worker->fn(worker->ctx);
+       ret = worker->cb(worker->ctx);
        if (IOTCON_ERROR_NONE != ret)
-               ERR("fn() Fail(%d)", ret);
+               ERR("cb() Fail(%d)", ret);
 
        /* worker was allocated from _ocprocess_worker_start() */
        free(worker);
@@ -104,13 +139,13 @@ static void* _ocprocess_worker_thread(void *data)
 }
 
 
-static int _ocprocess_worker_start(_ocprocess_fn fn, void *ctx)
+static int _ocprocess_worker_start(_ocprocess_cb cb, void *ctx)
 {
        GError *error;
        GThread *thread;
        struct icd_ioty_worker *worker;
 
-       RETV_IF(NULL == fn, IOTCON_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
 
        worker = calloc(1, sizeof(struct icd_ioty_worker));
        if (NULL == worker) {
@@ -118,7 +153,7 @@ static int _ocprocess_worker_start(_ocprocess_fn fn, void *ctx)
                return IOTCON_ERROR_OUT_OF_MEMORY;
        }
 
-       worker->fn = fn;
+       worker->cb = cb;
        worker->ctx = ctx;
 
        /* TODO : consider thread pool mechanism */
@@ -139,19 +174,19 @@ static int _ocprocess_worker_start(_ocprocess_fn fn, void *ctx)
 }
 
 
-static int _ocprocess_response_signal(const char *dest, const char *signal,
-               unsigned int signum, GVariant *value)
+static int _ocprocess_response_signal(const char *dest, const char *signal_prefix,
+               int64_t signal_number, GVariant *value)
 {
        int ret;
-       char sig_name[IC_DBUS_SIGNAL_LENGTH] = {0};
+       char signal_name[IC_DBUS_SIGNAL_LENGTH] = {0};
 
-       ret = snprintf(sig_name, sizeof(sig_name), "%s_%u", signal, signum);
-       if (ret <= 0 || sizeof(sig_name) <= ret) {
+       ret = snprintf(signal_name, sizeof(signal_name), "%s_%llx", signal_prefix, signal_number);
+       if (ret <= 0 || sizeof(signal_name) <= ret) {
                ERR("snprintf() Fail(%d)", ret);
-               return IOTCON_ERROR_UNKNOWN;
+               return IOTCON_ERROR_IO_ERROR;
        }
 
-       ret = icd_dbus_emit_signal(dest, sig_name, value);
+       ret = icd_dbus_emit_signal(dest, signal_name, value);
        if (IOTCON_ERROR_NONE != ret) {
                ERR("icd_dbus_emit_signal() Fail(%d)", ret);
                return ret;
@@ -176,49 +211,98 @@ static inline GVariantBuilder* _ocprocess_parse_header_options(
        return options;
 }
 
+static int _ioty_oic_action_to_ioty_action(int oic_action)
+{
+       int action;
+
+       switch (oic_action) {
+       case OC_OBSERVE_REGISTER:
+               action = IOTCON_OBSERVE_REGISTER;
+               break;
+       case OC_OBSERVE_DEREGISTER:
+               action = IOTCON_OBSERVE_DEREGISTER;
+               break;
+       case OC_OBSERVE_NO_OPTION:
+       default:
+               ERR("Invalid action (%d)", oic_action);
+               action = IOTCON_OBSERVE_NO_TYPE;
+       }
+       return action;
+}
+
+
+static void _icd_req_context_free(struct icd_req_context *ctx)
+{
+       free(ctx->bus_name);
+       if (ctx->payload)
+               g_variant_unref(ctx->payload);
+       g_variant_builder_unref(ctx->options);
+       g_variant_builder_unref(ctx->query);
+       free(ctx->dev_addr);
+       free(ctx);
+}
+
 
 static int _worker_req_handler(void *context)
 {
-       int ret;
        GVariant *value;
+       char *host_address;
+       int ret, conn_type;
+       GVariantBuilder payload_builder;
        struct icd_req_context *ctx = context;
 
        RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
 
-       value = g_variant_new("(ia(qs)a(ss)iisii)",
-                       ctx->types,
+       g_variant_builder_init(&payload_builder, G_VARIANT_TYPE("av"));
+       if (ctx->payload) {
+               g_variant_builder_add(&payload_builder, "v", ctx->payload);
+               ctx->payload = NULL;
+       }
+
+       ret = icd_ioty_get_host_address(ctx->dev_addr, &host_address, &conn_type);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("icd_ioty_get_host_address() Fail(%d)", ret);
+               g_variant_builder_clear(&payload_builder);
+               _icd_req_context_free(ctx);
+               return ret;
+       }
+
+       value = g_variant_new("(siia(qs)a(ss)iiavxx)",
+                       host_address,
+                       conn_type,
+                       ctx->request_type,
                        ctx->options,
                        ctx->query,
-                       ctx->observe_action,
-                       ctx->observer_id,
-                       ctx->payload,
-                       GPOINTER_TO_INT(ctx->request_h),
-                       GPOINTER_TO_INT(ctx->resource_h));
+                       ctx->observe_type,
+                       ctx->observe_id,
+                       &payload_builder,
+                       ICD_POINTER_TO_INT64(ctx->request_h),
+                       ICD_POINTER_TO_INT64(ctx->resource_h));
+
+       free(host_address);
 
        ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_REQUEST_HANDLER,
-                       ctx->signum, value);
+                       ctx->signal_number, value);
        if (IOTCON_ERROR_NONE != ret)
                ERR("_ocprocess_response_signal() Fail(%d)", ret);
 
-       free(ctx->bus_name);
-       free(ctx->payload);
-       g_variant_builder_unref(ctx->options);
-       g_variant_builder_unref(ctx->query);
-       free(ctx);
+       _icd_req_context_free(ctx);
 
        return ret;
 }
 
 
 OCEntityHandlerResult icd_ioty_ocprocess_req_handler(OCEntityHandlerFlag flag,
-               OCEntityHandlerRequest *request)
+               OCEntityHandlerRequest *request, void *user_data)
 {
+       FN_CALL;
        int ret;
-       unsigned int signal_number;
+       int64_t signal_number;
        char *query_str, *query_key, *query_value;
        char *token, *save_ptr1, *save_ptr2;
        char *bus_name = NULL;
        struct icd_req_context *req_ctx;
+       OCDevAddr *dev_addr;
 
        RETV_IF(NULL == request, OC_EH_ERROR);
 
@@ -240,42 +324,54 @@ OCEntityHandlerResult icd_ioty_ocprocess_req_handler(OCEntityHandlerFlag flag,
        }
 
        /* signal number & bus_name */
-       req_ctx->signum = signal_number;
+       req_ctx->signal_number = signal_number;
        req_ctx->bus_name = bus_name;
 
+       dev_addr = calloc(1, sizeof(OCDevAddr));
+       if (NULL == dev_addr) {
+               ERR("calloc() Fail(%d)", errno);
+               free(req_ctx->bus_name);
+               free(req_ctx);
+               return OC_EH_ERROR;
+       }
+       memcpy(dev_addr, &request->devAddr, sizeof(OCDevAddr));
+       req_ctx->dev_addr = dev_addr;
+
        /* request type */
        if (OC_REQUEST_FLAG & flag) {
                switch (request->method) {
                case OC_REST_GET:
-                       req_ctx->types = IOTCON_REQUEST_GET;
-                       req_ctx->payload = strdup(IC_STR_NULL);
-
-                       if (OC_OBSERVE_FLAG & flag) {
-                               req_ctx->types |= IOTCON_REQUEST_OBSERVE;
-                               /* observation info*/
-                               req_ctx->observer_id = request->obsInfo.obsId;
-                               req_ctx->observe_action = request->obsInfo.action;
-                       }
+                       req_ctx->request_type = IOTCON_REQUEST_GET;
+                       req_ctx->payload = NULL;
                        break;
                case OC_REST_PUT:
-                       req_ctx->types = IOTCON_REQUEST_PUT;
-                       req_ctx->payload = ic_utils_strdup(request->reqJSONPayload);
+                       req_ctx->request_type = IOTCON_REQUEST_PUT;
+                       req_ctx->payload = icd_payload_to_gvariant(request->payload);
                        break;
                case OC_REST_POST:
-                       req_ctx->types = IOTCON_REQUEST_POST;
-                       req_ctx->payload = ic_utils_strdup(request->reqJSONPayload);
+                       req_ctx->request_type = IOTCON_REQUEST_POST;
+                       req_ctx->payload = icd_payload_to_gvariant(request->payload);
                        break;
                case OC_REST_DELETE:
-                       req_ctx->types = IOTCON_REQUEST_DELETE;
-                       req_ctx->payload = strdup(IC_STR_NULL);
+                       req_ctx->request_type = IOTCON_REQUEST_DELETE;
+                       req_ctx->payload = NULL;
                        break;
                default:
+                       free(req_ctx->dev_addr);
                        free(req_ctx->bus_name);
                        free(req_ctx);
                        return OC_EH_ERROR;
                }
        }
 
+       if (OC_OBSERVE_FLAG & flag) {
+               /* observation info*/
+               req_ctx->observe_id = request->obsInfo.obsId;
+               req_ctx->observe_type = _ioty_oic_action_to_ioty_action(request->obsInfo.action);
+       } else {
+               req_ctx->observe_type = IOTCON_OBSERVE_NO_TYPE;
+       }
+
        /* header options */
        req_ctx->options = _ocprocess_parse_header_options(
                        request->rcvdVendorSpecificHeaderOptions,
@@ -284,7 +380,7 @@ OCEntityHandlerResult icd_ioty_ocprocess_req_handler(OCEntityHandlerFlag flag,
        /* query */
        req_ctx->query = g_variant_builder_new(G_VARIANT_TYPE("a(ss)"));
        query_str = request->query;
-       while ((token = strtok_r(query_str, "&", &save_ptr1))) {
+       while ((token = strtok_r(query_str, "&;", &save_ptr1))) {
                while ((query_key = strtok_r(token, "=", &save_ptr2))) {
                        token = NULL;
                        query_value = strtok_r(token, "=", &save_ptr2);
@@ -299,11 +395,7 @@ OCEntityHandlerResult icd_ioty_ocprocess_req_handler(OCEntityHandlerFlag flag,
        ret = _ocprocess_worker_start(_worker_req_handler, req_ctx);
        if (IOTCON_ERROR_NONE != ret) {
                ERR("_ocprocess_worker_start() Fail(%d)", ret);
-               free(req_ctx->bus_name);
-               free(req_ctx->payload);
-               g_variant_builder_unref(req_ctx->options);
-               g_variant_builder_unref(req_ctx->query);
-               free(req_ctx);
+               _icd_req_context_free(req_ctx);
                return OC_EH_ERROR;
        }
 
@@ -317,6 +409,7 @@ gpointer icd_ioty_ocprocess_thread(gpointer data)
 {
        FN_CALL;
        OCStackResult result;
+       const struct timespec delay = {0, 10 * 1000 * 1000}; /* 10 ms */
 
        icd_ioty_alive = 1;
        while (icd_ioty_alive) {
@@ -328,188 +421,463 @@ gpointer icd_ioty_ocprocess_thread(gpointer data)
                        break;
                }
 
-               /* TODO : SHOULD revise time or usleep */
-               usleep(10);
+               /* TODO : Current '10ms' is not proven sleep time. Revise the time after test.
+                * Or recommend changes to event driven architecture */
+               nanosleep(&delay, NULL);
        }
 
        return NULL;
 }
 
 
-/*
- * returned string SHOULD be released by you
- */
-static inline char* _find_cb_get_address(OCDevAddr *address, int sec_type, int sec_port)
+static int _worker_find_cb(void *context)
 {
-       FN_CALL;
-       int ret;
-       uint16_t port;
-       uint8_t a, b, c, d;
-       char addr[1024] = {0};
+       GVariant *value;
+       int i, ret;
+       struct icd_find_context *ctx = context;
 
-       RETVM_IF(ICD_TRANSPORT_IPV4 != sec_type && ICD_TRANSPORT_IPV4_SECURE != sec_type,
-                       NULL, "Invalid secure type(%d)", sec_type);
+       RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
 
-       ret = OCDevAddrToIPv4Addr(address, &a, &b, &c, &d);
-       if (OC_STACK_OK != ret) {
-               ERR("OCDevAddrToIPv4Addr() Fail(%d)", ret);
-               return NULL;
+       for (i = 0; ctx->payload[i]; i++) {
+               value = g_variant_new("(vi)", ctx->payload[i], ctx->conn_type);
+               /* TODO : If one device has multi resources, it comes as bulk data.
+                * To reduce the number of emit_signal, let's send signal only one time for one device.
+                * for ex, client list. */
+               ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_FOUND_RESOURCE,
+                               ctx->signal_number, value);
+               if (IOTCON_ERROR_NONE != ret) {
+                       ERR("_ocprocess_response_signal() Fail(%d)", ret);
+                       g_variant_unref(value);
+                       return ret;
+               }
        }
 
-       if (ICD_TRANSPORT_IPV4_SECURE == sec_type) {
-               if (sec_port <= 0 || 65535 < sec_port) {
-                       SECURE_ERR("Invalid secure port(%d)", sec_port);
-                       return NULL;
-               }
+       /* ctx was allocated from icd_ioty_ocprocess_find_cb() */
+       free(ctx->bus_name);
+       free(ctx);
 
-               ret = snprintf(addr, sizeof(addr), ICD_IOTY_COAPS"%d.%d.%d.%d:%d", a, b, c, d,
-                               sec_port);
-       } else {
-               ret = OCDevAddrToPort(address, &port);
-               if (OC_STACK_OK != ret) {
-                       ERR("OCDevAddrToPort() Fail(%d)", ret);
-                       return NULL;
-               }
+       return ret;
+}
+
+
+OCStackApplicationResult icd_ioty_ocprocess_find_cb(void *ctx, OCDoHandle handle,
+               OCClientResponse *resp)
+{
+       int ret;
+       struct icd_find_context *find_ctx;
+       icd_sig_ctx_s *sig_context = ctx;
 
-               ret = snprintf(addr, sizeof(addr), ICD_IOTY_COAP"%d.%d.%d.%d:%d", a, b, c, d,
-                               port);
+       RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
+       RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
+       if (NULL == resp->payload)
+               /* normal case : payload COULD be NULL */
+               return OC_STACK_KEEP_TRANSACTION;
+       RETVM_IF(PAYLOAD_TYPE_DISCOVERY != resp->payload->type,
+                       OC_STACK_KEEP_TRANSACTION, "Invalid payload type(%d)", resp->payload->type);
+
+       find_ctx = calloc(1, sizeof(struct icd_find_context));
+       if (NULL == find_ctx) {
+               ERR("calloc() Fail(%d)", errno);
+               return OC_STACK_KEEP_TRANSACTION;
        }
 
-       WARN_IF(ret <= 0 || sizeof(addr) <= ret, "snprintf() Fail(%d)", ret);
+       find_ctx->signal_number = sig_context->signal_number;
+       find_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
+       find_ctx->payload = icd_payload_res_to_gvariant(resp->payload, &resp->devAddr);
+       find_ctx->conn_type = icd_ioty_transport_flag_to_conn_type(resp->devAddr.adapter,
+                       resp->devAddr.flags);
 
-       return ic_utils_strdup(addr);
+       ret = _ocprocess_worker_start(_worker_find_cb, find_ctx);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("_ocprocess_worker_start() Fail(%d)", ret);
+               free(find_ctx->bus_name);
+               ic_utils_gvariant_array_free(find_ctx->payload);
+               free(find_ctx);
+               return OC_STACK_KEEP_TRANSACTION;
+       }
+
+       /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
+       /* DO NOT FREE find_ctx. It MUST be freed in the _worker_find_cb func */
+
+       return OC_STACK_KEEP_TRANSACTION;
 }
 
 
-static inline int _find_cb_response(JsonObject *rsrc_obj,
-               struct icd_find_context *ctx)
+static int _worker_crud_cb(void *context)
 {
        GVariant *value;
-       JsonGenerator *gen;
-       JsonNode *root_node;
-       char *host, *json_data;
-       JsonObject *property_obj;
-       int ret, secure, secure_type, secure_port;
+       struct icd_crud_context *ctx = context;
 
-       RETV_IF(NULL == rsrc_obj, IOTCON_ERROR_INVALID_PARAMETER);
        RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
 
-       /* parse secure secure_port */
-       property_obj = json_object_get_object_member(rsrc_obj, IC_JSON_KEY_PROPERTY);
-       if (NULL == property_obj) {
-               ERR("json_object_get_object_member() Fail");
-               return IOTCON_ERROR_INVALID_PARAMETER;
+       if (ICD_CRUD_DELETE == ctx->crud_type)
+               value = g_variant_new("(a(qs)i)", ctx->options, ctx->res);
+       else
+               value = g_variant_new("(a(qs)vi)", ctx->options, ctx->payload, ctx->res);
+       icd_ioty_complete(ctx->crud_type, ctx->invocation, value);
+
+       /* ctx was allocated from icd_ioty_ocprocess_xxx_cb() */
+       g_variant_builder_unref(ctx->options);
+       free(ctx);
+
+       return IOTCON_ERROR_NONE;
+}
+
+
+static int _worker_info_cb(void *context)
+{
+       int ret;
+       const char *signal_prefix = NULL;
+       struct icd_info_context *ctx = context;
+
+       RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
+
+       if (ICD_DEVICE_INFO == ctx->info_type)
+               signal_prefix = IC_DBUS_SIGNAL_DEVICE;
+       else if (ICD_PLATFORM_INFO == ctx->info_type)
+               signal_prefix = IC_DBUS_SIGNAL_PLATFORM;
+
+       ret = _ocprocess_response_signal(ctx->bus_name, signal_prefix, ctx->signal_number,
+                       ctx->payload);
+       if (IOTCON_ERROR_NONE != ret)
+               ERR("_ocprocess_response_signal() Fail(%d)", ret);
+
+       /* ctx was allocated from icd_ioty_ocprocess_info_cb() */
+       free(ctx->bus_name);
+       free(ctx);
+
+       return ret;
+}
+
+
+static int _ocprocess_worker(_ocprocess_cb cb, int type, OCPayload *payload, int res,
+               GVariantBuilder *options, void *ctx)
+{
+       int ret;
+       struct icd_crud_context *crud_ctx;
+
+       crud_ctx = calloc(1, sizeof(struct icd_crud_context));
+       if (NULL == crud_ctx) {
+               ERR("calloc() Fail(%d)", errno);
+               return IOTCON_ERROR_OUT_OF_MEMORY;
        }
 
-       secure = json_object_get_int_member(property_obj, IC_JSON_KEY_SECURE);
-       if (0 == secure) {
-               secure_type = ICD_TRANSPORT_IPV4;
-               secure_port = 0;
-       } else {
-               secure_type = ICD_TRANSPORT_IPV4_SECURE;
-               secure_port = json_object_get_int_member(property_obj, IC_JSON_KEY_PORT);
+       crud_ctx->crud_type = type;
+       crud_ctx->payload = icd_payload_to_gvariant(payload);
+       crud_ctx->res = res;
+       crud_ctx->options = options;
+       crud_ctx->invocation = ctx;
+
+       ret = _ocprocess_worker_start(cb, crud_ctx);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("_ocprocess_worker_start() Fail(%d)", ret);
+               if (crud_ctx->payload)
+                       g_variant_unref(crud_ctx->payload);
+               g_variant_builder_unref(crud_ctx->options);
+               free(crud_ctx);
        }
 
-       host = _find_cb_get_address(ctx->dev_addr, secure_type, secure_port);
-       if (NULL == host) {
-               ERR("_find_cb_get_address() Fail");
-               return IOTCON_ERROR_IOTIVITY;
+       /* DO NOT FREE crud_ctx. It MUST be freed in the _worker_crud_cb func */
+
+       return ret;
+}
+
+static int _ocprocess_parse_oic_result(OCStackResult result)
+{
+       int res;
+
+       switch (result) {
+       case OC_STACK_OK:
+               res = IOTCON_RESPONSE_OK;
+               break;
+       case OC_STACK_RESOURCE_CREATED:
+               res = IOTCON_RESPONSE_RESOURCE_CREATED;
+               break;
+       case OC_STACK_RESOURCE_DELETED:
+               res = IOTCON_RESPONSE_RESULT_DELETED;
+               break;
+       case OC_STACK_UNAUTHORIZED_REQ:
+               res = IOTCON_RESPONSE_FORBIDDEN;
+               break;
+       default:
+               WARN("response error(%d)", result);
+               res = IOTCON_RESPONSE_ERROR;
+               break;
        }
 
-       gen = json_generator_new();
-       root_node = json_node_new(JSON_NODE_OBJECT);
-       json_node_set_object(root_node, rsrc_obj);
-       json_generator_set_root(gen, root_node);
+       return res;
+}
+
+
+OCStackApplicationResult icd_ioty_ocprocess_get_cb(void *ctx, OCDoHandle handle,
+               OCClientResponse *resp)
+{
+       FN_CALL;
+       int ret, res;
+       GVariantBuilder *options;
+
+       RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
 
-       json_data = json_generator_to_data(gen, NULL);
-       json_node_free(root_node);
-       g_object_unref(gen);
+       if (NULL == resp->payload) {
+               ERR("payload is empty");
+               icd_ioty_complete_error(ICD_CRUD_GET, ctx, IOTCON_ERROR_IOTIVITY);
+               return OC_STACK_DELETE_TRANSACTION;
+       }
+
+       res = _ocprocess_parse_oic_result(resp->result);
 
-       value = g_variant_new("(ssi)", json_data, host, ctx->conn_type);
-       free(json_data);
-       free(host);
+       options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
+                       resp->numRcvdVendorSpecificHeaderOptions);
 
-       /* TODO : If one device has multi resources, it comes as bulk data.
-        * To reduce the number of emit_signal, let's send signal only one time for one device.
-        * for ex, client list. */
-       ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_FOUND_RESOURCE,
-                       ctx->signum, value);
+       ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_GET, resp->payload, res,
+                       options, ctx);
        if (IOTCON_ERROR_NONE != ret) {
-               ERR("_ocprocess_response_signal() Fail(%d)", ret);
-               return ret;
+               ERR("_ocprocess_worker() Fail(%d)", ret);
+               icd_ioty_complete_error(ICD_CRUD_GET, ctx, ret);
+               return OC_STACK_DELETE_TRANSACTION;
        }
 
-       return IOTCON_ERROR_NONE;
+       return OC_STACK_DELETE_TRANSACTION;
 }
 
 
-static inline int _find_cb_handle_context(struct icd_find_context *ctx)
+OCStackApplicationResult icd_ioty_ocprocess_put_cb(void *ctx, OCDoHandle handle,
+               OCClientResponse *resp)
 {
-       int ret;
-       JsonParser *parser;
-       GError *error = NULL;
-       JsonObject *root_obj;
-       JsonArray *rsrc_array;
-       unsigned int rsrc_count, rsrc_index;
+       FN_CALL;
+       int ret, res;
+       GVariantBuilder *options;
 
-       RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
-       RETV_IF(NULL == ctx->payload, IOTCON_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
 
-       parser = json_parser_new();
-       ret = json_parser_load_from_data(parser, ctx->payload, strlen(ctx->payload), &error);
-       if (FALSE == ret) {
-               ERR("json_parser_load_from_data() Fail(%s)", error->message);
-               g_error_free(error);
-               return IOTCON_ERROR_INVALID_PARAMETER;
+       if (NULL == resp->payload) {
+               ERR("payload is empty");
+               icd_ioty_complete_error(ICD_CRUD_PUT, ctx, IOTCON_ERROR_IOTIVITY);
+               return OC_STACK_DELETE_TRANSACTION;
        }
 
-       /* parse 'oc' prefix */
-       root_obj = json_node_get_object(json_parser_get_root(parser));
-       rsrc_array = json_object_get_array_member(root_obj, IC_JSON_KEY_OC);
-       if (NULL == rsrc_array) {
-               ERR("json_object_get_array_member() Fail");
-               g_object_unref(parser);
-               return IOTCON_ERROR_INVALID_PARAMETER;
+       res = _ocprocess_parse_oic_result(resp->result);
+
+       options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
+                       resp->numRcvdVendorSpecificHeaderOptions);
+
+       ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_PUT, resp->payload, res,
+                       options, ctx);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("_ocprocess_worker() Fail(%d)", ret);
+               icd_ioty_complete_error(ICD_CRUD_PUT, ctx, ret);
+               return OC_STACK_DELETE_TRANSACTION;
        }
 
-       rsrc_count = json_array_get_length(rsrc_array);
-       if (0 == rsrc_count) {
-               ERR("Invalid count(%d)", rsrc_count);
-               g_object_unref(parser);
-               return IOTCON_ERROR_INVALID_PARAMETER;
+       return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+OCStackApplicationResult icd_ioty_ocprocess_post_cb(void *ctx, OCDoHandle handle,
+               OCClientResponse *resp)
+{
+       FN_CALL;
+       int ret, res;
+       GVariantBuilder *options;
+
+       RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
+
+       if (NULL == resp->payload) {
+               ERR("payload is empty");
+               icd_ioty_complete_error(ICD_CRUD_POST, ctx, IOTCON_ERROR_IOTIVITY);
+               return OC_STACK_DELETE_TRANSACTION;
        }
 
-       for (rsrc_index = 0; rsrc_index < rsrc_count; rsrc_index++) {
-               JsonObject *rsrc_obj = json_array_get_object_element(rsrc_array, rsrc_index);
+       res = _ocprocess_parse_oic_result(resp->result);
 
-               ret = _find_cb_response(rsrc_obj, ctx);
-               if (IOTCON_ERROR_NONE != ret) {
-                       ERR("_find_cb_response() Fail(%d)", ret);
-                       g_object_unref(parser);
-                       return ret;
-               }
+       options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
+                       resp->numRcvdVendorSpecificHeaderOptions);
+
+       ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_POST, resp->payload, res,
+                       options, ctx);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("_ocprocess_worker() Fail(%d)", ret);
+               icd_ioty_complete_error(ICD_CRUD_POST, ctx, ret);
+               return OC_STACK_DELETE_TRANSACTION;
        }
 
-       g_object_unref(parser);
+       return OC_STACK_DELETE_TRANSACTION;
+}
 
-       return IOTCON_ERROR_NONE;
+
+OCStackApplicationResult icd_ioty_ocprocess_delete_cb(void *ctx, OCDoHandle handle,
+               OCClientResponse *resp)
+{
+       FN_CALL;
+       int ret, res;
+       GVariantBuilder *options;
+
+       RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
+
+       if (NULL == resp->payload) {
+               ERR("payload is empty");
+               icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, IOTCON_ERROR_IOTIVITY);
+               return OC_STACK_DELETE_TRANSACTION;
+       }
+
+       res = _ocprocess_parse_oic_result(resp->result);
+
+       options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
+                       resp->numRcvdVendorSpecificHeaderOptions);
+
+       ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_DELETE, NULL, res, options, ctx);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("_ocprocess_worker() Fail(%d)", ret);
+               icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, ret);
+               return OC_STACK_DELETE_TRANSACTION;
+       }
+
+       return OC_STACK_DELETE_TRANSACTION;
 }
 
 
-static int _worker_find_cb(void *context)
+static int _worker_observe_cb(void *context)
 {
        int ret;
-       struct icd_find_context *ctx = context;
+       GVariant *value;
+       struct icd_observe_context *ctx = context;
 
        RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
 
-       ret = _find_cb_handle_context(ctx);
+       value = g_variant_new("(a(qs)vii)", ctx->options, ctx->payload, ctx->res,
+                       ctx->seqnum);
+
+       ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_OBSERVE,
+                       ctx->signal_number, value);
        if (IOTCON_ERROR_NONE != ret)
-               ERR("_find_cb_handle_context() Fail(%d)", ret);
+               ERR("_ocprocess_response_signal() Fail(%d)", ret);
 
-       /* ctx was allocated from icd_ioty_ocprocess_find_cb() */
+       /* ctx was allocated from icd_ioty_ocprocess_observe_cb() */
        free(ctx->bus_name);
-       free(ctx->payload);
+       g_variant_builder_unref(ctx->options);
+       free(ctx);
+
+       return ret;
+}
+
+
+static void _observe_cb_response_error(const char *dest,
+               int64_t signal_number, int ret_val)
+{
+       int ret;
+       GVariant *value;
+       GVariant *payload;
+       GVariantBuilder options;
+
+       g_variant_builder_init(&options, G_VARIANT_TYPE("a(qs)"));
+       payload = icd_payload_representation_empty_gvariant();
+
+       value = g_variant_new("(a(qs)vii)", &options, payload, ret_val, 0);
+
+       ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_OBSERVE, signal_number, value);
+       if (IOTCON_ERROR_NONE != ret)
+               ERR("_ocprocess_response_signal() Fail(%d)", ret);
+}
+
+
+OCStackApplicationResult icd_ioty_ocprocess_observe_cb(void *ctx,
+               OCDoHandle handle, OCClientResponse *resp)
+{
+       int ret, res;
+       GVariantBuilder *options;
+       struct icd_observe_context *observe_ctx;
+       icd_sig_ctx_s *sig_context = ctx;
+
+       RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
+
+       if (NULL == resp->payload) {
+               ERR("payload is empty");
+               _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number,
+                               IOTCON_ERROR_IOTIVITY);
+               return OC_STACK_KEEP_TRANSACTION;
+       }
+
+       observe_ctx = calloc(1, sizeof(struct icd_observe_context));
+       if (NULL == observe_ctx) {
+               ERR("calloc() Fail(%d)", errno);
+               _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number,
+                               IOTCON_ERROR_OUT_OF_MEMORY);
+               return OC_STACK_KEEP_TRANSACTION;
+       }
+
+       res = _ocprocess_parse_oic_result(resp->result);
+
+       options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
+                       resp->numRcvdVendorSpecificHeaderOptions);
+
+       observe_ctx->payload = icd_payload_to_gvariant(resp->payload);
+       observe_ctx->signal_number = sig_context->signal_number;
+       observe_ctx->res = res;
+       observe_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
+       observe_ctx->options = options;
+
+       ret = _ocprocess_worker_start(_worker_observe_cb, observe_ctx);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("_ocprocess_worker_start() Fail(%d)", ret);
+               _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number, ret);
+               free(observe_ctx->bus_name);
+               if (observe_ctx->payload)
+                       g_variant_unref(observe_ctx->payload);
+               g_variant_builder_unref(observe_ctx->options);
+               free(observe_ctx);
+               return OC_STACK_KEEP_TRANSACTION;
+       }
+
+       /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
+       /* DO NOT FREE observe_ctx. It MUST be freed in the _worker_observe_cb func */
+
+       return OC_STACK_KEEP_TRANSACTION;
+}
+
+
+static int _worker_presence_cb(void *context)
+{
+       int conn_type;
+       OCDoHandle handle;
+       char *host_address;
+       GVariant *value, *value2;
+       int ret = IOTCON_ERROR_NONE;
+       struct icd_presence_context *ctx = context;
+
+       RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
+
+       ret = icd_ioty_get_host_address(ctx->dev_addr, &host_address, &conn_type);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("icd_ioty_get_host_address() Fail(%d)", ret);
+               free(ctx->resource_type);
+               free(ctx->dev_addr);
+               free(ctx);
+               return ret;
+       }
+
+       value = g_variant_new("(iusiis)", ctx->result, ctx->nonce, host_address, conn_type,
+                       ctx->trigger, ic_utils_dbus_encode_str(ctx->resource_type));
+       value2 = g_variant_ref(value);
+
+       free(host_address);
+
+       ret = _ocprocess_response_signal(NULL, IC_DBUS_SIGNAL_PRESENCE,
+                       ICD_POINTER_TO_INT64(ctx->handle), value);
+       if (IOTCON_ERROR_NONE != ret)
+               ERR("_ocprocess_response_signal() Fail(%d)", ret);
+
+       handle = icd_ioty_presence_table_get_handle(ICD_MULTICAST_ADDRESS);
+       if (handle && (handle != ctx->handle)) {
+               ret = _ocprocess_response_signal(NULL, IC_DBUS_SIGNAL_PRESENCE,
+                               ICD_POINTER_TO_INT64(handle), value2);
+               if (IOTCON_ERROR_NONE != ret)
+                       ERR("_ocprocess_response_signal() Fail(%d)", ret);
+       } else {
+               g_variant_unref(value2);
+       }
+
+       /* ctx was allocated from icd_ioty_ocprocess_presence_cb() */
+       free(ctx->resource_type);
        free(ctx->dev_addr);
        free(ctx);
 
@@ -517,127 +885,329 @@ static int _worker_find_cb(void *context)
 }
 
 
-OCStackApplicationResult icd_ioty_ocprocess_find_cb(void *ctx, OCDoHandle handle,
+static void _presence_cb_response_error(OCDoHandle handle, int ret_val)
+{
+       FN_CALL;
+       int ret;
+       OCDoHandle handle2;
+       GVariant *value, *value2;
+
+       value = g_variant_new("(iusiis)", ret_val, 0, IC_STR_NULL, IOTCON_CONNECTIVITY_ALL,
+                       IOTCON_PRESENCE_RESOURCE_CREATED, IC_STR_NULL);
+       value2 = g_variant_ref(value);
+
+       ret = _ocprocess_response_signal(NULL, IC_DBUS_SIGNAL_PRESENCE,
+                       ICD_POINTER_TO_INT64(handle), value);
+       if (IOTCON_ERROR_NONE != ret)
+               ERR("_ocprocess_response_signal() Fail(%d)", ret);
+
+       handle2 = icd_ioty_presence_table_get_handle(ICD_MULTICAST_ADDRESS);
+       if (handle2 && (handle2 != handle)) {
+               ret = _ocprocess_response_signal(NULL, IC_DBUS_SIGNAL_PRESENCE,
+                               ICD_POINTER_TO_INT64(handle), value2);
+               if (IOTCON_ERROR_NONE != ret)
+                       ERR("_ocprocess_response_signal() Fail(%d)", ret);
+       } else {
+               g_variant_unref(value2);
+       }
+}
+
+
+static int _presence_trigger_to_ioty_trigger(OCPresenceTrigger src,
+               iotcon_presence_trigger_e *dest)
+{
+       RETV_IF(NULL == dest, IOTCON_ERROR_INVALID_PARAMETER);
+
+       switch (src) {
+       case OC_PRESENCE_TRIGGER_CREATE:
+               *dest = IOTCON_PRESENCE_RESOURCE_CREATED;
+               break;
+       case OC_PRESENCE_TRIGGER_CHANGE:
+               *dest = IOTCON_PRESENCE_RESOURCE_UPDATED;
+               break;
+       case OC_PRESENCE_TRIGGER_DELETE:
+               *dest = IOTCON_PRESENCE_RESOURCE_DESTROYED;
+               break;
+       default:
+               ERR("Invalid trigger(%d)", src);
+               return IOTCON_ERROR_INVALID_PARAMETER;
+       }
+
+       return IOTCON_ERROR_NONE;
+}
+
+
+OCStackApplicationResult icd_ioty_ocprocess_presence_cb(void *ctx, OCDoHandle handle,
                OCClientResponse *resp)
 {
+       FN_CALL;
        int ret;
        OCDevAddr *dev_addr;
-       struct icd_find_context *find_ctx;
-       icd_sig_ctx_s *sig_context = ctx;
+       OCPresencePayload *payload;
+       struct icd_presence_context *presence_ctx;
 
-       RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
        RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
-       RETV_IF(NULL == resp->resJSONPayload, OC_STACK_KEEP_TRANSACTION);
 
-       find_ctx = calloc(1, sizeof(struct icd_find_context));
-       if (NULL == find_ctx) {
+       presence_ctx = calloc(1, sizeof(struct icd_presence_context));
+       if (NULL == presence_ctx) {
                ERR("calloc() Fail(%d)", errno);
+               _presence_cb_response_error(handle, IOTCON_ERROR_OUT_OF_MEMORY);
                return OC_STACK_KEEP_TRANSACTION;
        }
 
        dev_addr = calloc(1, sizeof(OCDevAddr));
        if (NULL == dev_addr) {
                ERR("calloc() Fail(%d)", errno);
-               free(find_ctx);
+               _presence_cb_response_error(handle, IOTCON_ERROR_OUT_OF_MEMORY);
+               free(presence_ctx);
                return OC_STACK_KEEP_TRANSACTION;
        }
-       memcpy(dev_addr, resp->addr, sizeof(OCDevAddr));
+       memcpy(dev_addr, &resp->devAddr, sizeof(OCDevAddr));
 
-       find_ctx->signum = sig_context->signum;
-       find_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
-       find_ctx->payload = ic_utils_strdup(resp->resJSONPayload);
-       find_ctx->dev_addr = dev_addr;
-       find_ctx->conn_type = resp->connType;
+       payload = (OCPresencePayload*)resp->payload;
 
-       ret = _ocprocess_worker_start(_worker_find_cb, find_ctx);
+       switch (resp->result) {
+       case OC_STACK_OK:
+               presence_ctx->result = IOTCON_PRESENCE_OK;
+               ret = _presence_trigger_to_ioty_trigger(payload->trigger, &presence_ctx->trigger);
+               if (IOTCON_ERROR_NONE != ret) {
+                       ERR("_presence_trigger_to_ioty_trigger() Fail(%d)", ret);
+                       _presence_cb_response_error(handle, ret);
+                       free(presence_ctx);
+                       return OC_STACK_KEEP_TRANSACTION;
+               }
+               break;
+       case OC_STACK_PRESENCE_STOPPED:
+               presence_ctx->result = IOTCON_PRESENCE_STOPPED;
+               break;
+       case OC_STACK_PRESENCE_TIMEOUT:
+               presence_ctx->result = IOTCON_PRESENCE_TIMEOUT;
+               break;
+       case OC_STACK_ERROR:
+       default:
+               DBG("Presence error(%d)", resp->result);
+               presence_ctx->result = IOTCON_ERROR_IOTIVITY;
+       }
+
+       presence_ctx->handle = handle;
+       presence_ctx->nonce = resp->sequenceNumber;
+       presence_ctx->dev_addr = dev_addr;
+
+       if (payload->resourceType)
+               presence_ctx->resource_type = strdup(payload->resourceType);
+
+       ret = _ocprocess_worker_start(_worker_presence_cb, presence_ctx);
        if (IOTCON_ERROR_NONE != ret) {
                ERR("_ocprocess_worker_start() Fail(%d)", ret);
-               free(find_ctx->bus_name);
-               free(find_ctx->payload);
-               free(find_ctx->dev_addr);
-               free(find_ctx);
+               _presence_cb_response_error(handle, ret);
+               free(presence_ctx->resource_type);
+               free(presence_ctx->dev_addr);
+               free(presence_ctx);
+               return OC_STACK_KEEP_TRANSACTION;
+       }
+
+       /* DO NOT FREE presence_ctx. It MUST be freed in the _worker_presence_cb func */
+
+       return OC_STACK_KEEP_TRANSACTION;
+}
+
+
+OCStackApplicationResult icd_ioty_ocprocess_info_cb(void *ctx, OCDoHandle handle,
+               OCClientResponse *resp)
+{
+       int ret;
+       int info_type;
+       struct icd_info_context *info_ctx;
+       icd_sig_ctx_s *sig_context = ctx;
+
+       RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
+       RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
+       RETV_IF(NULL == resp->payload, OC_STACK_KEEP_TRANSACTION);
+
+       if (PAYLOAD_TYPE_DEVICE == resp->payload->type)
+               info_type = ICD_DEVICE_INFO;
+       else if (PAYLOAD_TYPE_PLATFORM == resp->payload->type)
+               info_type = ICD_PLATFORM_INFO;
+       else
+               return OC_STACK_KEEP_TRANSACTION;
+
+       info_ctx = calloc(1, sizeof(struct icd_info_context));
+       if (NULL == info_ctx) {
+               ERR("calloc() Fail(%d)", errno);
+               return OC_STACK_KEEP_TRANSACTION;
+       }
+
+       info_ctx->info_type = info_type;
+       info_ctx->payload = icd_payload_to_gvariant(resp->payload);
+       info_ctx->signal_number = sig_context->signal_number;
+       info_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
+
+       ret = _ocprocess_worker_start(_worker_info_cb, info_ctx);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("_ocprocess_worker_start() Fail(%d)", ret);
+               free(info_ctx->bus_name);
+               if (info_ctx->payload)
+                       g_variant_unref(info_ctx->payload);
+               free(info_ctx);
                return OC_STACK_KEEP_TRANSACTION;
        }
 
        /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
-       /* DO NOT FREE find_ctx. It MUST be freed in the _worker_find_cb func */
+       /* DO NOT FREE info_ctx. It MUST be freed in the _worker_info_cb func */
 
        return OC_STACK_KEEP_TRANSACTION;
 }
 
 
-static int _worker_get_cb(void *context)
+static int _worker_encap_get_cb(void *context)
 {
        int ret;
-       GVariant *value;
-       struct icd_get_context *ctx = context;
+       struct icd_encap_context *ctx = context;
+       iotcon_remote_resource_state_e resource_state;
+       GVariant *monitoring_value, *caching_value;
 
        RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
 
-       value = g_variant_new("(a(qs)si)", ctx->options, ctx->payload, ctx->res);
-       icd_ioty_get_complete(ctx->invocation, value);
+       /* MONITORING */
+       if (0 < ctx->encap_info->monitoring_count) {
+               switch (ctx->ret) {
+               case OC_STACK_OK:
+                       resource_state = IOTCON_REMOTE_RESOURCE_ALIVE;
+                       break;
+               case OC_STACK_ERROR:
+               default:
+                       resource_state = IOTCON_REMOTE_RESOURCE_LOST_SIGNAL;
+               }
+               if (resource_state != ctx->encap_info->resource_state) {
+                       ctx->encap_info->resource_state = resource_state;
+                       monitoring_value = g_variant_new("(i)", resource_state);
+                       ret = _ocprocess_response_signal(NULL, IC_DBUS_SIGNAL_MONITORING,
+                                       ctx->encap_info->signal_number, monitoring_value);
+                       if (IOTCON_ERROR_NONE != ret) {
+                               ERR("_ocprocess_response_signal() Fail(%d)", ret);
+                               OCRepPayloadDestroy(ctx->oic_payload);
+                               free(ctx);
+                               return ret;
+                       }
+               }
+       }
 
-       /* ctx was allocated from icd_ioty_ocprocess_get_cb() */
-       free(ctx->payload);
-       g_variant_builder_unref(ctx->options);
+       /* CACHING */
+       if (0 < ctx->encap_info->caching_count) {
+               if (OC_STACK_OK != ctx->ret) {
+                       OCRepPayloadDestroy(ctx->oic_payload);
+                       free(ctx);
+                       return IOTCON_ERROR_NONE;
+               }
+
+               ret = icd_payload_representation_compare(ctx->encap_info->oic_payload,
+                               ctx->oic_payload);
+               if (IC_EQUAL == ret) {
+                       OCRepPayloadDestroy(ctx->oic_payload);
+                       free(ctx);
+                       return IOTCON_ERROR_NONE;
+               }
+
+               ctx->encap_info->oic_payload = ctx->oic_payload;
+               caching_value = icd_payload_to_gvariant((OCPayload*)ctx->oic_payload);
+
+               ret = _ocprocess_response_signal(NULL, IC_DBUS_SIGNAL_CACHING,
+                               ctx->encap_info->signal_number, caching_value);
+               if (IOTCON_ERROR_NONE != ret) {
+                       ERR("_ocprocess_response_signal() Fail(%d)", ret);
+                       OCRepPayloadDestroy(ctx->oic_payload);
+                       free(ctx);
+                       return ret;
+               }
+       }
+
+       OCRepPayloadDestroy(ctx->oic_payload);
        free(ctx);
 
-       return ret;
+       return IOTCON_ERROR_NONE;
 }
 
 
-OCStackApplicationResult icd_ioty_ocprocess_get_cb(void *ctx, OCDoHandle handle,
+OCStackApplicationResult icd_ioty_ocprocess_encap_get_cb(void *ctx, OCDoHandle handle,
                OCClientResponse *resp)
 {
        FN_CALL;
-       int ret, res;
-       OCStackResult result;
-       GVariantBuilder *options;
-       struct icd_get_context *get_ctx;
+       int ret;
+       icd_encap_info_s *encap_info = ctx;
+       struct icd_encap_context *encap_ctx;
 
        RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
 
-       if (NULL == resp->resJSONPayload || '\0' == resp->resJSONPayload[0]) {
-               ERR("json payload is empty");
-               icd_ioty_get_complete_error(ctx, IOTCON_ERROR_IOTIVITY);
+       encap_ctx = calloc(1, sizeof(struct icd_encap_context));
+       if (NULL == encap_ctx) {
+               ERR("calloc() Fail(%d)", errno);
                return OC_STACK_DELETE_TRANSACTION;
        }
 
-       get_ctx = calloc(1, sizeof(struct icd_get_context));
-       if (NULL == get_ctx) {
-               ERR("calloc() Fail(%d)", errno);
-               icd_ioty_get_complete_error(ctx, IOTCON_ERROR_OUT_OF_MEMORY);
+       encap_ctx->ret = resp->result;
+       encap_ctx->oic_payload = OCRepPayloadClone((OCRepPayload*)resp->payload);
+       encap_ctx->encap_info = encap_info;
+
+       ret = _ocprocess_worker_start(_worker_encap_get_cb, encap_ctx);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("_ocprocess_worker_start() Fail(%d)", ret);
+               OCRepPayloadDestroy((OCRepPayload*)encap_ctx->oic_payload);
+               free(encap_ctx);
                return OC_STACK_DELETE_TRANSACTION;
        }
 
-       result = resp->result;
-       if (result == OC_STACK_OK) {
-               res = IOTCON_RESPONSE_RESULT_OK;
-               options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
-                               resp->numRcvdVendorSpecificHeaderOptions);
-       } else {
-               WARN("resp error(%d)", result);
-               res = IOTCON_RESPONSE_RESULT_ERROR;
-               options = NULL;
-       }
+       return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+static int _worker_encap_get(void *context)
+{
+       icd_encap_info_s *encap_info = context;
+
+       g_source_remove(encap_info->get_timer_id);
+       icd_ioty_encap_get(encap_info);
+       encap_info->get_timer_id = g_timeout_add_seconds(icd_ioty_encap_get_time_interval(),
+                       icd_ioty_encap_get, encap_info);
+
+       return IOTCON_ERROR_NONE;
+}
+
 
-       get_ctx->payload = strdup(resp->resJSONPayload);
-       get_ctx->res = res;
-       get_ctx->options = options;
-       get_ctx->invocation = ctx;
+OCStackApplicationResult icd_ioty_ocprocess_encap_observe_cb(void *ctx, OCDoHandle handle,
+               OCClientResponse *resp)
+{
+       FN_CALL;
+       int ret;
 
-       ret = _ocprocess_worker_start(_worker_get_cb, get_ctx);
+       RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
+
+       ret = _ocprocess_worker_start(_worker_encap_get, ctx);
        if (IOTCON_ERROR_NONE != ret) {
                ERR("_ocprocess_worker_start() Fail(%d)", ret);
-               icd_ioty_get_complete_error(ctx, ret);
-               free(get_ctx->payload);
-               g_variant_builder_unref(get_ctx->options);
-               free(get_ctx);
-               return OC_STACK_DELETE_TRANSACTION;
+               return OC_STACK_KEEP_TRANSACTION;
        }
 
-       /* DO NOT FREE get_ctx. It MUST be freed in the _worker_get_cb func */
-
-       return OC_STACK_DELETE_TRANSACTION;
+       return OC_STACK_KEEP_TRANSACTION;
 }
 
+
+OCStackApplicationResult icd_ioty_ocprocess_encap_presence_cb(void *ctx,
+               OCDoHandle handle, OCClientResponse *resp)
+{
+       FN_CALL;
+       int ret;
+       OCPresencePayload *payload = (OCPresencePayload*)resp->payload;
+
+       RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
+
+       if ((OC_STACK_OK == resp->result) && (OC_PRESENCE_TRIGGER_DELETE != payload->trigger))
+               return OC_STACK_KEEP_TRANSACTION;
+
+       ret = _ocprocess_worker_start(_worker_encap_get, ctx);
+       if (IOTCON_ERROR_NONE != ret) {
+               ERR("_ocprocess_worker_start() Fail(%d)", ret);
+               return OC_STACK_KEEP_TRANSACTION;
+       }
+
+       return OC_STACK_KEEP_TRANSACTION;
+}