2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
24 #include <ocpayload.h>
29 #include "icd-payload.h"
32 #include "icd-ioty-type.h"
33 #include "icd-ioty-ocprocess.h"
35 static int icd_ioty_alive;
37 typedef int (*_ocprocess_cb)(void *user_data);
39 struct icd_ioty_worker
46 struct icd_req_context {
47 int64_t signal_number;
52 OCRequestHandle request_h;
53 OCResourceHandle resource_h;
55 GVariantBuilder *options;
56 GVariantBuilder *query;
61 struct icd_find_context {
62 int64_t signal_number;
69 struct icd_crud_context {
73 GVariantBuilder *options;
74 GDBusMethodInvocation *invocation;
78 struct icd_info_context {
79 int64_t signal_number;
86 struct icd_tizen_info_context {
87 OCRequestHandle request_h;
88 OCResourceHandle resource_h;
89 GDBusMethodInvocation *invocation;
93 struct icd_observe_context {
94 int64_t signal_number;
99 GVariantBuilder *options;
103 struct icd_presence_context {
108 iotcon_presence_trigger_e trigger;
113 void icd_ioty_ocprocess_stop()
119 static void* _ocprocess_worker_thread(void *data)
122 struct icd_ioty_worker *worker = data;
125 ERR("worker is NULL");
129 ret = worker->cb(worker->ctx);
130 if (IOTCON_ERROR_NONE != ret)
131 ERR("cb() Fail(%d)", ret);
133 /* worker was allocated from _ocprocess_worker_start() */
136 /* GCC warning happen if use g_thread_exit() */
141 static int _ocprocess_worker_start(_ocprocess_cb cb, void *ctx)
145 struct icd_ioty_worker *worker;
147 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
149 worker = calloc(1, sizeof(struct icd_ioty_worker));
150 if (NULL == worker) {
151 ERR("calloc() Fail(%d)", errno);
152 return IOTCON_ERROR_OUT_OF_MEMORY;
158 /* TODO : consider thread pool mechanism */
159 thread = g_thread_try_new("worker_thread", _ocprocess_worker_thread, worker, &error);
160 if (NULL == thread) {
161 ERR("g_thread_try_new() Fail(%s)", error->message);
164 return IOTCON_ERROR_SYSTEM;
167 /* DO NOT join thread. It was already detached by calling g_thread_unref() */
168 g_thread_unref(thread);
170 /* DO NOT FREE worker. It MUST be freed in the _ocprocess_worker_thread() */
172 return IOTCON_ERROR_NONE;
176 static int _ocprocess_response_signal(const char *dest, const char *signal_prefix,
177 int64_t signal_number, GVariant *value)
180 char signal_name[IC_DBUS_SIGNAL_LENGTH] = {0};
182 ret = snprintf(signal_name, sizeof(signal_name), "%s_%llx", signal_prefix, signal_number);
183 if (ret <= 0 || sizeof(signal_name) <= ret) {
184 ERR("snprintf() Fail(%d)", ret);
185 return IOTCON_ERROR_IO_ERROR;
188 ret = icd_dbus_emit_signal(dest, signal_name, value);
189 if (IOTCON_ERROR_NONE != ret) {
190 ERR("icd_dbus_emit_signal() Fail(%d)", ret);
194 return IOTCON_ERROR_NONE;
198 static inline GVariantBuilder* _ocprocess_parse_header_options(
199 OCHeaderOption *oic_option, int option_size)
202 GVariantBuilder *options;
204 options = g_variant_builder_new(G_VARIANT_TYPE("a(qs)"));
205 for (i = 0; i < option_size; i++) {
206 g_variant_builder_add(options, "(qs)", oic_option[i].optionID,
207 oic_option[i].optionData);
213 static int _ioty_oic_action_to_ioty_action(int oic_action)
217 switch (oic_action) {
218 case OC_OBSERVE_REGISTER:
219 action = IOTCON_OBSERVE_REGISTER;
221 case OC_OBSERVE_DEREGISTER:
222 action = IOTCON_OBSERVE_DEREGISTER;
224 case OC_OBSERVE_NO_OPTION:
226 ERR("Invalid action (%d)", oic_action);
227 action = IOTCON_OBSERVE_NO_TYPE;
233 static void _icd_req_context_free(struct icd_req_context *ctx)
237 g_variant_unref(ctx->payload);
238 g_variant_builder_unref(ctx->options);
239 g_variant_builder_unref(ctx->query);
245 static int _worker_req_handler(void *context)
250 GVariantBuilder payload_builder;
251 struct icd_req_context *ctx = context;
253 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
255 g_variant_builder_init(&payload_builder, G_VARIANT_TYPE("av"));
257 g_variant_builder_add(&payload_builder, "v", ctx->payload);
261 ret = icd_ioty_get_host_address(ctx->dev_addr, &host_address, &conn_type);
262 if (IOTCON_ERROR_NONE != ret) {
263 ERR("icd_ioty_get_host_address() Fail(%d)", ret);
264 g_variant_builder_clear(&payload_builder);
265 _icd_req_context_free(ctx);
269 value = g_variant_new("(siia(qs)a(ss)iiavxx)",
278 ICD_POINTER_TO_INT64(ctx->request_h),
279 ICD_POINTER_TO_INT64(ctx->resource_h));
283 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_REQUEST_HANDLER,
284 ctx->signal_number, value);
285 if (IOTCON_ERROR_NONE != ret)
286 ERR("_ocprocess_response_signal() Fail(%d)", ret);
288 _icd_req_context_free(ctx);
294 OCEntityHandlerResult icd_ioty_ocprocess_req_handler(OCEntityHandlerFlag flag,
295 OCEntityHandlerRequest *request, void *user_data)
299 int64_t signal_number;
300 char *query_str, *query_key, *query_value;
301 char *token, *save_ptr1, *save_ptr2;
302 char *bus_name = NULL;
303 struct icd_req_context *req_ctx;
306 RETV_IF(NULL == request, OC_EH_ERROR);
308 req_ctx = calloc(1, sizeof(struct icd_req_context));
309 if (NULL == req_ctx) {
310 ERR("calloc() Fail(%d)", errno);
315 req_ctx->request_h = request->requestHandle;
316 req_ctx->resource_h = request->resource;
318 ret = icd_dbus_client_list_get_info(req_ctx->resource_h, &signal_number, &bus_name);
319 if (IOTCON_ERROR_NONE != ret) {
320 ERR("icd_dbus_client_list_get_info() Fail(%d)", ret);
325 /* signal number & bus_name */
326 req_ctx->signal_number = signal_number;
327 req_ctx->bus_name = bus_name;
329 dev_addr = calloc(1, sizeof(OCDevAddr));
330 if (NULL == dev_addr) {
331 ERR("calloc() Fail(%d)", errno);
332 free(req_ctx->bus_name);
336 memcpy(dev_addr, &request->devAddr, sizeof(OCDevAddr));
337 req_ctx->dev_addr = dev_addr;
340 if (OC_REQUEST_FLAG & flag) {
341 switch (request->method) {
343 req_ctx->request_type = IOTCON_REQUEST_GET;
344 req_ctx->payload = NULL;
347 req_ctx->request_type = IOTCON_REQUEST_PUT;
348 req_ctx->payload = icd_payload_to_gvariant(request->payload);
351 req_ctx->request_type = IOTCON_REQUEST_POST;
352 req_ctx->payload = icd_payload_to_gvariant(request->payload);
355 req_ctx->request_type = IOTCON_REQUEST_DELETE;
356 req_ctx->payload = NULL;
359 free(req_ctx->dev_addr);
360 free(req_ctx->bus_name);
366 if (OC_OBSERVE_FLAG & flag) {
367 /* observation info*/
368 req_ctx->observe_id = request->obsInfo.obsId;
369 req_ctx->observe_type = _ioty_oic_action_to_ioty_action(request->obsInfo.action);
371 req_ctx->observe_type = IOTCON_OBSERVE_NO_TYPE;
375 req_ctx->options = _ocprocess_parse_header_options(
376 request->rcvdVendorSpecificHeaderOptions,
377 request->numRcvdVendorSpecificHeaderOptions);
380 req_ctx->query = g_variant_builder_new(G_VARIANT_TYPE("a(ss)"));
381 query_str = request->query;
382 while ((token = strtok_r(query_str, "&;", &save_ptr1))) {
383 while ((query_key = strtok_r(token, "=", &save_ptr2))) {
385 query_value = strtok_r(token, "=", &save_ptr2);
386 if (NULL == query_value)
389 g_variant_builder_add(req_ctx->query, "(ss)", query_key, query_value);
394 ret = _ocprocess_worker_start(_worker_req_handler, req_ctx);
395 if (IOTCON_ERROR_NONE != ret) {
396 ERR("_ocprocess_worker_start() Fail(%d)", ret);
397 _icd_req_context_free(req_ctx);
401 /* DO NOT FREE req_ctx. It MUST be freed in the _worker_req_handler func */
407 gpointer icd_ioty_ocprocess_thread(gpointer data)
410 OCStackResult result;
411 const struct timespec delay = {0, 10 * 1000 * 1000}; /* 10 ms */
414 while (icd_ioty_alive) {
415 icd_ioty_csdk_lock();
416 result = OCProcess();
417 icd_ioty_csdk_unlock();
418 if (OC_STACK_OK != result) {
419 ERR("OCProcess() Fail(%d)", result);
423 /* TODO : Current '10ms' is not proven sleep time. Revise the time after test.
424 * Or recommend changes to event driven architecture */
425 nanosleep(&delay, NULL);
432 static int _worker_find_cb(void *context)
436 struct icd_find_context *ctx = context;
438 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
440 for (i = 0; ctx->payload[i]; i++) {
441 value = g_variant_new("(vi)", ctx->payload[i], ctx->conn_type);
442 /* TODO : If one device has multi resources, it comes as bulk data.
443 * To reduce the number of emit_signal, let's send signal only one time for one device.
444 * for ex, client list. */
445 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_FOUND_RESOURCE,
446 ctx->signal_number, value);
447 if (IOTCON_ERROR_NONE != ret) {
448 ERR("_ocprocess_response_signal() Fail(%d)", ret);
449 g_variant_unref(value);
454 /* ctx was allocated from icd_ioty_ocprocess_find_cb() */
462 OCStackApplicationResult icd_ioty_ocprocess_find_cb(void *ctx, OCDoHandle handle,
463 OCClientResponse *resp)
466 struct icd_find_context *find_ctx;
467 icd_sig_ctx_s *sig_context = ctx;
469 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
470 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
471 if (NULL == resp->payload)
472 /* normal case : payload COULD be NULL */
473 return OC_STACK_KEEP_TRANSACTION;
474 RETVM_IF(PAYLOAD_TYPE_DISCOVERY != resp->payload->type,
475 OC_STACK_KEEP_TRANSACTION, "Invalid payload type(%d)", resp->payload->type);
477 find_ctx = calloc(1, sizeof(struct icd_find_context));
478 if (NULL == find_ctx) {
479 ERR("calloc() Fail(%d)", errno);
480 return OC_STACK_KEEP_TRANSACTION;
483 find_ctx->signal_number = sig_context->signal_number;
484 find_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
485 find_ctx->payload = icd_payload_res_to_gvariant(resp->payload, &resp->devAddr);
486 find_ctx->conn_type = icd_ioty_transport_flag_to_conn_type(resp->devAddr.adapter,
487 resp->devAddr.flags);
489 ret = _ocprocess_worker_start(_worker_find_cb, find_ctx);
490 if (IOTCON_ERROR_NONE != ret) {
491 ERR("_ocprocess_worker_start() Fail(%d)", ret);
492 free(find_ctx->bus_name);
493 ic_utils_gvariant_array_free(find_ctx->payload);
495 return OC_STACK_KEEP_TRANSACTION;
498 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
499 /* DO NOT FREE find_ctx. It MUST be freed in the _worker_find_cb func */
501 return OC_STACK_KEEP_TRANSACTION;
505 static int _worker_crud_cb(void *context)
508 struct icd_crud_context *ctx = context;
510 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
512 if (ICD_CRUD_DELETE == ctx->crud_type)
513 value = g_variant_new("(a(qs)i)", ctx->options, ctx->res);
515 value = g_variant_new("(a(qs)vi)", ctx->options, ctx->payload, ctx->res);
516 icd_ioty_complete(ctx->crud_type, ctx->invocation, value);
518 /* ctx was allocated from icd_ioty_ocprocess_xxx_cb() */
519 g_variant_builder_unref(ctx->options);
522 return IOTCON_ERROR_NONE;
526 static int _worker_info_cb(void *context)
529 const char *signal_prefix = NULL;
530 struct icd_info_context *ctx = context;
532 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
534 if (ICD_DEVICE_INFO == ctx->info_type)
535 signal_prefix = IC_DBUS_SIGNAL_DEVICE;
536 else if (ICD_PLATFORM_INFO == ctx->info_type)
537 signal_prefix = IC_DBUS_SIGNAL_PLATFORM;
539 ret = _ocprocess_response_signal(ctx->bus_name, signal_prefix, ctx->signal_number,
541 if (IOTCON_ERROR_NONE != ret)
542 ERR("_ocprocess_response_signal() Fail(%d)", ret);
544 /* ctx was allocated from icd_ioty_ocprocess_info_cb() */
552 static int _ocprocess_worker(_ocprocess_cb cb, int type, OCPayload *payload, int res,
553 GVariantBuilder *options, void *ctx)
556 struct icd_crud_context *crud_ctx;
558 crud_ctx = calloc(1, sizeof(struct icd_crud_context));
559 if (NULL == crud_ctx) {
560 ERR("calloc() Fail(%d)", errno);
561 return IOTCON_ERROR_OUT_OF_MEMORY;
564 crud_ctx->crud_type = type;
565 crud_ctx->payload = icd_payload_to_gvariant(payload);
567 crud_ctx->options = options;
568 crud_ctx->invocation = ctx;
570 ret = _ocprocess_worker_start(cb, crud_ctx);
571 if (IOTCON_ERROR_NONE != ret) {
572 ERR("_ocprocess_worker_start() Fail(%d)", ret);
573 if (crud_ctx->payload)
574 g_variant_unref(crud_ctx->payload);
575 g_variant_builder_unref(crud_ctx->options);
579 /* DO NOT FREE crud_ctx. It MUST be freed in the _worker_crud_cb func */
584 static int _ocprocess_parse_oic_result(OCStackResult result)
590 res = IOTCON_RESPONSE_OK;
592 case OC_STACK_RESOURCE_CREATED:
593 res = IOTCON_RESPONSE_RESOURCE_CREATED;
595 case OC_STACK_RESOURCE_DELETED:
596 res = IOTCON_RESPONSE_RESULT_DELETED;
598 case OC_STACK_UNAUTHORIZED_REQ:
599 res = IOTCON_RESPONSE_FORBIDDEN;
602 WARN("response error(%d)", result);
603 res = IOTCON_RESPONSE_ERROR;
611 OCStackApplicationResult icd_ioty_ocprocess_get_cb(void *ctx, OCDoHandle handle,
612 OCClientResponse *resp)
616 GVariantBuilder *options;
618 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
620 if (NULL == resp->payload) {
621 ERR("payload is empty");
622 icd_ioty_complete_error(ICD_CRUD_GET, ctx, IOTCON_ERROR_IOTIVITY);
623 return OC_STACK_DELETE_TRANSACTION;
626 res = _ocprocess_parse_oic_result(resp->result);
628 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
629 resp->numRcvdVendorSpecificHeaderOptions);
631 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_GET, resp->payload, res,
633 if (IOTCON_ERROR_NONE != ret) {
634 ERR("_ocprocess_worker() Fail(%d)", ret);
635 icd_ioty_complete_error(ICD_CRUD_GET, ctx, ret);
636 return OC_STACK_DELETE_TRANSACTION;
639 return OC_STACK_DELETE_TRANSACTION;
643 OCStackApplicationResult icd_ioty_ocprocess_put_cb(void *ctx, OCDoHandle handle,
644 OCClientResponse *resp)
648 GVariantBuilder *options;
650 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
652 if (NULL == resp->payload) {
653 ERR("payload is empty");
654 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, IOTCON_ERROR_IOTIVITY);
655 return OC_STACK_DELETE_TRANSACTION;
658 res = _ocprocess_parse_oic_result(resp->result);
660 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
661 resp->numRcvdVendorSpecificHeaderOptions);
663 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_PUT, resp->payload, res,
665 if (IOTCON_ERROR_NONE != ret) {
666 ERR("_ocprocess_worker() Fail(%d)", ret);
667 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, ret);
668 return OC_STACK_DELETE_TRANSACTION;
671 return OC_STACK_DELETE_TRANSACTION;
675 OCStackApplicationResult icd_ioty_ocprocess_post_cb(void *ctx, OCDoHandle handle,
676 OCClientResponse *resp)
680 GVariantBuilder *options;
682 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
684 if (NULL == resp->payload) {
685 ERR("payload is empty");
686 icd_ioty_complete_error(ICD_CRUD_POST, ctx, IOTCON_ERROR_IOTIVITY);
687 return OC_STACK_DELETE_TRANSACTION;
690 res = _ocprocess_parse_oic_result(resp->result);
692 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
693 resp->numRcvdVendorSpecificHeaderOptions);
695 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_POST, resp->payload, res,
697 if (IOTCON_ERROR_NONE != ret) {
698 ERR("_ocprocess_worker() Fail(%d)", ret);
699 icd_ioty_complete_error(ICD_CRUD_POST, ctx, ret);
700 return OC_STACK_DELETE_TRANSACTION;
703 return OC_STACK_DELETE_TRANSACTION;
707 OCStackApplicationResult icd_ioty_ocprocess_delete_cb(void *ctx, OCDoHandle handle,
708 OCClientResponse *resp)
712 GVariantBuilder *options;
714 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
716 if (NULL == resp->payload) {
717 ERR("payload is empty");
718 icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, IOTCON_ERROR_IOTIVITY);
719 return OC_STACK_DELETE_TRANSACTION;
722 res = _ocprocess_parse_oic_result(resp->result);
724 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
725 resp->numRcvdVendorSpecificHeaderOptions);
727 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_DELETE, NULL, res, options, ctx);
728 if (IOTCON_ERROR_NONE != ret) {
729 ERR("_ocprocess_worker() Fail(%d)", ret);
730 icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, ret);
731 return OC_STACK_DELETE_TRANSACTION;
734 return OC_STACK_DELETE_TRANSACTION;
738 static int _worker_observe_cb(void *context)
742 struct icd_observe_context *ctx = context;
744 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
746 value = g_variant_new("(a(qs)vii)", ctx->options, ctx->payload, ctx->res,
749 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_OBSERVE,
750 ctx->signal_number, value);
751 if (IOTCON_ERROR_NONE != ret)
752 ERR("_ocprocess_response_signal() Fail(%d)", ret);
754 /* ctx was allocated from icd_ioty_ocprocess_observe_cb() */
756 g_variant_builder_unref(ctx->options);
763 static void _observe_cb_response_error(const char *dest,
764 int64_t signal_number, int ret_val)
769 GVariantBuilder options;
771 g_variant_builder_init(&options, G_VARIANT_TYPE("a(qs)"));
772 payload = icd_payload_representation_empty_gvariant();
774 value = g_variant_new("(a(qs)vii)", &options, payload, ret_val, 0);
776 ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_OBSERVE, signal_number, value);
777 if (IOTCON_ERROR_NONE != ret)
778 ERR("_ocprocess_response_signal() Fail(%d)", ret);
782 OCStackApplicationResult icd_ioty_ocprocess_observe_cb(void *ctx,
783 OCDoHandle handle, OCClientResponse *resp)
786 GVariantBuilder *options;
787 struct icd_observe_context *observe_ctx;
788 icd_sig_ctx_s *sig_context = ctx;
790 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
792 if (NULL == resp->payload) {
793 ERR("payload is empty");
794 _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number,
795 IOTCON_ERROR_IOTIVITY);
796 return OC_STACK_KEEP_TRANSACTION;
799 observe_ctx = calloc(1, sizeof(struct icd_observe_context));
800 if (NULL == observe_ctx) {
801 ERR("calloc() Fail(%d)", errno);
802 _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number,
803 IOTCON_ERROR_OUT_OF_MEMORY);
804 return OC_STACK_KEEP_TRANSACTION;
807 res = _ocprocess_parse_oic_result(resp->result);
809 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
810 resp->numRcvdVendorSpecificHeaderOptions);
812 observe_ctx->payload = icd_payload_to_gvariant(resp->payload);
813 observe_ctx->signal_number = sig_context->signal_number;
814 observe_ctx->res = res;
815 observe_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
816 observe_ctx->options = options;
818 ret = _ocprocess_worker_start(_worker_observe_cb, observe_ctx);
819 if (IOTCON_ERROR_NONE != ret) {
820 ERR("_ocprocess_worker_start() Fail(%d)", ret);
821 _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number, ret);
822 free(observe_ctx->bus_name);
823 if (observe_ctx->payload)
824 g_variant_unref(observe_ctx->payload);
825 g_variant_builder_unref(observe_ctx->options);
827 return OC_STACK_KEEP_TRANSACTION;
830 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
831 /* DO NOT FREE observe_ctx. It MUST be freed in the _worker_observe_cb func */
833 return OC_STACK_KEEP_TRANSACTION;
837 static int _worker_presence_cb(void *context)
842 GVariant *value, *value2;
843 int ret = IOTCON_ERROR_NONE;
844 struct icd_presence_context *ctx = context;
846 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
848 ret = icd_ioty_get_host_address(ctx->dev_addr, &host_address, &conn_type);
849 if (IOTCON_ERROR_NONE != ret) {
850 ERR("icd_ioty_get_host_address() Fail(%d)", ret);
851 free(ctx->resource_type);
857 value = g_variant_new("(iusiis)", ctx->result, ctx->nonce, host_address, conn_type,
858 ctx->trigger, ic_utils_dbus_encode_str(ctx->resource_type));
859 value2 = g_variant_ref(value);
863 ret = _ocprocess_response_signal(NULL, IC_DBUS_SIGNAL_PRESENCE,
864 ICD_POINTER_TO_INT64(ctx->handle), value);
865 if (IOTCON_ERROR_NONE != ret)
866 ERR("_ocprocess_response_signal() Fail(%d)", ret);
868 handle = icd_ioty_presence_table_get_handle(ICD_MULTICAST_ADDRESS);
869 if (handle && (handle != ctx->handle)) {
870 ret = _ocprocess_response_signal(NULL, IC_DBUS_SIGNAL_PRESENCE,
871 ICD_POINTER_TO_INT64(handle), value2);
872 if (IOTCON_ERROR_NONE != ret)
873 ERR("_ocprocess_response_signal() Fail(%d)", ret);
875 g_variant_unref(value2);
878 /* ctx was allocated from icd_ioty_ocprocess_presence_cb() */
879 free(ctx->resource_type);
887 static void _presence_cb_response_error(OCDoHandle handle, int ret_val)
892 GVariant *value, *value2;
894 value = g_variant_new("(iusiis)", ret_val, 0, IC_STR_NULL, IOTCON_CONNECTIVITY_ALL,
895 IOTCON_PRESENCE_RESOURCE_CREATED, IC_STR_NULL);
896 value2 = g_variant_ref(value);
898 ret = _ocprocess_response_signal(NULL, IC_DBUS_SIGNAL_PRESENCE,
899 ICD_POINTER_TO_INT64(handle), value);
900 if (IOTCON_ERROR_NONE != ret)
901 ERR("_ocprocess_response_signal() Fail(%d)", ret);
903 handle2 = icd_ioty_presence_table_get_handle(ICD_MULTICAST_ADDRESS);
904 if (handle2 && (handle2 != handle)) {
905 ret = _ocprocess_response_signal(NULL, IC_DBUS_SIGNAL_PRESENCE,
906 ICD_POINTER_TO_INT64(handle), value2);
907 if (IOTCON_ERROR_NONE != ret)
908 ERR("_ocprocess_response_signal() Fail(%d)", ret);
910 g_variant_unref(value2);
915 static int _presence_trigger_to_ioty_trigger(OCPresenceTrigger src,
916 iotcon_presence_trigger_e *dest)
918 RETV_IF(NULL == dest, IOTCON_ERROR_INVALID_PARAMETER);
921 case OC_PRESENCE_TRIGGER_CREATE:
922 *dest = IOTCON_PRESENCE_RESOURCE_CREATED;
924 case OC_PRESENCE_TRIGGER_CHANGE:
925 *dest = IOTCON_PRESENCE_RESOURCE_UPDATED;
927 case OC_PRESENCE_TRIGGER_DELETE:
928 *dest = IOTCON_PRESENCE_RESOURCE_DESTROYED;
931 ERR("Invalid trigger(%d)", src);
932 return IOTCON_ERROR_INVALID_PARAMETER;
935 return IOTCON_ERROR_NONE;
939 OCStackApplicationResult icd_ioty_ocprocess_presence_cb(void *ctx, OCDoHandle handle,
940 OCClientResponse *resp)
945 OCPresencePayload *payload;
946 struct icd_presence_context *presence_ctx;
948 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
950 presence_ctx = calloc(1, sizeof(struct icd_presence_context));
951 if (NULL == presence_ctx) {
952 ERR("calloc() Fail(%d)", errno);
953 _presence_cb_response_error(handle, IOTCON_ERROR_OUT_OF_MEMORY);
954 return OC_STACK_KEEP_TRANSACTION;
957 dev_addr = calloc(1, sizeof(OCDevAddr));
958 if (NULL == dev_addr) {
959 ERR("calloc() Fail(%d)", errno);
960 _presence_cb_response_error(handle, IOTCON_ERROR_OUT_OF_MEMORY);
962 return OC_STACK_KEEP_TRANSACTION;
964 memcpy(dev_addr, &resp->devAddr, sizeof(OCDevAddr));
966 payload = (OCPresencePayload*)resp->payload;
968 switch (resp->result) {
970 presence_ctx->result = IOTCON_PRESENCE_OK;
971 ret = _presence_trigger_to_ioty_trigger(payload->trigger, &presence_ctx->trigger);
972 if (IOTCON_ERROR_NONE != ret) {
973 ERR("_presence_trigger_to_ioty_trigger() Fail(%d)", ret);
974 _presence_cb_response_error(handle, ret);
976 return OC_STACK_KEEP_TRANSACTION;
979 case OC_STACK_PRESENCE_STOPPED:
980 presence_ctx->result = IOTCON_PRESENCE_STOPPED;
982 case OC_STACK_PRESENCE_TIMEOUT:
983 presence_ctx->result = IOTCON_PRESENCE_TIMEOUT;
987 DBG("Presence error(%d)", resp->result);
988 presence_ctx->result = IOTCON_ERROR_IOTIVITY;
991 presence_ctx->handle = handle;
992 presence_ctx->nonce = resp->sequenceNumber;
993 presence_ctx->dev_addr = dev_addr;
995 if (payload->resourceType)
996 presence_ctx->resource_type = strdup(payload->resourceType);
998 ret = _ocprocess_worker_start(_worker_presence_cb, presence_ctx);
999 if (IOTCON_ERROR_NONE != ret) {
1000 ERR("_ocprocess_worker_start() Fail(%d)", ret);
1001 _presence_cb_response_error(handle, ret);
1002 free(presence_ctx->resource_type);
1003 free(presence_ctx->dev_addr);
1005 return OC_STACK_KEEP_TRANSACTION;
1008 /* DO NOT FREE presence_ctx. It MUST be freed in the _worker_presence_cb func */
1010 return OC_STACK_KEEP_TRANSACTION;
1014 OCStackApplicationResult icd_ioty_ocprocess_info_cb(void *ctx, OCDoHandle handle,
1015 OCClientResponse *resp)
1019 struct icd_info_context *info_ctx;
1020 icd_sig_ctx_s *sig_context = ctx;
1022 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
1023 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
1024 RETV_IF(NULL == resp->payload, OC_STACK_KEEP_TRANSACTION);
1026 if (PAYLOAD_TYPE_DEVICE == resp->payload->type)
1027 info_type = ICD_DEVICE_INFO;
1028 else if (PAYLOAD_TYPE_PLATFORM == resp->payload->type)
1029 info_type = ICD_PLATFORM_INFO;
1031 return OC_STACK_KEEP_TRANSACTION;
1033 info_ctx = calloc(1, sizeof(struct icd_info_context));
1034 if (NULL == info_ctx) {
1035 ERR("calloc() Fail(%d)", errno);
1036 return OC_STACK_KEEP_TRANSACTION;
1039 info_ctx->info_type = info_type;
1040 info_ctx->payload = icd_payload_to_gvariant(resp->payload);
1041 info_ctx->signal_number = sig_context->signal_number;
1042 info_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
1044 ret = _ocprocess_worker_start(_worker_info_cb, info_ctx);
1045 if (IOTCON_ERROR_NONE != ret) {
1046 ERR("_ocprocess_worker_start() Fail(%d)", ret);
1047 free(info_ctx->bus_name);
1048 if (info_ctx->payload)
1049 g_variant_unref(info_ctx->payload);
1051 return OC_STACK_KEEP_TRANSACTION;
1054 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
1055 /* DO NOT FREE info_ctx. It MUST be freed in the _worker_info_cb func */
1057 return OC_STACK_KEEP_TRANSACTION;
1061 static int _worker_tizen_info_handler(void *context)
1065 char *tizen_device_id;
1066 OCStackResult result;
1067 OCRepPayload *payload;
1068 OCEntityHandlerResponse response = {0};
1069 struct icd_tizen_info_context *ctx = context;
1071 response.requestHandle = ctx->request_h;
1072 response.resourceHandle = ctx->resource_h;
1073 response.ehResult = OC_EH_OK;
1075 /* Get Tizen Info */
1076 ret = icd_ioty_tizen_info_get_property(&device_name, &tizen_device_id);
1077 if (IOTCON_ERROR_NONE != ret) {
1078 ERR("icd_ioty_tizen_info_get_property() Fail(%d)", ret);
1079 response.ehResult = OC_EH_ERROR;
1083 payload = OCRepPayloadCreate();
1084 OCRepPayloadSetUri(payload, ICD_IOTY_TIZEN_INFO_URI);
1085 OCRepPayloadAddResourceType(payload, ICD_IOTY_TIZEN_INFO_TYPE);
1086 OCRepPayloadAddInterface(payload, IC_INTERFACE_DEFAULT);
1088 OCRepPayloadSetPropString(payload, ICD_IOTY_TIZEN_INFO_DEVICE_NAME,
1089 ic_utils_dbus_encode_str(device_name));
1090 OCRepPayloadSetPropString(payload, ICD_IOTY_TIZEN_INFO_TIZEN_DEVICE_ID,
1091 ic_utils_dbus_encode_str(tizen_device_id));
1092 response.payload = (OCPayload*)payload;
1094 icd_ioty_csdk_lock();
1095 result = OCDoResponse(&response);
1096 icd_ioty_csdk_unlock();
1098 if (OC_STACK_OK != result) {
1099 ERR("OCDoResponse() Fail(%d)", result);
1101 return IOTCON_ERROR_IOTIVITY;
1105 return IOTCON_ERROR_NONE;
1109 OCEntityHandlerResult icd_ioty_ocprocess_tizen_info_handler(OCEntityHandlerFlag flag,
1110 OCEntityHandlerRequest *request, void *user_data)
1113 struct icd_tizen_info_context *tizen_info_ctx;
1115 if ((0 == (OC_REQUEST_FLAG & flag)) || (OC_REST_GET != request->method)) {
1116 ERR("Prohibited Action");
1117 return OC_EH_FORBIDDEN;
1120 tizen_info_ctx = calloc(1, sizeof(struct icd_tizen_info_context));
1121 if (NULL == tizen_info_ctx) {
1122 ERR("calloc() Fail(%d)", errno);
1126 tizen_info_ctx->request_h = request->requestHandle;
1127 tizen_info_ctx->resource_h = request->resource;
1129 ret = _ocprocess_worker_start(_worker_tizen_info_handler, tizen_info_ctx);
1130 if (IOTCON_ERROR_NONE != ret) {
1131 ERR("_ocprocess_worker_start() Fail(%d)", ret);
1132 free(tizen_info_ctx);
1140 OCStackApplicationResult icd_ioty_ocprocess_get_tizen_info_cb(void *ctx,
1141 OCDoHandle handle, OCClientResponse *resp)
1145 char *tizen_device_id;
1146 GVariant *tizen_info;
1147 OCRepPayload *payload;
1148 OCRepPayloadValue *val;
1150 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
1152 if (NULL == resp->payload) {
1153 ERR("payload is empty");
1154 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1155 return OC_STACK_DELETE_TRANSACTION;
1158 payload = (OCRepPayload*)resp->payload;
1159 val = payload->values;
1161 ERR("Invalid payload");
1162 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1163 return OC_STACK_DELETE_TRANSACTION;
1165 device_name = val->str;
1169 ERR("Invalid Payload");
1170 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1171 return OC_STACK_DELETE_TRANSACTION;
1174 tizen_device_id = val->str;
1176 if (OC_STACK_OK == resp->result)
1177 res = IOTCON_RESPONSE_OK;
1179 res = IOTCON_RESPONSE_ERROR;
1181 tizen_info = g_variant_new("(ssi)", device_name, tizen_device_id, res);
1183 icd_ioty_complete(ICD_TIZEN_INFO, ctx, tizen_info);
1185 return OC_STACK_DELETE_TRANSACTION;