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 {
51 OCRequestHandle request_h;
52 OCResourceHandle resource_h;
54 GVariantBuilder *options;
55 GVariantBuilder *query;
59 struct icd_find_context {
67 struct icd_crud_context {
71 GVariantBuilder *options;
72 GDBusMethodInvocation *invocation;
76 struct icd_info_context {
84 struct icd_tizen_info_context {
85 OCRequestHandle request_h;
86 OCResourceHandle resource_h;
87 GDBusMethodInvocation *invocation;
91 struct icd_observe_context {
97 GVariantBuilder *options;
101 struct icd_presence_context {
110 void icd_ioty_ocprocess_stop()
116 static void* _ocprocess_worker_thread(void *data)
119 struct icd_ioty_worker *worker = data;
122 ERR("worker is NULL");
126 ret = worker->cb(worker->ctx);
127 if (IOTCON_ERROR_NONE != ret)
128 ERR("cb() Fail(%d)", ret);
130 /* worker was allocated from _ocprocess_worker_start() */
133 /* GCC warning happen if use g_thread_exit() */
138 static int _ocprocess_worker_start(_ocprocess_cb cb, void *ctx)
142 struct icd_ioty_worker *worker;
144 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
146 worker = calloc(1, sizeof(struct icd_ioty_worker));
147 if (NULL == worker) {
148 ERR("calloc() Fail(%d)", errno);
149 return IOTCON_ERROR_OUT_OF_MEMORY;
155 /* TODO : consider thread pool mechanism */
156 thread = g_thread_try_new("worker_thread", _ocprocess_worker_thread, worker, &error);
157 if (NULL == thread) {
158 ERR("g_thread_try_new() Fail(%s)", error->message);
161 return IOTCON_ERROR_SYSTEM;
164 /* DO NOT join thread. It was already detached by calling g_thread_unref() */
165 g_thread_unref(thread);
167 /* DO NOT FREE worker. It MUST be freed in the _ocprocess_worker_thread() */
169 return IOTCON_ERROR_NONE;
173 static int _ocprocess_response_signal(const char *dest, const char *signal,
174 unsigned int signum, GVariant *value)
177 char sig_name[IC_DBUS_SIGNAL_LENGTH] = {0};
179 ret = snprintf(sig_name, sizeof(sig_name), "%s_%u", signal, signum);
180 if (ret <= 0 || sizeof(sig_name) <= ret) {
181 ERR("snprintf() Fail(%d)", ret);
182 return IOTCON_ERROR_IO_ERROR;
185 ret = icd_dbus_emit_signal(dest, sig_name, value);
186 if (IOTCON_ERROR_NONE != ret) {
187 ERR("icd_dbus_emit_signal() Fail(%d)", ret);
191 return IOTCON_ERROR_NONE;
195 static inline GVariantBuilder* _ocprocess_parse_header_options(
196 OCHeaderOption *oic_option, int option_size)
199 GVariantBuilder *options;
201 options = g_variant_builder_new(G_VARIANT_TYPE("a(qs)"));
202 for (i = 0; i < option_size; i++) {
203 g_variant_builder_add(options, "(qs)", oic_option[i].optionID,
204 oic_option[i].optionData);
211 static int _worker_req_handler(void *context)
215 struct icd_req_context *ctx = context;
216 GVariantBuilder payload_builder;
218 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
220 g_variant_builder_init(&payload_builder, G_VARIANT_TYPE("av"));
222 g_variant_builder_add(&payload_builder, "v", ctx->payload);
224 value = g_variant_new("(ia(qs)a(ss)iiavxx)",
231 ICD_POINTER_TO_INT64(ctx->request_h),
232 ICD_POINTER_TO_INT64(ctx->resource_h));
234 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_REQUEST_HANDLER,
236 if (IOTCON_ERROR_NONE != ret)
237 ERR("_ocprocess_response_signal() Fail(%d)", ret);
240 g_variant_builder_unref(ctx->options);
241 g_variant_builder_unref(ctx->query);
248 OCEntityHandlerResult icd_ioty_ocprocess_req_handler(OCEntityHandlerFlag flag,
249 OCEntityHandlerRequest *request, void *user_data)
253 unsigned int signal_number;
254 char *query_str, *query_key, *query_value;
255 char *token, *save_ptr1, *save_ptr2;
256 char *bus_name = NULL;
257 struct icd_req_context *req_ctx;
259 RETV_IF(NULL == request, OC_EH_ERROR);
261 req_ctx = calloc(1, sizeof(struct icd_req_context));
262 if (NULL == req_ctx) {
263 ERR("calloc() Fail(%d)", errno);
268 req_ctx->request_h = request->requestHandle;
269 req_ctx->resource_h = request->resource;
271 ret = icd_dbus_client_list_get_info(req_ctx->resource_h, &signal_number, &bus_name);
272 if (IOTCON_ERROR_NONE != ret) {
273 ERR("icd_dbus_client_list_get_info() Fail(%d)", ret);
278 /* signal number & bus_name */
279 req_ctx->signum = signal_number;
280 req_ctx->bus_name = bus_name;
283 if (OC_REQUEST_FLAG & flag) {
284 switch (request->method) {
286 req_ctx->types = IOTCON_REQUEST_GET;
287 req_ctx->payload = NULL;
289 if (OC_OBSERVE_FLAG & flag) {
290 req_ctx->types |= IOTCON_REQUEST_OBSERVE;
291 /* observation info*/
292 req_ctx->observer_id = request->obsInfo.obsId;
293 req_ctx->observe_action = request->obsInfo.action;
297 req_ctx->types = IOTCON_REQUEST_PUT;
298 req_ctx->payload = icd_payload_to_gvariant(request->payload);
301 req_ctx->types = IOTCON_REQUEST_POST;
302 req_ctx->payload = icd_payload_to_gvariant(request->payload);
305 req_ctx->types = IOTCON_REQUEST_DELETE;
306 req_ctx->payload = NULL;
309 free(req_ctx->bus_name);
316 req_ctx->options = _ocprocess_parse_header_options(
317 request->rcvdVendorSpecificHeaderOptions,
318 request->numRcvdVendorSpecificHeaderOptions);
321 req_ctx->query = g_variant_builder_new(G_VARIANT_TYPE("a(ss)"));
322 query_str = request->query;
323 while ((token = strtok_r(query_str, "&;", &save_ptr1))) {
324 while ((query_key = strtok_r(token, "=", &save_ptr2))) {
326 query_value = strtok_r(token, "=", &save_ptr2);
327 if (NULL == query_value)
330 g_variant_builder_add(req_ctx->query, "(ss)", query_key, query_value);
335 ret = _ocprocess_worker_start(_worker_req_handler, req_ctx);
336 if (IOTCON_ERROR_NONE != ret) {
337 ERR("_ocprocess_worker_start() Fail(%d)", ret);
338 free(req_ctx->bus_name);
339 if (req_ctx->payload)
340 g_variant_unref(req_ctx->payload);
341 g_variant_builder_unref(req_ctx->options);
342 g_variant_builder_unref(req_ctx->query);
347 /* DO NOT FREE req_ctx. It MUST be freed in the _worker_req_handler func */
353 gpointer icd_ioty_ocprocess_thread(gpointer data)
356 OCStackResult result;
359 while (icd_ioty_alive) {
360 icd_ioty_csdk_lock();
361 result = OCProcess();
362 icd_ioty_csdk_unlock();
363 if (OC_STACK_OK != result) {
364 ERR("OCProcess() Fail(%d)", result);
368 /* TODO : SHOULD revise time or usleep */
376 static int _worker_find_cb(void *context)
380 struct icd_find_context *ctx = context;
382 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
384 for (i = 0; ctx->payload[i]; i++) {
385 value = g_variant_new("(vi)", ctx->payload[i], ctx->conn_type);
386 /* TODO : If one device has multi resources, it comes as bulk data.
387 * To reduce the number of emit_signal, let's send signal only one time for one device.
388 * for ex, client list. */
389 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_FOUND_RESOURCE,
391 if (IOTCON_ERROR_NONE != ret) {
392 ERR("_ocprocess_response_signal() Fail(%d)", ret);
393 g_variant_unref(value);
398 /* ctx was allocated from icd_ioty_ocprocess_find_cb() */
406 OCStackApplicationResult icd_ioty_ocprocess_find_cb(void *ctx, OCDoHandle handle,
407 OCClientResponse *resp)
410 struct icd_find_context *find_ctx;
411 icd_sig_ctx_s *sig_context = ctx;
413 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
414 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
415 if (NULL == resp->payload)
416 /* normal case : payload COULD be NULL */
417 return OC_STACK_KEEP_TRANSACTION;
418 RETVM_IF(PAYLOAD_TYPE_DISCOVERY != resp->payload->type,
419 OC_STACK_KEEP_TRANSACTION, "Invalid payload type(%d)", resp->payload->type);
421 find_ctx = calloc(1, sizeof(struct icd_find_context));
422 if (NULL == find_ctx) {
423 ERR("calloc() Fail(%d)", errno);
424 return OC_STACK_KEEP_TRANSACTION;
427 find_ctx->signum = sig_context->signum;
428 find_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
429 find_ctx->payload = icd_payload_res_to_gvariant(resp->payload, &resp->devAddr);
430 find_ctx->conn_type = icd_ioty_transport_flag_to_conn_type(resp->devAddr.adapter,
431 resp->devAddr.flags);
433 ret = _ocprocess_worker_start(_worker_find_cb, find_ctx);
434 if (IOTCON_ERROR_NONE != ret) {
435 ERR("_ocprocess_worker_start() Fail(%d)", ret);
436 free(find_ctx->bus_name);
437 ic_utils_gvariant_array_free(find_ctx->payload);
439 return OC_STACK_KEEP_TRANSACTION;
442 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
443 /* DO NOT FREE find_ctx. It MUST be freed in the _worker_find_cb func */
445 return OC_STACK_KEEP_TRANSACTION;
449 static int _worker_crud_cb(void *context)
452 struct icd_crud_context *ctx = context;
454 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
456 if (ICD_CRUD_DELETE == ctx->crud_type)
457 value = g_variant_new("(a(qs)i)", ctx->options, ctx->res);
459 value = g_variant_new("(a(qs)vi)", ctx->options, ctx->payload, ctx->res);
460 icd_ioty_complete(ctx->crud_type, ctx->invocation, value);
462 /* ctx was allocated from icd_ioty_ocprocess_xxx_cb() */
463 g_variant_builder_unref(ctx->options);
466 return IOTCON_ERROR_NONE;
470 static int _worker_info_cb(void *context)
473 const char *sig_name = NULL;
474 struct icd_info_context *ctx = context;
476 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
478 if (ICD_DEVICE_INFO == ctx->info_type)
479 sig_name = IC_DBUS_SIGNAL_DEVICE;
480 else if (ICD_PLATFORM_INFO == ctx->info_type)
481 sig_name = IC_DBUS_SIGNAL_PLATFORM;
483 ret = _ocprocess_response_signal(ctx->bus_name, sig_name, ctx->signum, ctx->payload);
484 if (IOTCON_ERROR_NONE != ret)
485 ERR("_ocprocess_response_signal() Fail(%d)", ret);
487 /* ctx was allocated from icd_ioty_ocprocess_info_cb() */
495 static int _ocprocess_worker(_ocprocess_cb cb, int type, OCPayload *payload, int res,
496 GVariantBuilder *options, void *ctx)
499 struct icd_crud_context *crud_ctx;
501 crud_ctx = calloc(1, sizeof(struct icd_crud_context));
502 if (NULL == crud_ctx) {
503 ERR("calloc() Fail(%d)", errno);
504 return IOTCON_ERROR_OUT_OF_MEMORY;
507 crud_ctx->crud_type = type;
508 crud_ctx->payload = icd_payload_to_gvariant(payload);
510 crud_ctx->options = options;
511 crud_ctx->invocation = ctx;
513 ret = _ocprocess_worker_start(cb, crud_ctx);
514 if (IOTCON_ERROR_NONE != ret) {
515 ERR("_ocprocess_worker_start() Fail(%d)", ret);
516 if (crud_ctx->payload)
517 g_variant_unref(crud_ctx->payload);
518 g_variant_builder_unref(crud_ctx->options);
522 /* DO NOT FREE crud_ctx. It MUST be freed in the _worker_crud_cb func */
528 OCStackApplicationResult icd_ioty_ocprocess_get_cb(void *ctx, OCDoHandle handle,
529 OCClientResponse *resp)
533 OCStackResult result;
534 GVariantBuilder *options;
536 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
538 if (NULL == resp->payload) {
539 ERR("payload is empty");
540 icd_ioty_complete_error(ICD_CRUD_GET, ctx, IOTCON_ERROR_IOTIVITY);
541 return OC_STACK_DELETE_TRANSACTION;
544 result = resp->result;
545 if (OC_STACK_OK == result) {
546 res = IOTCON_RESPONSE_RESULT_OK;
547 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
548 resp->numRcvdVendorSpecificHeaderOptions);
550 WARN("resp error(%d)", result);
551 res = IOTCON_RESPONSE_RESULT_ERROR;
555 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_GET, resp->payload, res,
557 if (IOTCON_ERROR_NONE != ret) {
558 ERR("_ocprocess_worker() Fail(%d)", ret);
559 icd_ioty_complete_error(ICD_CRUD_GET, ctx, ret);
560 return OC_STACK_DELETE_TRANSACTION;
563 return OC_STACK_DELETE_TRANSACTION;
567 OCStackApplicationResult icd_ioty_ocprocess_put_cb(void *ctx, OCDoHandle handle,
568 OCClientResponse *resp)
572 OCStackResult result;
573 GVariantBuilder *options;
575 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
577 if (NULL == resp->payload) {
578 ERR("payload is empty");
579 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, IOTCON_ERROR_IOTIVITY);
580 return OC_STACK_DELETE_TRANSACTION;
583 result = resp->result;
586 res = IOTCON_RESPONSE_RESULT_OK;
588 case OC_STACK_RESOURCE_CREATED:
589 res = IOTCON_RESPONSE_RESULT_RESOURCE_CREATED;
592 WARN("resp error(%d)", result);
593 res = IOTCON_RESPONSE_RESULT_ERROR;
597 if (IOTCON_RESPONSE_RESULT_ERROR != res) {
598 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
599 resp->numRcvdVendorSpecificHeaderOptions);
602 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_PUT, resp->payload, res,
604 if (IOTCON_ERROR_NONE != ret) {
605 ERR("_ocprocess_worker() Fail(%d)", ret);
606 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, ret);
607 return OC_STACK_DELETE_TRANSACTION;
610 return OC_STACK_DELETE_TRANSACTION;
614 OCStackApplicationResult icd_ioty_ocprocess_post_cb(void *ctx, OCDoHandle handle,
615 OCClientResponse *resp)
619 OCStackResult result;
620 GVariantBuilder *options;
622 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
624 if (NULL == resp->payload) {
625 ERR("payload is empty");
626 icd_ioty_complete_error(ICD_CRUD_POST, ctx, IOTCON_ERROR_IOTIVITY);
627 return OC_STACK_DELETE_TRANSACTION;
630 result = resp->result;
633 res = IOTCON_RESPONSE_RESULT_OK;
635 case OC_STACK_RESOURCE_CREATED:
636 res = IOTCON_RESPONSE_RESULT_RESOURCE_CREATED;
639 WARN("resp error(%d)", result);
640 res = IOTCON_RESPONSE_RESULT_ERROR;
644 if (IOTCON_RESPONSE_RESULT_ERROR != res) {
645 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
646 resp->numRcvdVendorSpecificHeaderOptions);
649 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_POST, resp->payload, res,
651 if (IOTCON_ERROR_NONE != ret) {
652 ERR("_ocprocess_worker() Fail(%d)", ret);
653 icd_ioty_complete_error(ICD_CRUD_POST, ctx, ret);
654 return OC_STACK_DELETE_TRANSACTION;
657 return OC_STACK_DELETE_TRANSACTION;
661 OCStackApplicationResult icd_ioty_ocprocess_delete_cb(void *ctx, OCDoHandle handle,
662 OCClientResponse *resp)
666 OCStackResult result;
667 GVariantBuilder *options;
669 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
671 if (NULL == resp->payload) {
672 ERR("payload is empty");
673 icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, IOTCON_ERROR_IOTIVITY);
674 return OC_STACK_DELETE_TRANSACTION;
677 result = resp->result;
680 res = IOTCON_RESPONSE_RESULT_OK;
682 case OC_STACK_RESOURCE_DELETED:
683 res = IOTCON_RESPONSE_RESULT_RESOURCE_DELETED;
686 WARN("resp error(%d)", result);
687 res = IOTCON_RESPONSE_RESULT_ERROR;
691 if (IOTCON_RESPONSE_RESULT_ERROR != res) {
692 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
693 resp->numRcvdVendorSpecificHeaderOptions);
696 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_DELETE, NULL, res, options, ctx);
697 if (IOTCON_ERROR_NONE != ret) {
698 ERR("_ocprocess_worker() Fail(%d)", ret);
699 icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, ret);
700 return OC_STACK_DELETE_TRANSACTION;
703 return OC_STACK_DELETE_TRANSACTION;
707 static int _worker_observe_cb(void *context)
711 struct icd_observe_context *ctx = context;
713 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
715 value = g_variant_new("(a(qs)vii)", ctx->options, ctx->payload, ctx->res,
718 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_OBSERVE, ctx->signum,
720 if (IOTCON_ERROR_NONE != ret)
721 ERR("_ocprocess_response_signal() Fail(%d)", ret);
723 /* ctx was allocated from icd_ioty_ocprocess_observe_cb() */
725 g_variant_builder_unref(ctx->options);
732 static void _observe_cb_response_error(const char *dest, unsigned int signum, int ret_val)
737 value = g_variant_new("(a(qs)vii)", NULL, NULL, ret_val, 0);
739 ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_OBSERVE, signum, value);
740 if (IOTCON_ERROR_NONE != ret)
741 ERR("_ocprocess_response_signal() Fail(%d)", ret);
745 OCStackApplicationResult icd_ioty_ocprocess_observe_cb(void *ctx, OCDoHandle handle,
746 OCClientResponse *resp)
749 OCStackResult result;
750 GVariantBuilder *options;
751 struct icd_observe_context *observe_ctx;
752 icd_sig_ctx_s *sig_context = ctx;
754 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
756 if (NULL == resp->payload) {
757 ERR("payload is empty");
758 _observe_cb_response_error(sig_context->bus_name, sig_context->signum,
759 IOTCON_ERROR_IOTIVITY);
760 return OC_STACK_KEEP_TRANSACTION;
763 observe_ctx = calloc(1, sizeof(struct icd_observe_context));
764 if (NULL == observe_ctx) {
765 ERR("calloc() Fail(%d)", errno);
766 _observe_cb_response_error(sig_context->bus_name, sig_context->signum,
767 IOTCON_ERROR_OUT_OF_MEMORY);
768 return OC_STACK_KEEP_TRANSACTION;
771 result = resp->result;
772 if (OC_STACK_OK == result) {
773 res = IOTCON_RESPONSE_RESULT_OK;
774 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
775 resp->numRcvdVendorSpecificHeaderOptions);
777 WARN("resp error(%d)", result);
778 res = IOTCON_RESPONSE_RESULT_ERROR;
782 observe_ctx->payload = icd_payload_to_gvariant(resp->payload);
783 observe_ctx->signum = sig_context->signum;
784 observe_ctx->res = res;
785 observe_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
786 observe_ctx->options = options;
788 ret = _ocprocess_worker_start(_worker_observe_cb, observe_ctx);
789 if (IOTCON_ERROR_NONE != ret) {
790 ERR("_ocprocess_worker_start() Fail(%d)", ret);
791 _observe_cb_response_error(sig_context->bus_name, sig_context->signum, ret);
792 free(observe_ctx->bus_name);
793 if (observe_ctx->payload)
794 g_variant_unref(observe_ctx->payload);
795 g_variant_builder_unref(observe_ctx->options);
797 return OC_STACK_KEEP_TRANSACTION;
800 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
801 /* DO NOT FREE observe_ctx. It MUST be freed in the _worker_observe_cb func */
803 return OC_STACK_KEEP_TRANSACTION;
807 static int _worker_presence_cb(void *context)
812 char addr[PATH_MAX] = {0};
813 struct icd_presence_context *ctx = context;
815 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
817 snprintf(addr, sizeof(addr), "%s:%d", ctx->dev_addr->addr, ctx->dev_addr->port);
819 value = g_variant_new("(ius)", ctx->result, ctx->nonce, addr);
821 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_PRESENCE, ctx->signum,
823 if (IOTCON_ERROR_NONE != ret)
824 ERR("_ocprocess_response_signal() Fail(%d)", ret);
826 /* ctx was allocated from icd_ioty_ocprocess_presence_cb() */
835 static void _presence_cb_response_error(const char *dest, unsigned int signum,
842 value = g_variant_new("(ius)", ret_val, 0, IC_STR_NULL);
844 ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_PRESENCE, signum, value);
845 if (IOTCON_ERROR_NONE != ret)
846 ERR("_ocprocess_response_signal() Fail(%d)", ret);
850 OCStackApplicationResult icd_ioty_ocprocess_presence_cb(void *ctx, OCDoHandle handle,
851 OCClientResponse *resp)
856 icd_sig_ctx_s *sig_context = ctx;
857 struct icd_presence_context *presence_ctx;
859 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
860 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
862 presence_ctx = calloc(1, sizeof(struct icd_presence_context));
863 if (NULL == presence_ctx) {
864 ERR("calloc() Fail(%d)", errno);
865 _presence_cb_response_error(sig_context->bus_name, sig_context->signum,
866 IOTCON_ERROR_OUT_OF_MEMORY);
867 return OC_STACK_KEEP_TRANSACTION;
870 dev_addr = calloc(1, sizeof(OCDevAddr));
871 if (NULL == dev_addr) {
872 ERR("calloc() Fail(%d)", errno);
873 _presence_cb_response_error(sig_context->bus_name, sig_context->signum,
874 IOTCON_ERROR_OUT_OF_MEMORY);
876 return OC_STACK_KEEP_TRANSACTION;
878 memcpy(dev_addr, &resp->devAddr, sizeof(OCDevAddr));
880 switch (resp->result) {
882 presence_ctx->result = IOTCON_PRESENCE_OK;
884 case OC_STACK_PRESENCE_STOPPED:
885 presence_ctx->result = IOTCON_PRESENCE_STOPPED;
887 case OC_STACK_PRESENCE_TIMEOUT:
888 presence_ctx->result = IOTCON_PRESENCE_TIMEOUT;
892 DBG("Presence error(%d)", resp->result);
893 presence_ctx->result = IOTCON_ERROR_IOTIVITY;
896 presence_ctx->signum = sig_context->signum;
897 presence_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
898 presence_ctx->nonce = resp->sequenceNumber;
899 presence_ctx->dev_addr = dev_addr;
901 ret = _ocprocess_worker_start(_worker_presence_cb, presence_ctx);
902 if (IOTCON_ERROR_NONE != ret) {
903 ERR("_ocprocess_worker_start() Fail(%d)", ret);
904 _presence_cb_response_error(sig_context->bus_name, sig_context->signum, ret);
905 free(presence_ctx->bus_name);
906 free(presence_ctx->dev_addr);
908 return OC_STACK_KEEP_TRANSACTION;
911 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
912 /* DO NOT FREE presence_ctx. It MUST be freed in the _worker_presence_cb func */
914 return OC_STACK_KEEP_TRANSACTION;
918 OCStackApplicationResult icd_ioty_ocprocess_info_cb(void *ctx, OCDoHandle handle,
919 OCClientResponse *resp)
923 struct icd_info_context *info_ctx;
924 icd_sig_ctx_s *sig_context = ctx;
926 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
927 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
928 RETV_IF(NULL == resp->payload, OC_STACK_KEEP_TRANSACTION);
930 if (PAYLOAD_TYPE_DEVICE == resp->payload->type)
931 info_type = ICD_DEVICE_INFO;
932 else if (PAYLOAD_TYPE_PLATFORM == resp->payload->type)
933 info_type = ICD_PLATFORM_INFO;
935 return OC_STACK_KEEP_TRANSACTION;
937 info_ctx = calloc(1, sizeof(struct icd_info_context));
938 if (NULL == info_ctx) {
939 ERR("calloc() Fail(%d)", errno);
940 return OC_STACK_KEEP_TRANSACTION;
943 info_ctx->info_type = info_type;
944 info_ctx->payload = icd_payload_to_gvariant(resp->payload);
945 info_ctx->signum = sig_context->signum;
946 info_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
948 ret = _ocprocess_worker_start(_worker_info_cb, info_ctx);
949 if (IOTCON_ERROR_NONE != ret) {
950 ERR("_ocprocess_worker_start() Fail(%d)", ret);
951 free(info_ctx->bus_name);
952 if (info_ctx->payload)
953 g_variant_unref(info_ctx->payload);
955 return OC_STACK_KEEP_TRANSACTION;
958 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
959 /* DO NOT FREE info_ctx. It MUST be freed in the _worker_info_cb func */
961 return OC_STACK_KEEP_TRANSACTION;
965 static int _worker_tizen_info_handler(void *context)
969 char *tizen_device_id;
970 OCStackResult result;
971 OCRepPayload *payload;
972 OCEntityHandlerResponse response = {0};
973 struct icd_tizen_info_context *ctx = context;
975 response.requestHandle = ctx->request_h;
976 response.resourceHandle = ctx->resource_h;
977 response.ehResult = OC_EH_OK;
980 ret = icd_ioty_tizen_info_get_property(&device_name, &tizen_device_id);
981 if (IOTCON_ERROR_NONE != ret) {
982 ERR("icd_ioty_tizen_info_get_property() Fail(%d)", ret);
983 response.ehResult = OC_EH_ERROR;
987 payload = OCRepPayloadCreate();
988 OCRepPayloadSetUri(payload, ICD_IOTY_TIZEN_INFO_URI);
989 OCRepPayloadAddResourceType(payload, ICD_IOTY_TIZEN_INFO_TYPE);
990 OCRepPayloadAddInterface(payload, IC_INTERFACE_DEFAULT);
992 OCRepPayloadSetPropString(payload, ICD_IOTY_TIZEN_INFO_DEVICE_NAME,
993 ic_utils_dbus_encode_str(device_name));
994 OCRepPayloadSetPropString(payload, ICD_IOTY_TIZEN_INFO_TIZEN_DEVICE_ID,
995 ic_utils_dbus_encode_str(tizen_device_id));
996 response.payload = (OCPayload*)payload;
998 icd_ioty_csdk_lock();
999 result = OCDoResponse(&response);
1000 icd_ioty_csdk_unlock();
1002 if (OC_STACK_OK != result) {
1003 ERR("OCDoResponse() Fail(%d)", result);
1005 return IOTCON_ERROR_IOTIVITY;
1009 return IOTCON_ERROR_NONE;
1013 OCEntityHandlerResult icd_ioty_ocprocess_tizen_info_handler(OCEntityHandlerFlag flag,
1014 OCEntityHandlerRequest *request, void *user_data)
1017 struct icd_tizen_info_context *tizen_info_ctx;
1019 if ((0 == (OC_REQUEST_FLAG & flag)) || (OC_REST_GET != request->method)) {
1020 ERR("Prohibited Action");
1021 return OC_EH_FORBIDDEN;
1024 tizen_info_ctx = calloc(1, sizeof(struct icd_tizen_info_context));
1025 if (NULL == tizen_info_ctx) {
1026 ERR("calloc() Fail(%d)", errno);
1030 tizen_info_ctx->request_h = request->requestHandle;
1031 tizen_info_ctx->resource_h = request->resource;
1033 ret = _ocprocess_worker_start(_worker_tizen_info_handler, tizen_info_ctx);
1034 if (IOTCON_ERROR_NONE != ret) {
1035 ERR("_ocprocess_worker_start() Fail(%d)", ret);
1036 free(tizen_info_ctx);
1044 OCStackApplicationResult icd_ioty_ocprocess_get_tizen_info_cb(void *ctx,
1045 OCDoHandle handle, OCClientResponse *resp)
1049 char *tizen_device_id;
1050 GVariant *tizen_info;
1051 OCRepPayload *payload;
1052 OCRepPayloadValue *val;
1054 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
1056 if (NULL == resp->payload) {
1057 ERR("payload is empty");
1058 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1059 return OC_STACK_DELETE_TRANSACTION;
1062 payload = (OCRepPayload*)resp->payload;
1063 val = payload->values;
1065 ERR("Invalid payload");
1066 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1067 return OC_STACK_DELETE_TRANSACTION;
1069 device_name = val->str;
1073 ERR("Invalid Payload");
1074 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1075 return OC_STACK_DELETE_TRANSACTION;
1078 tizen_device_id = val->str;
1080 if (OC_STACK_OK == resp->result)
1081 res = IOTCON_RESPONSE_RESULT_OK;
1083 res = IOTCON_RESPONSE_RESULT_ERROR;
1085 tizen_info = g_variant_new("(ssi)", device_name, tizen_device_id, res);
1087 icd_ioty_complete(ICD_TIZEN_INFO, ctx, tizen_info);
1089 return OC_STACK_DELETE_TRANSACTION;