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.
18 #include <unistd.h> /* for usleep() */
23 #include <ocpayload.h>
28 #include "icd-payload.h"
31 #include "icd-ioty-type.h"
32 #include "icd-ioty-ocprocess.h"
34 static int icd_ioty_alive;
36 typedef int (*_ocprocess_cb)(void *user_data);
38 struct icd_ioty_worker
45 struct icd_req_context {
46 unsigned int signal_number;
51 OCRequestHandle request_h;
52 OCResourceHandle resource_h;
54 GVariantBuilder *options;
55 GVariantBuilder *query;
60 struct icd_find_context {
61 unsigned int signal_number;
68 struct icd_crud_context {
72 GVariantBuilder *options;
73 GDBusMethodInvocation *invocation;
77 struct icd_info_context {
78 unsigned int signal_number;
85 struct icd_tizen_info_context {
86 OCRequestHandle request_h;
87 OCResourceHandle resource_h;
88 GDBusMethodInvocation *invocation;
92 struct icd_observe_context {
93 unsigned int signal_number;
98 GVariantBuilder *options;
102 struct icd_presence_context {
103 unsigned int signal_number;
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 unsigned int signal_number, GVariant *value)
180 char signal_name[IC_DBUS_SIGNAL_LENGTH] = {0};
182 ret = snprintf(signal_name, sizeof(signal_name), "%s_%u", 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_OPTION;
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)
249 int ret, conn_type, action;
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 action = _ioty_oic_action_to_ioty_action(ctx->observe_action);
271 value = g_variant_new("(siia(qs)a(ss)iiavxx)",
280 ICD_POINTER_TO_INT64(ctx->request_h),
281 ICD_POINTER_TO_INT64(ctx->resource_h));
285 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_REQUEST_HANDLER,
286 ctx->signal_number, value);
287 if (IOTCON_ERROR_NONE != ret)
288 ERR("_ocprocess_response_signal() Fail(%d)", ret);
290 _icd_req_context_free(ctx);
296 OCEntityHandlerResult icd_ioty_ocprocess_req_handler(OCEntityHandlerFlag flag,
297 OCEntityHandlerRequest *request, void *user_data)
301 unsigned int signal_number;
302 char *query_str, *query_key, *query_value;
303 char *token, *save_ptr1, *save_ptr2;
304 char *bus_name = NULL;
305 struct icd_req_context *req_ctx;
308 RETV_IF(NULL == request, OC_EH_ERROR);
310 req_ctx = calloc(1, sizeof(struct icd_req_context));
311 if (NULL == req_ctx) {
312 ERR("calloc() Fail(%d)", errno);
317 req_ctx->request_h = request->requestHandle;
318 req_ctx->resource_h = request->resource;
320 ret = icd_dbus_client_list_get_info(req_ctx->resource_h, &signal_number, &bus_name);
321 if (IOTCON_ERROR_NONE != ret) {
322 ERR("icd_dbus_client_list_get_info() Fail(%d)", ret);
327 /* signal number & bus_name */
328 req_ctx->signal_number = signal_number;
329 req_ctx->bus_name = bus_name;
331 dev_addr = calloc(1, sizeof(OCDevAddr));
332 if (NULL == dev_addr) {
333 ERR("calloc() Fail(%d)", errno);
337 memcpy(dev_addr, &request->devAddr, sizeof(OCDevAddr));
338 req_ctx->dev_addr = dev_addr;
341 if (OC_REQUEST_FLAG & flag) {
342 switch (request->method) {
344 req_ctx->types = IOTCON_REQUEST_GET;
345 req_ctx->payload = NULL;
347 if (OC_OBSERVE_FLAG & flag) {
348 req_ctx->types |= IOTCON_REQUEST_OBSERVE;
349 /* observation info*/
350 req_ctx->observe_id = request->obsInfo.obsId;
351 req_ctx->observe_action = request->obsInfo.action;
355 req_ctx->types = IOTCON_REQUEST_PUT;
356 req_ctx->payload = icd_payload_to_gvariant(request->payload);
359 req_ctx->types = IOTCON_REQUEST_POST;
360 req_ctx->payload = icd_payload_to_gvariant(request->payload);
363 req_ctx->types = IOTCON_REQUEST_DELETE;
364 req_ctx->payload = NULL;
367 free(req_ctx->bus_name);
374 req_ctx->options = _ocprocess_parse_header_options(
375 request->rcvdVendorSpecificHeaderOptions,
376 request->numRcvdVendorSpecificHeaderOptions);
379 req_ctx->query = g_variant_builder_new(G_VARIANT_TYPE("a(ss)"));
380 query_str = request->query;
381 while ((token = strtok_r(query_str, "&;", &save_ptr1))) {
382 while ((query_key = strtok_r(token, "=", &save_ptr2))) {
384 query_value = strtok_r(token, "=", &save_ptr2);
385 if (NULL == query_value)
388 g_variant_builder_add(req_ctx->query, "(ss)", query_key, query_value);
393 ret = _ocprocess_worker_start(_worker_req_handler, req_ctx);
394 if (IOTCON_ERROR_NONE != ret) {
395 ERR("_ocprocess_worker_start() Fail(%d)", ret);
396 _icd_req_context_free(req_ctx);
400 /* DO NOT FREE req_ctx. It MUST be freed in the _worker_req_handler func */
406 gpointer icd_ioty_ocprocess_thread(gpointer data)
409 OCStackResult result;
412 while (icd_ioty_alive) {
413 icd_ioty_csdk_lock();
414 result = OCProcess();
415 icd_ioty_csdk_unlock();
416 if (OC_STACK_OK != result) {
417 ERR("OCProcess() Fail(%d)", result);
421 /* TODO : SHOULD revise time or usleep */
429 static int _worker_find_cb(void *context)
433 struct icd_find_context *ctx = context;
435 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
437 for (i = 0; ctx->payload[i]; i++) {
438 value = g_variant_new("(vi)", ctx->payload[i], ctx->conn_type);
439 /* TODO : If one device has multi resources, it comes as bulk data.
440 * To reduce the number of emit_signal, let's send signal only one time for one device.
441 * for ex, client list. */
442 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_FOUND_RESOURCE,
443 ctx->signal_number, value);
444 if (IOTCON_ERROR_NONE != ret) {
445 ERR("_ocprocess_response_signal() Fail(%d)", ret);
446 g_variant_unref(value);
451 /* ctx was allocated from icd_ioty_ocprocess_find_cb() */
459 OCStackApplicationResult icd_ioty_ocprocess_find_cb(void *ctx, OCDoHandle handle,
460 OCClientResponse *resp)
463 struct icd_find_context *find_ctx;
464 icd_sig_ctx_s *sig_context = ctx;
466 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
467 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
468 if (NULL == resp->payload)
469 /* normal case : payload COULD be NULL */
470 return OC_STACK_KEEP_TRANSACTION;
471 RETVM_IF(PAYLOAD_TYPE_DISCOVERY != resp->payload->type,
472 OC_STACK_KEEP_TRANSACTION, "Invalid payload type(%d)", resp->payload->type);
474 find_ctx = calloc(1, sizeof(struct icd_find_context));
475 if (NULL == find_ctx) {
476 ERR("calloc() Fail(%d)", errno);
477 return OC_STACK_KEEP_TRANSACTION;
480 find_ctx->signal_number = sig_context->signal_number;
481 find_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
482 find_ctx->payload = icd_payload_res_to_gvariant(resp->payload, &resp->devAddr);
483 find_ctx->conn_type = icd_ioty_transport_flag_to_conn_type(resp->devAddr.adapter,
484 resp->devAddr.flags);
486 ret = _ocprocess_worker_start(_worker_find_cb, find_ctx);
487 if (IOTCON_ERROR_NONE != ret) {
488 ERR("_ocprocess_worker_start() Fail(%d)", ret);
489 free(find_ctx->bus_name);
490 ic_utils_gvariant_array_free(find_ctx->payload);
492 return OC_STACK_KEEP_TRANSACTION;
495 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
496 /* DO NOT FREE find_ctx. It MUST be freed in the _worker_find_cb func */
498 return OC_STACK_KEEP_TRANSACTION;
502 static int _worker_crud_cb(void *context)
505 struct icd_crud_context *ctx = context;
507 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
509 if (ICD_CRUD_DELETE == ctx->crud_type)
510 value = g_variant_new("(a(qs)i)", ctx->options, ctx->res);
512 value = g_variant_new("(a(qs)vi)", ctx->options, ctx->payload, ctx->res);
513 icd_ioty_complete(ctx->crud_type, ctx->invocation, value);
515 /* ctx was allocated from icd_ioty_ocprocess_xxx_cb() */
516 g_variant_builder_unref(ctx->options);
519 return IOTCON_ERROR_NONE;
523 static int _worker_info_cb(void *context)
526 const char *signal_prefix = NULL;
527 struct icd_info_context *ctx = context;
529 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
531 if (ICD_DEVICE_INFO == ctx->info_type)
532 signal_prefix = IC_DBUS_SIGNAL_DEVICE;
533 else if (ICD_PLATFORM_INFO == ctx->info_type)
534 signal_prefix = IC_DBUS_SIGNAL_PLATFORM;
536 ret = _ocprocess_response_signal(ctx->bus_name, signal_prefix, ctx->signal_number,
538 if (IOTCON_ERROR_NONE != ret)
539 ERR("_ocprocess_response_signal() Fail(%d)", ret);
541 /* ctx was allocated from icd_ioty_ocprocess_info_cb() */
549 static int _ocprocess_worker(_ocprocess_cb cb, int type, OCPayload *payload, int res,
550 GVariantBuilder *options, void *ctx)
553 struct icd_crud_context *crud_ctx;
555 crud_ctx = calloc(1, sizeof(struct icd_crud_context));
556 if (NULL == crud_ctx) {
557 ERR("calloc() Fail(%d)", errno);
558 return IOTCON_ERROR_OUT_OF_MEMORY;
561 crud_ctx->crud_type = type;
562 crud_ctx->payload = icd_payload_to_gvariant(payload);
564 crud_ctx->options = options;
565 crud_ctx->invocation = ctx;
567 ret = _ocprocess_worker_start(cb, crud_ctx);
568 if (IOTCON_ERROR_NONE != ret) {
569 ERR("_ocprocess_worker_start() Fail(%d)", ret);
570 if (crud_ctx->payload)
571 g_variant_unref(crud_ctx->payload);
572 g_variant_builder_unref(crud_ctx->options);
576 /* DO NOT FREE crud_ctx. It MUST be freed in the _worker_crud_cb func */
581 static int _ocprocess_parse_oic_result(OCStackResult result)
587 res = IOTCON_RESPONSE_RESULT_OK;
589 case OC_STACK_RESOURCE_CREATED:
590 res = IOTCON_RESPONSE_RESULT_RESOURCE_CREATED;
592 case OC_STACK_RESOURCE_DELETED:
593 res = IOTCON_RESPONSE_RESULT_RESOURCE_DELETED;
595 case OC_STACK_UNAUTHORIZED_REQ:
596 res = IOTCON_RESPONSE_RESULT_FORBIDDEN;
599 WARN("response error(%d)", result);
600 res = IOTCON_RESPONSE_RESULT_ERROR;
608 OCStackApplicationResult icd_ioty_ocprocess_get_cb(void *ctx, OCDoHandle handle,
609 OCClientResponse *resp)
613 GVariantBuilder *options;
615 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
617 if (NULL == resp->payload) {
618 ERR("payload is empty");
619 icd_ioty_complete_error(ICD_CRUD_GET, ctx, IOTCON_ERROR_IOTIVITY);
620 return OC_STACK_DELETE_TRANSACTION;
623 res = _ocprocess_parse_oic_result(resp->result);
625 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
626 resp->numRcvdVendorSpecificHeaderOptions);
628 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_GET, resp->payload, res,
630 if (IOTCON_ERROR_NONE != ret) {
631 ERR("_ocprocess_worker() Fail(%d)", ret);
632 icd_ioty_complete_error(ICD_CRUD_GET, ctx, ret);
633 return OC_STACK_DELETE_TRANSACTION;
636 return OC_STACK_DELETE_TRANSACTION;
640 OCStackApplicationResult icd_ioty_ocprocess_put_cb(void *ctx, OCDoHandle handle,
641 OCClientResponse *resp)
645 GVariantBuilder *options;
647 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
649 if (NULL == resp->payload) {
650 ERR("payload is empty");
651 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, IOTCON_ERROR_IOTIVITY);
652 return OC_STACK_DELETE_TRANSACTION;
655 res = _ocprocess_parse_oic_result(resp->result);
657 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
658 resp->numRcvdVendorSpecificHeaderOptions);
660 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_PUT, resp->payload, res,
662 if (IOTCON_ERROR_NONE != ret) {
663 ERR("_ocprocess_worker() Fail(%d)", ret);
664 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, ret);
665 return OC_STACK_DELETE_TRANSACTION;
668 return OC_STACK_DELETE_TRANSACTION;
672 OCStackApplicationResult icd_ioty_ocprocess_post_cb(void *ctx, OCDoHandle handle,
673 OCClientResponse *resp)
677 GVariantBuilder *options;
679 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
681 if (NULL == resp->payload) {
682 ERR("payload is empty");
683 icd_ioty_complete_error(ICD_CRUD_POST, ctx, IOTCON_ERROR_IOTIVITY);
684 return OC_STACK_DELETE_TRANSACTION;
687 res = _ocprocess_parse_oic_result(resp->result);
689 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
690 resp->numRcvdVendorSpecificHeaderOptions);
692 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_POST, resp->payload, res,
694 if (IOTCON_ERROR_NONE != ret) {
695 ERR("_ocprocess_worker() Fail(%d)", ret);
696 icd_ioty_complete_error(ICD_CRUD_POST, ctx, ret);
697 return OC_STACK_DELETE_TRANSACTION;
700 return OC_STACK_DELETE_TRANSACTION;
704 OCStackApplicationResult icd_ioty_ocprocess_delete_cb(void *ctx, OCDoHandle handle,
705 OCClientResponse *resp)
709 GVariantBuilder *options;
711 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
713 if (NULL == resp->payload) {
714 ERR("payload is empty");
715 icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, IOTCON_ERROR_IOTIVITY);
716 return OC_STACK_DELETE_TRANSACTION;
719 res = _ocprocess_parse_oic_result(resp->result);
721 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
722 resp->numRcvdVendorSpecificHeaderOptions);
724 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_DELETE, NULL, res, options, ctx);
725 if (IOTCON_ERROR_NONE != ret) {
726 ERR("_ocprocess_worker() Fail(%d)", ret);
727 icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, ret);
728 return OC_STACK_DELETE_TRANSACTION;
731 return OC_STACK_DELETE_TRANSACTION;
735 static int _worker_observe_cb(void *context)
739 struct icd_observe_context *ctx = context;
741 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
743 value = g_variant_new("(a(qs)vii)", ctx->options, ctx->payload, ctx->res,
746 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_OBSERVE,
747 ctx->signal_number, value);
748 if (IOTCON_ERROR_NONE != ret)
749 ERR("_ocprocess_response_signal() Fail(%d)", ret);
751 /* ctx was allocated from icd_ioty_ocprocess_observe_cb() */
753 g_variant_builder_unref(ctx->options);
760 static void _observe_cb_response_error(const char *dest,
761 unsigned int signal_number, int ret_val)
766 GVariantBuilder options;
768 g_variant_builder_init(&options, G_VARIANT_TYPE("a(qs)"));
769 payload = icd_payload_representation_empty_gvariant();
771 value = g_variant_new("(a(qs)vii)", &options, payload, ret_val, 0);
773 ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_OBSERVE, signal_number, value);
774 if (IOTCON_ERROR_NONE != ret)
775 ERR("_ocprocess_response_signal() Fail(%d)", ret);
779 OCStackApplicationResult icd_ioty_ocprocess_observe_cb(void *ctx,
780 OCDoHandle handle, OCClientResponse *resp)
783 GVariantBuilder *options;
784 struct icd_observe_context *observe_ctx;
785 icd_sig_ctx_s *sig_context = ctx;
787 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
789 if (NULL == resp->payload) {
790 ERR("payload is empty");
791 _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number,
792 IOTCON_ERROR_IOTIVITY);
793 return OC_STACK_KEEP_TRANSACTION;
796 observe_ctx = calloc(1, sizeof(struct icd_observe_context));
797 if (NULL == observe_ctx) {
798 ERR("calloc() Fail(%d)", errno);
799 _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number,
800 IOTCON_ERROR_OUT_OF_MEMORY);
801 return OC_STACK_KEEP_TRANSACTION;
804 res = _ocprocess_parse_oic_result(resp->result);
806 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
807 resp->numRcvdVendorSpecificHeaderOptions);
809 observe_ctx->payload = icd_payload_to_gvariant(resp->payload);
810 observe_ctx->signal_number = sig_context->signal_number;
811 observe_ctx->res = res;
812 observe_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
813 observe_ctx->options = options;
815 ret = _ocprocess_worker_start(_worker_observe_cb, observe_ctx);
816 if (IOTCON_ERROR_NONE != ret) {
817 ERR("_ocprocess_worker_start() Fail(%d)", ret);
818 _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number, ret);
819 free(observe_ctx->bus_name);
820 if (observe_ctx->payload)
821 g_variant_unref(observe_ctx->payload);
822 g_variant_builder_unref(observe_ctx->options);
824 return OC_STACK_KEEP_TRANSACTION;
827 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
828 /* DO NOT FREE observe_ctx. It MUST be freed in the _worker_observe_cb func */
830 return OC_STACK_KEEP_TRANSACTION;
834 static int _worker_presence_cb(void *context)
839 struct icd_presence_context *ctx = context;
841 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
843 ret = icd_ioty_get_host_address(ctx->dev_addr, &host_address, &conn_type);
844 if (IOTCON_ERROR_NONE != ret) {
845 ERR("icd_ioty_get_host_address() Fail(%d)", ret);
846 free(ctx->resource_type);
853 value = g_variant_new("(iusiis)", ctx->result, ctx->nonce, host_address, conn_type,
854 ctx->trigger, ic_utils_dbus_encode_str(ctx->resource_type));
858 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_PRESENCE,
859 ctx->signal_number, value);
860 if (IOTCON_ERROR_NONE != ret)
861 ERR("_ocprocess_response_signal() Fail(%d)", ret);
863 /* ctx was allocated from icd_ioty_ocprocess_presence_cb() */
864 free(ctx->resource_type);
873 static void _presence_cb_response_error(const char *dest, unsigned int signal_number,
880 value = g_variant_new("(iusiis)", ret_val, 0, IC_STR_NULL, IOTCON_CONNECTIVITY_ALL,
881 IOTCON_PRESENCE_TRIGGER_RESOURCE_CREATED, IC_STR_NULL);
883 ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_PRESENCE, signal_number, value);
884 if (IOTCON_ERROR_NONE != ret)
885 ERR("_ocprocess_response_signal() Fail(%d)", ret);
889 static int _presence_trigger_to_ioty_trigger(OCPresenceTrigger src,
890 iotcon_presence_trigger_e *dest)
892 RETV_IF(NULL == dest, IOTCON_ERROR_INVALID_PARAMETER);
895 case OC_PRESENCE_TRIGGER_CREATE:
896 *dest = IOTCON_PRESENCE_TRIGGER_RESOURCE_CREATED;
898 case OC_PRESENCE_TRIGGER_CHANGE:
899 *dest = IOTCON_PRESENCE_TRIGGER_RESOURCE_UPDATED;
901 case OC_PRESENCE_TRIGGER_DELETE:
902 *dest = IOTCON_PRESENCE_TRIGGER_RESOURCE_DESTROYED;
905 ERR("Invalid trigger(%d)", src);
906 return IOTCON_ERROR_INVALID_PARAMETER;
909 return IOTCON_ERROR_NONE;
913 OCStackApplicationResult icd_ioty_ocprocess_presence_cb(void *ctx, OCDoHandle handle,
914 OCClientResponse *resp)
919 OCPresencePayload *payload;
920 icd_sig_ctx_s *sig_context = ctx;
921 struct icd_presence_context *presence_ctx;
923 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
924 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
926 presence_ctx = calloc(1, sizeof(struct icd_presence_context));
927 if (NULL == presence_ctx) {
928 ERR("calloc() Fail(%d)", errno);
929 _presence_cb_response_error(sig_context->bus_name, sig_context->signal_number,
930 IOTCON_ERROR_OUT_OF_MEMORY);
931 return OC_STACK_KEEP_TRANSACTION;
934 dev_addr = calloc(1, sizeof(OCDevAddr));
935 if (NULL == dev_addr) {
936 ERR("calloc() Fail(%d)", errno);
937 _presence_cb_response_error(sig_context->bus_name, sig_context->signal_number,
938 IOTCON_ERROR_OUT_OF_MEMORY);
940 return OC_STACK_KEEP_TRANSACTION;
942 memcpy(dev_addr, &resp->devAddr, sizeof(OCDevAddr));
944 payload = (OCPresencePayload*)resp->payload;
946 switch (resp->result) {
948 presence_ctx->result = IOTCON_PRESENCE_OK;
949 ret = _presence_trigger_to_ioty_trigger(payload->trigger, &presence_ctx->trigger);
950 if (IOTCON_ERROR_NONE != ret) {
951 ERR("_presence_trigger_to_ioty_trigger() Fail(%d)", ret);
952 _presence_cb_response_error(sig_context->bus_name, sig_context->signal_number,
955 return OC_STACK_KEEP_TRANSACTION;
958 case OC_STACK_PRESENCE_STOPPED:
959 presence_ctx->result = IOTCON_PRESENCE_STOPPED;
961 case OC_STACK_PRESENCE_TIMEOUT:
962 presence_ctx->result = IOTCON_PRESENCE_TIMEOUT;
966 DBG("Presence error(%d)", resp->result);
967 presence_ctx->result = IOTCON_ERROR_IOTIVITY;
970 presence_ctx->signal_number = sig_context->signal_number;
971 presence_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
972 presence_ctx->nonce = resp->sequenceNumber;
973 presence_ctx->dev_addr = dev_addr;
975 if (payload->resourceType)
976 presence_ctx->resource_type = strdup(payload->resourceType);
978 ret = _ocprocess_worker_start(_worker_presence_cb, presence_ctx);
979 if (IOTCON_ERROR_NONE != ret) {
980 ERR("_ocprocess_worker_start() Fail(%d)", ret);
981 _presence_cb_response_error(sig_context->bus_name, sig_context->signal_number, ret);
982 free(presence_ctx->resource_type);
983 free(presence_ctx->bus_name);
984 free(presence_ctx->dev_addr);
986 return OC_STACK_KEEP_TRANSACTION;
989 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
990 /* DO NOT FREE presence_ctx. It MUST be freed in the _worker_presence_cb func */
992 return OC_STACK_KEEP_TRANSACTION;
996 OCStackApplicationResult icd_ioty_ocprocess_info_cb(void *ctx, OCDoHandle handle,
997 OCClientResponse *resp)
1001 struct icd_info_context *info_ctx;
1002 icd_sig_ctx_s *sig_context = ctx;
1004 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
1005 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
1006 RETV_IF(NULL == resp->payload, OC_STACK_KEEP_TRANSACTION);
1008 if (PAYLOAD_TYPE_DEVICE == resp->payload->type)
1009 info_type = ICD_DEVICE_INFO;
1010 else if (PAYLOAD_TYPE_PLATFORM == resp->payload->type)
1011 info_type = ICD_PLATFORM_INFO;
1013 return OC_STACK_KEEP_TRANSACTION;
1015 info_ctx = calloc(1, sizeof(struct icd_info_context));
1016 if (NULL == info_ctx) {
1017 ERR("calloc() Fail(%d)", errno);
1018 return OC_STACK_KEEP_TRANSACTION;
1021 info_ctx->info_type = info_type;
1022 info_ctx->payload = icd_payload_to_gvariant(resp->payload);
1023 info_ctx->signal_number = sig_context->signal_number;
1024 info_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
1026 ret = _ocprocess_worker_start(_worker_info_cb, info_ctx);
1027 if (IOTCON_ERROR_NONE != ret) {
1028 ERR("_ocprocess_worker_start() Fail(%d)", ret);
1029 free(info_ctx->bus_name);
1030 if (info_ctx->payload)
1031 g_variant_unref(info_ctx->payload);
1033 return OC_STACK_KEEP_TRANSACTION;
1036 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
1037 /* DO NOT FREE info_ctx. It MUST be freed in the _worker_info_cb func */
1039 return OC_STACK_KEEP_TRANSACTION;
1043 static int _worker_tizen_info_handler(void *context)
1047 char *tizen_device_id;
1048 OCStackResult result;
1049 OCRepPayload *payload;
1050 OCEntityHandlerResponse response = {0};
1051 struct icd_tizen_info_context *ctx = context;
1053 response.requestHandle = ctx->request_h;
1054 response.resourceHandle = ctx->resource_h;
1055 response.ehResult = OC_EH_OK;
1057 /* Get Tizen Info */
1058 ret = icd_ioty_tizen_info_get_property(&device_name, &tizen_device_id);
1059 if (IOTCON_ERROR_NONE != ret) {
1060 ERR("icd_ioty_tizen_info_get_property() Fail(%d)", ret);
1061 response.ehResult = OC_EH_ERROR;
1065 payload = OCRepPayloadCreate();
1066 OCRepPayloadSetUri(payload, ICD_IOTY_TIZEN_INFO_URI);
1067 OCRepPayloadAddResourceType(payload, ICD_IOTY_TIZEN_INFO_TYPE);
1068 OCRepPayloadAddInterface(payload, IC_INTERFACE_DEFAULT);
1070 OCRepPayloadSetPropString(payload, ICD_IOTY_TIZEN_INFO_DEVICE_NAME,
1071 ic_utils_dbus_encode_str(device_name));
1072 OCRepPayloadSetPropString(payload, ICD_IOTY_TIZEN_INFO_TIZEN_DEVICE_ID,
1073 ic_utils_dbus_encode_str(tizen_device_id));
1074 response.payload = (OCPayload*)payload;
1076 icd_ioty_csdk_lock();
1077 result = OCDoResponse(&response);
1078 icd_ioty_csdk_unlock();
1080 if (OC_STACK_OK != result) {
1081 ERR("OCDoResponse() Fail(%d)", result);
1083 return IOTCON_ERROR_IOTIVITY;
1087 return IOTCON_ERROR_NONE;
1091 OCEntityHandlerResult icd_ioty_ocprocess_tizen_info_handler(OCEntityHandlerFlag flag,
1092 OCEntityHandlerRequest *request, void *user_data)
1095 struct icd_tizen_info_context *tizen_info_ctx;
1097 if ((0 == (OC_REQUEST_FLAG & flag)) || (OC_REST_GET != request->method)) {
1098 ERR("Prohibited Action");
1099 return OC_EH_FORBIDDEN;
1102 tizen_info_ctx = calloc(1, sizeof(struct icd_tizen_info_context));
1103 if (NULL == tizen_info_ctx) {
1104 ERR("calloc() Fail(%d)", errno);
1108 tizen_info_ctx->request_h = request->requestHandle;
1109 tizen_info_ctx->resource_h = request->resource;
1111 ret = _ocprocess_worker_start(_worker_tizen_info_handler, tizen_info_ctx);
1112 if (IOTCON_ERROR_NONE != ret) {
1113 ERR("_ocprocess_worker_start() Fail(%d)", ret);
1114 free(tizen_info_ctx);
1122 OCStackApplicationResult icd_ioty_ocprocess_get_tizen_info_cb(void *ctx,
1123 OCDoHandle handle, OCClientResponse *resp)
1127 char *tizen_device_id;
1128 GVariant *tizen_info;
1129 OCRepPayload *payload;
1130 OCRepPayloadValue *val;
1132 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
1134 if (NULL == resp->payload) {
1135 ERR("payload is empty");
1136 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1137 return OC_STACK_DELETE_TRANSACTION;
1140 payload = (OCRepPayload*)resp->payload;
1141 val = payload->values;
1143 ERR("Invalid payload");
1144 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1145 return OC_STACK_DELETE_TRANSACTION;
1147 device_name = val->str;
1151 ERR("Invalid Payload");
1152 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1153 return OC_STACK_DELETE_TRANSACTION;
1156 tizen_device_id = val->str;
1158 if (OC_STACK_OK == resp->result)
1159 res = IOTCON_RESPONSE_RESULT_OK;
1161 res = IOTCON_RESPONSE_RESULT_ERROR;
1163 tizen_info = g_variant_new("(ssi)", device_name, tizen_device_id, res);
1165 icd_ioty_complete(ICD_TIZEN_INFO, ctx, tizen_info);
1167 return OC_STACK_DELETE_TRANSACTION;