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;
232 static int _worker_req_handler(void *context)
235 int ret, conn_type, action;
236 struct icd_req_context *ctx = context;
237 GVariantBuilder payload_builder;
238 char addr[PATH_MAX] = {0};
240 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
242 g_variant_builder_init(&payload_builder, G_VARIANT_TYPE("av"));
244 g_variant_builder_add(&payload_builder, "v", ctx->payload);
246 if (ctx->dev_addr->addr && *ctx->dev_addr->addr)
247 snprintf(addr, sizeof(addr), "%s:%d", ctx->dev_addr->addr, ctx->dev_addr->port);
249 conn_type = icd_ioty_transport_flag_to_conn_type(ctx->dev_addr->adapter,
250 ctx->dev_addr->flags);
252 action = _ioty_oic_action_to_ioty_action(ctx->observe_action);
254 value = g_variant_new("(siia(qs)a(ss)iiavxx)",
263 ICD_POINTER_TO_INT64(ctx->request_h),
264 ICD_POINTER_TO_INT64(ctx->resource_h));
266 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_REQUEST_HANDLER,
267 ctx->signal_number, value);
268 if (IOTCON_ERROR_NONE != ret)
269 ERR("_ocprocess_response_signal() Fail(%d)", ret);
272 g_variant_builder_unref(ctx->options);
273 g_variant_builder_unref(ctx->query);
281 OCEntityHandlerResult icd_ioty_ocprocess_req_handler(OCEntityHandlerFlag flag,
282 OCEntityHandlerRequest *request, void *user_data)
286 unsigned int signal_number;
287 char *query_str, *query_key, *query_value;
288 char *token, *save_ptr1, *save_ptr2;
289 char *bus_name = NULL;
290 struct icd_req_context *req_ctx;
293 RETV_IF(NULL == request, OC_EH_ERROR);
295 req_ctx = calloc(1, sizeof(struct icd_req_context));
296 if (NULL == req_ctx) {
297 ERR("calloc() Fail(%d)", errno);
302 req_ctx->request_h = request->requestHandle;
303 req_ctx->resource_h = request->resource;
305 ret = icd_dbus_client_list_get_info(req_ctx->resource_h, &signal_number, &bus_name);
306 if (IOTCON_ERROR_NONE != ret) {
307 ERR("icd_dbus_client_list_get_info() Fail(%d)", ret);
312 /* signal number & bus_name */
313 req_ctx->signal_number = signal_number;
314 req_ctx->bus_name = bus_name;
316 dev_addr = calloc(1, sizeof(OCDevAddr));
317 if (NULL == dev_addr) {
318 ERR("calloc() Fail(%d)", errno);
322 memcpy(dev_addr, &request->devAddr, sizeof(OCDevAddr));
323 req_ctx->dev_addr = dev_addr;
326 if (OC_REQUEST_FLAG & flag) {
327 switch (request->method) {
329 req_ctx->types = IOTCON_REQUEST_GET;
330 req_ctx->payload = NULL;
332 if (OC_OBSERVE_FLAG & flag) {
333 req_ctx->types |= IOTCON_REQUEST_OBSERVE;
334 /* observation info*/
335 req_ctx->observe_id = request->obsInfo.obsId;
336 req_ctx->observe_action = request->obsInfo.action;
340 req_ctx->types = IOTCON_REQUEST_PUT;
341 req_ctx->payload = icd_payload_to_gvariant(request->payload);
344 req_ctx->types = IOTCON_REQUEST_POST;
345 req_ctx->payload = icd_payload_to_gvariant(request->payload);
348 req_ctx->types = IOTCON_REQUEST_DELETE;
349 req_ctx->payload = NULL;
352 free(req_ctx->bus_name);
359 req_ctx->options = _ocprocess_parse_header_options(
360 request->rcvdVendorSpecificHeaderOptions,
361 request->numRcvdVendorSpecificHeaderOptions);
364 req_ctx->query = g_variant_builder_new(G_VARIANT_TYPE("a(ss)"));
365 query_str = request->query;
366 while ((token = strtok_r(query_str, "&;", &save_ptr1))) {
367 while ((query_key = strtok_r(token, "=", &save_ptr2))) {
369 query_value = strtok_r(token, "=", &save_ptr2);
370 if (NULL == query_value)
373 g_variant_builder_add(req_ctx->query, "(ss)", query_key, query_value);
378 ret = _ocprocess_worker_start(_worker_req_handler, req_ctx);
379 if (IOTCON_ERROR_NONE != ret) {
380 ERR("_ocprocess_worker_start() Fail(%d)", ret);
381 free(req_ctx->bus_name);
382 if (req_ctx->payload)
383 g_variant_unref(req_ctx->payload);
384 g_variant_builder_unref(req_ctx->options);
385 g_variant_builder_unref(req_ctx->query);
386 free(req_ctx->dev_addr);
391 /* DO NOT FREE req_ctx. It MUST be freed in the _worker_req_handler func */
397 gpointer icd_ioty_ocprocess_thread(gpointer data)
400 OCStackResult result;
403 while (icd_ioty_alive) {
404 icd_ioty_csdk_lock();
405 result = OCProcess();
406 icd_ioty_csdk_unlock();
407 if (OC_STACK_OK != result) {
408 ERR("OCProcess() Fail(%d)", result);
412 /* TODO : SHOULD revise time or usleep */
420 static int _worker_find_cb(void *context)
424 struct icd_find_context *ctx = context;
426 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
428 for (i = 0; ctx->payload[i]; i++) {
429 value = g_variant_new("(vi)", ctx->payload[i], ctx->conn_type);
430 /* TODO : If one device has multi resources, it comes as bulk data.
431 * To reduce the number of emit_signal, let's send signal only one time for one device.
432 * for ex, client list. */
433 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_FOUND_RESOURCE,
434 ctx->signal_number, value);
435 if (IOTCON_ERROR_NONE != ret) {
436 ERR("_ocprocess_response_signal() Fail(%d)", ret);
437 g_variant_unref(value);
442 /* ctx was allocated from icd_ioty_ocprocess_find_cb() */
450 OCStackApplicationResult icd_ioty_ocprocess_find_cb(void *ctx, OCDoHandle handle,
451 OCClientResponse *resp)
454 struct icd_find_context *find_ctx;
455 icd_sig_ctx_s *sig_context = ctx;
457 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
458 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
459 if (NULL == resp->payload)
460 /* normal case : payload COULD be NULL */
461 return OC_STACK_KEEP_TRANSACTION;
462 RETVM_IF(PAYLOAD_TYPE_DISCOVERY != resp->payload->type,
463 OC_STACK_KEEP_TRANSACTION, "Invalid payload type(%d)", resp->payload->type);
465 find_ctx = calloc(1, sizeof(struct icd_find_context));
466 if (NULL == find_ctx) {
467 ERR("calloc() Fail(%d)", errno);
468 return OC_STACK_KEEP_TRANSACTION;
471 find_ctx->signal_number = sig_context->signal_number;
472 find_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
473 find_ctx->payload = icd_payload_res_to_gvariant(resp->payload, &resp->devAddr);
474 find_ctx->conn_type = icd_ioty_transport_flag_to_conn_type(resp->devAddr.adapter,
475 resp->devAddr.flags);
477 ret = _ocprocess_worker_start(_worker_find_cb, find_ctx);
478 if (IOTCON_ERROR_NONE != ret) {
479 ERR("_ocprocess_worker_start() Fail(%d)", ret);
480 free(find_ctx->bus_name);
481 ic_utils_gvariant_array_free(find_ctx->payload);
483 return OC_STACK_KEEP_TRANSACTION;
486 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
487 /* DO NOT FREE find_ctx. It MUST be freed in the _worker_find_cb func */
489 return OC_STACK_KEEP_TRANSACTION;
493 static int _worker_crud_cb(void *context)
496 struct icd_crud_context *ctx = context;
498 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
500 if (ICD_CRUD_DELETE == ctx->crud_type)
501 value = g_variant_new("(a(qs)i)", ctx->options, ctx->res);
503 value = g_variant_new("(a(qs)vi)", ctx->options, ctx->payload, ctx->res);
504 icd_ioty_complete(ctx->crud_type, ctx->invocation, value);
506 /* ctx was allocated from icd_ioty_ocprocess_xxx_cb() */
507 g_variant_builder_unref(ctx->options);
510 return IOTCON_ERROR_NONE;
514 static int _worker_info_cb(void *context)
517 const char *signal_prefix = NULL;
518 struct icd_info_context *ctx = context;
520 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
522 if (ICD_DEVICE_INFO == ctx->info_type)
523 signal_prefix = IC_DBUS_SIGNAL_DEVICE;
524 else if (ICD_PLATFORM_INFO == ctx->info_type)
525 signal_prefix = IC_DBUS_SIGNAL_PLATFORM;
527 ret = _ocprocess_response_signal(ctx->bus_name, signal_prefix, ctx->signal_number,
529 if (IOTCON_ERROR_NONE != ret)
530 ERR("_ocprocess_response_signal() Fail(%d)", ret);
532 /* ctx was allocated from icd_ioty_ocprocess_info_cb() */
540 static int _ocprocess_worker(_ocprocess_cb cb, int type, OCPayload *payload, int res,
541 GVariantBuilder *options, void *ctx)
544 struct icd_crud_context *crud_ctx;
546 crud_ctx = calloc(1, sizeof(struct icd_crud_context));
547 if (NULL == crud_ctx) {
548 ERR("calloc() Fail(%d)", errno);
549 return IOTCON_ERROR_OUT_OF_MEMORY;
552 crud_ctx->crud_type = type;
553 crud_ctx->payload = icd_payload_to_gvariant(payload);
555 crud_ctx->options = options;
556 crud_ctx->invocation = ctx;
558 ret = _ocprocess_worker_start(cb, crud_ctx);
559 if (IOTCON_ERROR_NONE != ret) {
560 ERR("_ocprocess_worker_start() Fail(%d)", ret);
561 if (crud_ctx->payload)
562 g_variant_unref(crud_ctx->payload);
563 g_variant_builder_unref(crud_ctx->options);
567 /* DO NOT FREE crud_ctx. It MUST be freed in the _worker_crud_cb func */
572 static int _ocprocess_parse_oic_result(OCStackResult result)
578 res = IOTCON_RESPONSE_RESULT_OK;
580 case OC_STACK_RESOURCE_CREATED:
581 res = IOTCON_RESPONSE_RESULT_RESOURCE_CREATED;
583 case OC_STACK_RESOURCE_DELETED:
584 res = IOTCON_RESPONSE_RESULT_RESOURCE_DELETED;
586 case OC_STACK_UNAUTHORIZED_REQ:
587 res = IOTCON_RESPONSE_RESULT_FORBIDDEN;
590 WARN("response error(%d)", result);
591 res = IOTCON_RESPONSE_RESULT_ERROR;
599 OCStackApplicationResult icd_ioty_ocprocess_get_cb(void *ctx, OCDoHandle handle,
600 OCClientResponse *resp)
604 GVariantBuilder *options;
606 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
608 if (NULL == resp->payload) {
609 ERR("payload is empty");
610 icd_ioty_complete_error(ICD_CRUD_GET, ctx, IOTCON_ERROR_IOTIVITY);
611 return OC_STACK_DELETE_TRANSACTION;
614 res = _ocprocess_parse_oic_result(resp->result);
616 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
617 resp->numRcvdVendorSpecificHeaderOptions);
619 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_GET, resp->payload, res,
621 if (IOTCON_ERROR_NONE != ret) {
622 ERR("_ocprocess_worker() Fail(%d)", ret);
623 icd_ioty_complete_error(ICD_CRUD_GET, ctx, ret);
624 return OC_STACK_DELETE_TRANSACTION;
627 return OC_STACK_DELETE_TRANSACTION;
631 OCStackApplicationResult icd_ioty_ocprocess_put_cb(void *ctx, OCDoHandle handle,
632 OCClientResponse *resp)
636 GVariantBuilder *options;
638 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
640 if (NULL == resp->payload) {
641 ERR("payload is empty");
642 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, IOTCON_ERROR_IOTIVITY);
643 return OC_STACK_DELETE_TRANSACTION;
646 res = _ocprocess_parse_oic_result(resp->result);
648 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
649 resp->numRcvdVendorSpecificHeaderOptions);
651 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_PUT, resp->payload, res,
653 if (IOTCON_ERROR_NONE != ret) {
654 ERR("_ocprocess_worker() Fail(%d)", ret);
655 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, ret);
656 return OC_STACK_DELETE_TRANSACTION;
659 return OC_STACK_DELETE_TRANSACTION;
663 OCStackApplicationResult icd_ioty_ocprocess_post_cb(void *ctx, OCDoHandle handle,
664 OCClientResponse *resp)
668 GVariantBuilder *options;
670 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
672 if (NULL == resp->payload) {
673 ERR("payload is empty");
674 icd_ioty_complete_error(ICD_CRUD_POST, ctx, IOTCON_ERROR_IOTIVITY);
675 return OC_STACK_DELETE_TRANSACTION;
678 res = _ocprocess_parse_oic_result(resp->result);
680 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
681 resp->numRcvdVendorSpecificHeaderOptions);
683 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_POST, resp->payload, res,
685 if (IOTCON_ERROR_NONE != ret) {
686 ERR("_ocprocess_worker() Fail(%d)", ret);
687 icd_ioty_complete_error(ICD_CRUD_POST, ctx, ret);
688 return OC_STACK_DELETE_TRANSACTION;
691 return OC_STACK_DELETE_TRANSACTION;
695 OCStackApplicationResult icd_ioty_ocprocess_delete_cb(void *ctx, OCDoHandle handle,
696 OCClientResponse *resp)
700 GVariantBuilder *options;
702 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
704 if (NULL == resp->payload) {
705 ERR("payload is empty");
706 icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, IOTCON_ERROR_IOTIVITY);
707 return OC_STACK_DELETE_TRANSACTION;
710 res = _ocprocess_parse_oic_result(resp->result);
712 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
713 resp->numRcvdVendorSpecificHeaderOptions);
715 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_DELETE, NULL, res, options, ctx);
716 if (IOTCON_ERROR_NONE != ret) {
717 ERR("_ocprocess_worker() Fail(%d)", ret);
718 icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, ret);
719 return OC_STACK_DELETE_TRANSACTION;
722 return OC_STACK_DELETE_TRANSACTION;
726 static int _worker_observe_cb(void *context)
730 struct icd_observe_context *ctx = context;
732 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
734 value = g_variant_new("(a(qs)vii)", ctx->options, ctx->payload, ctx->res,
737 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_OBSERVE,
738 ctx->signal_number, value);
739 if (IOTCON_ERROR_NONE != ret)
740 ERR("_ocprocess_response_signal() Fail(%d)", ret);
742 /* ctx was allocated from icd_ioty_ocprocess_observe_cb() */
744 g_variant_builder_unref(ctx->options);
751 static void _observe_cb_response_error(const char *dest,
752 unsigned int signal_number, int ret_val)
757 GVariantBuilder options;
759 g_variant_builder_init(&options, G_VARIANT_TYPE("a(qs)"));
760 payload = icd_payload_representation_empty_gvariant();
762 value = g_variant_new("(a(qs)vii)", &options, payload, ret_val, 0);
764 ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_OBSERVE, signal_number, value);
765 if (IOTCON_ERROR_NONE != ret)
766 ERR("_ocprocess_response_signal() Fail(%d)", ret);
770 OCStackApplicationResult icd_ioty_ocprocess_observe_cb(void *ctx,
771 OCDoHandle handle, OCClientResponse *resp)
774 GVariantBuilder *options;
775 struct icd_observe_context *observe_ctx;
776 icd_sig_ctx_s *sig_context = ctx;
778 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
780 if (NULL == resp->payload) {
781 ERR("payload is empty");
782 _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number,
783 IOTCON_ERROR_IOTIVITY);
784 return OC_STACK_KEEP_TRANSACTION;
787 observe_ctx = calloc(1, sizeof(struct icd_observe_context));
788 if (NULL == observe_ctx) {
789 ERR("calloc() Fail(%d)", errno);
790 _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number,
791 IOTCON_ERROR_OUT_OF_MEMORY);
792 return OC_STACK_KEEP_TRANSACTION;
795 res = _ocprocess_parse_oic_result(resp->result);
797 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
798 resp->numRcvdVendorSpecificHeaderOptions);
800 observe_ctx->payload = icd_payload_to_gvariant(resp->payload);
801 observe_ctx->signal_number = sig_context->signal_number;
802 observe_ctx->res = res;
803 observe_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
804 observe_ctx->options = options;
806 ret = _ocprocess_worker_start(_worker_observe_cb, observe_ctx);
807 if (IOTCON_ERROR_NONE != ret) {
808 ERR("_ocprocess_worker_start() Fail(%d)", ret);
809 _observe_cb_response_error(sig_context->bus_name, sig_context->signal_number, ret);
810 free(observe_ctx->bus_name);
811 if (observe_ctx->payload)
812 g_variant_unref(observe_ctx->payload);
813 g_variant_builder_unref(observe_ctx->options);
815 return OC_STACK_KEEP_TRANSACTION;
818 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
819 /* DO NOT FREE observe_ctx. It MUST be freed in the _worker_observe_cb func */
821 return OC_STACK_KEEP_TRANSACTION;
825 static int _worker_presence_cb(void *context)
829 char addr[PATH_MAX] = {0};
830 struct icd_presence_context *ctx = context;
832 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
834 snprintf(addr, sizeof(addr), "%s:%d", ctx->dev_addr->addr, ctx->dev_addr->port);
835 conn_type = icd_ioty_transport_flag_to_conn_type(ctx->dev_addr->adapter,
836 ctx->dev_addr->flags);
838 value = g_variant_new("(iusiis)", ctx->result, ctx->nonce, addr, conn_type,
839 ctx->trigger, ic_utils_dbus_encode_str(ctx->resource_type));
841 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_PRESENCE,
842 ctx->signal_number, value);
843 if (IOTCON_ERROR_NONE != ret)
844 ERR("_ocprocess_response_signal() Fail(%d)", ret);
846 /* ctx was allocated from icd_ioty_ocprocess_presence_cb() */
847 free(ctx->resource_type);
856 static void _presence_cb_response_error(const char *dest, unsigned int signal_number,
863 value = g_variant_new("(iusiis)", ret_val, 0, IC_STR_NULL, IOTCON_CONNECTIVITY_ALL,
864 IOTCON_PRESENCE_TRIGGER_RESOURCE_CREATED, IC_STR_NULL);
866 ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_PRESENCE, signal_number, value);
867 if (IOTCON_ERROR_NONE != ret)
868 ERR("_ocprocess_response_signal() Fail(%d)", ret);
872 static int _presence_trigger_to_ioty_trigger(OCPresenceTrigger src,
873 iotcon_presence_trigger_e *dest)
875 RETV_IF(NULL == dest, IOTCON_ERROR_INVALID_PARAMETER);
878 case OC_PRESENCE_TRIGGER_CREATE:
879 *dest = IOTCON_PRESENCE_TRIGGER_RESOURCE_CREATED;
881 case OC_PRESENCE_TRIGGER_CHANGE:
882 *dest = IOTCON_PRESENCE_TRIGGER_RESOURCE_UPDATED;
884 case OC_PRESENCE_TRIGGER_DELETE:
885 *dest = IOTCON_PRESENCE_TRIGGER_RESOURCE_DESTROYED;
888 ERR("Invalid trigger(%d)", src);
889 return IOTCON_ERROR_INVALID_PARAMETER;
892 return IOTCON_ERROR_NONE;
896 OCStackApplicationResult icd_ioty_ocprocess_presence_cb(void *ctx, OCDoHandle handle,
897 OCClientResponse *resp)
902 OCPresencePayload *payload;
903 icd_sig_ctx_s *sig_context = ctx;
904 struct icd_presence_context *presence_ctx;
906 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
907 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
909 presence_ctx = calloc(1, sizeof(struct icd_presence_context));
910 if (NULL == presence_ctx) {
911 ERR("calloc() Fail(%d)", errno);
912 _presence_cb_response_error(sig_context->bus_name, sig_context->signal_number,
913 IOTCON_ERROR_OUT_OF_MEMORY);
914 return OC_STACK_KEEP_TRANSACTION;
917 dev_addr = calloc(1, sizeof(OCDevAddr));
918 if (NULL == dev_addr) {
919 ERR("calloc() Fail(%d)", errno);
920 _presence_cb_response_error(sig_context->bus_name, sig_context->signal_number,
921 IOTCON_ERROR_OUT_OF_MEMORY);
923 return OC_STACK_KEEP_TRANSACTION;
925 memcpy(dev_addr, &resp->devAddr, sizeof(OCDevAddr));
927 payload = (OCPresencePayload*)resp->payload;
929 switch (resp->result) {
931 presence_ctx->result = IOTCON_PRESENCE_OK;
932 ret = _presence_trigger_to_ioty_trigger(payload->trigger, &presence_ctx->trigger);
933 if (IOTCON_ERROR_NONE != ret) {
934 ERR("_presence_trigger_to_ioty_trigger() Fail(%d)", ret);
935 _presence_cb_response_error(sig_context->bus_name, sig_context->signal_number,
938 return OC_STACK_KEEP_TRANSACTION;
941 case OC_STACK_PRESENCE_STOPPED:
942 presence_ctx->result = IOTCON_PRESENCE_STOPPED;
944 case OC_STACK_PRESENCE_TIMEOUT:
945 presence_ctx->result = IOTCON_PRESENCE_TIMEOUT;
949 DBG("Presence error(%d)", resp->result);
950 presence_ctx->result = IOTCON_ERROR_IOTIVITY;
953 presence_ctx->signal_number = sig_context->signal_number;
954 presence_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
955 presence_ctx->nonce = resp->sequenceNumber;
956 presence_ctx->dev_addr = dev_addr;
958 if (payload->resourceType)
959 presence_ctx->resource_type = strdup(payload->resourceType);
961 ret = _ocprocess_worker_start(_worker_presence_cb, presence_ctx);
962 if (IOTCON_ERROR_NONE != ret) {
963 ERR("_ocprocess_worker_start() Fail(%d)", ret);
964 _presence_cb_response_error(sig_context->bus_name, sig_context->signal_number, ret);
965 free(presence_ctx->resource_type);
966 free(presence_ctx->bus_name);
967 free(presence_ctx->dev_addr);
969 return OC_STACK_KEEP_TRANSACTION;
972 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
973 /* DO NOT FREE presence_ctx. It MUST be freed in the _worker_presence_cb func */
975 return OC_STACK_KEEP_TRANSACTION;
979 OCStackApplicationResult icd_ioty_ocprocess_info_cb(void *ctx, OCDoHandle handle,
980 OCClientResponse *resp)
984 struct icd_info_context *info_ctx;
985 icd_sig_ctx_s *sig_context = ctx;
987 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
988 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
989 RETV_IF(NULL == resp->payload, OC_STACK_KEEP_TRANSACTION);
991 if (PAYLOAD_TYPE_DEVICE == resp->payload->type)
992 info_type = ICD_DEVICE_INFO;
993 else if (PAYLOAD_TYPE_PLATFORM == resp->payload->type)
994 info_type = ICD_PLATFORM_INFO;
996 return OC_STACK_KEEP_TRANSACTION;
998 info_ctx = calloc(1, sizeof(struct icd_info_context));
999 if (NULL == info_ctx) {
1000 ERR("calloc() Fail(%d)", errno);
1001 return OC_STACK_KEEP_TRANSACTION;
1004 info_ctx->info_type = info_type;
1005 info_ctx->payload = icd_payload_to_gvariant(resp->payload);
1006 info_ctx->signal_number = sig_context->signal_number;
1007 info_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
1009 ret = _ocprocess_worker_start(_worker_info_cb, info_ctx);
1010 if (IOTCON_ERROR_NONE != ret) {
1011 ERR("_ocprocess_worker_start() Fail(%d)", ret);
1012 free(info_ctx->bus_name);
1013 if (info_ctx->payload)
1014 g_variant_unref(info_ctx->payload);
1016 return OC_STACK_KEEP_TRANSACTION;
1019 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
1020 /* DO NOT FREE info_ctx. It MUST be freed in the _worker_info_cb func */
1022 return OC_STACK_KEEP_TRANSACTION;
1026 static int _worker_tizen_info_handler(void *context)
1030 char *tizen_device_id;
1031 OCStackResult result;
1032 OCRepPayload *payload;
1033 OCEntityHandlerResponse response = {0};
1034 struct icd_tizen_info_context *ctx = context;
1036 response.requestHandle = ctx->request_h;
1037 response.resourceHandle = ctx->resource_h;
1038 response.ehResult = OC_EH_OK;
1040 /* Get Tizen Info */
1041 ret = icd_ioty_tizen_info_get_property(&device_name, &tizen_device_id);
1042 if (IOTCON_ERROR_NONE != ret) {
1043 ERR("icd_ioty_tizen_info_get_property() Fail(%d)", ret);
1044 response.ehResult = OC_EH_ERROR;
1048 payload = OCRepPayloadCreate();
1049 OCRepPayloadSetUri(payload, ICD_IOTY_TIZEN_INFO_URI);
1050 OCRepPayloadAddResourceType(payload, ICD_IOTY_TIZEN_INFO_TYPE);
1051 OCRepPayloadAddInterface(payload, IC_INTERFACE_DEFAULT);
1053 OCRepPayloadSetPropString(payload, ICD_IOTY_TIZEN_INFO_DEVICE_NAME,
1054 ic_utils_dbus_encode_str(device_name));
1055 OCRepPayloadSetPropString(payload, ICD_IOTY_TIZEN_INFO_TIZEN_DEVICE_ID,
1056 ic_utils_dbus_encode_str(tizen_device_id));
1057 response.payload = (OCPayload*)payload;
1059 icd_ioty_csdk_lock();
1060 result = OCDoResponse(&response);
1061 icd_ioty_csdk_unlock();
1063 if (OC_STACK_OK != result) {
1064 ERR("OCDoResponse() Fail(%d)", result);
1066 return IOTCON_ERROR_IOTIVITY;
1070 return IOTCON_ERROR_NONE;
1074 OCEntityHandlerResult icd_ioty_ocprocess_tizen_info_handler(OCEntityHandlerFlag flag,
1075 OCEntityHandlerRequest *request, void *user_data)
1078 struct icd_tizen_info_context *tizen_info_ctx;
1080 if ((0 == (OC_REQUEST_FLAG & flag)) || (OC_REST_GET != request->method)) {
1081 ERR("Prohibited Action");
1082 return OC_EH_FORBIDDEN;
1085 tizen_info_ctx = calloc(1, sizeof(struct icd_tizen_info_context));
1086 if (NULL == tizen_info_ctx) {
1087 ERR("calloc() Fail(%d)", errno);
1091 tizen_info_ctx->request_h = request->requestHandle;
1092 tizen_info_ctx->resource_h = request->resource;
1094 ret = _ocprocess_worker_start(_worker_tizen_info_handler, tizen_info_ctx);
1095 if (IOTCON_ERROR_NONE != ret) {
1096 ERR("_ocprocess_worker_start() Fail(%d)", ret);
1097 free(tizen_info_ctx);
1105 OCStackApplicationResult icd_ioty_ocprocess_get_tizen_info_cb(void *ctx,
1106 OCDoHandle handle, OCClientResponse *resp)
1110 char *tizen_device_id;
1111 GVariant *tizen_info;
1112 OCRepPayload *payload;
1113 OCRepPayloadValue *val;
1115 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
1117 if (NULL == resp->payload) {
1118 ERR("payload is empty");
1119 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1120 return OC_STACK_DELETE_TRANSACTION;
1123 payload = (OCRepPayload*)resp->payload;
1124 val = payload->values;
1126 ERR("Invalid payload");
1127 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1128 return OC_STACK_DELETE_TRANSACTION;
1130 device_name = val->str;
1134 ERR("Invalid Payload");
1135 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1136 return OC_STACK_DELETE_TRANSACTION;
1139 tizen_device_id = val->str;
1141 if (OC_STACK_OK == resp->result)
1142 res = IOTCON_RESPONSE_RESULT_OK;
1144 res = IOTCON_RESPONSE_RESULT_ERROR;
1146 tizen_info = g_variant_new("(ssi)", device_name, tizen_device_id, res);
1148 icd_ioty_complete(ICD_TIZEN_INFO, ctx, tizen_info);
1150 return OC_STACK_DELETE_TRANSACTION;