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;
60 struct icd_find_context {
68 struct icd_crud_context {
72 GVariantBuilder *options;
73 GDBusMethodInvocation *invocation;
77 struct icd_info_context {
85 struct icd_tizen_info_context {
86 OCRequestHandle request_h;
87 OCResourceHandle resource_h;
88 GDBusMethodInvocation *invocation;
92 struct icd_observe_context {
98 GVariantBuilder *options;
102 struct icd_presence_context {
111 void icd_ioty_ocprocess_stop()
117 static void* _ocprocess_worker_thread(void *data)
120 struct icd_ioty_worker *worker = data;
123 ERR("worker is NULL");
127 ret = worker->cb(worker->ctx);
128 if (IOTCON_ERROR_NONE != ret)
129 ERR("cb() Fail(%d)", ret);
131 /* worker was allocated from _ocprocess_worker_start() */
134 /* GCC warning happen if use g_thread_exit() */
139 static int _ocprocess_worker_start(_ocprocess_cb cb, void *ctx)
143 struct icd_ioty_worker *worker;
145 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
147 worker = calloc(1, sizeof(struct icd_ioty_worker));
148 if (NULL == worker) {
149 ERR("calloc() Fail(%d)", errno);
150 return IOTCON_ERROR_OUT_OF_MEMORY;
156 /* TODO : consider thread pool mechanism */
157 thread = g_thread_try_new("worker_thread", _ocprocess_worker_thread, worker, &error);
158 if (NULL == thread) {
159 ERR("g_thread_try_new() Fail(%s)", error->message);
162 return IOTCON_ERROR_SYSTEM;
165 /* DO NOT join thread. It was already detached by calling g_thread_unref() */
166 g_thread_unref(thread);
168 /* DO NOT FREE worker. It MUST be freed in the _ocprocess_worker_thread() */
170 return IOTCON_ERROR_NONE;
174 static int _ocprocess_response_signal(const char *dest, const char *signal,
175 unsigned int signum, GVariant *value)
178 char sig_name[IC_DBUS_SIGNAL_LENGTH] = {0};
180 ret = snprintf(sig_name, sizeof(sig_name), "%s_%u", signal, signum);
181 if (ret <= 0 || sizeof(sig_name) <= ret) {
182 ERR("snprintf() Fail(%d)", ret);
183 return IOTCON_ERROR_IO_ERROR;
186 ret = icd_dbus_emit_signal(dest, sig_name, value);
187 if (IOTCON_ERROR_NONE != ret) {
188 ERR("icd_dbus_emit_signal() Fail(%d)", ret);
192 return IOTCON_ERROR_NONE;
196 static inline GVariantBuilder* _ocprocess_parse_header_options(
197 OCHeaderOption *oic_option, int option_size)
200 GVariantBuilder *options;
202 options = g_variant_builder_new(G_VARIANT_TYPE("a(qs)"));
203 for (i = 0; i < option_size; i++) {
204 g_variant_builder_add(options, "(qs)", oic_option[i].optionID,
205 oic_option[i].optionData);
212 static int _worker_req_handler(void *context)
216 struct icd_req_context *ctx = context;
217 GVariantBuilder payload_builder;
218 char addr[PATH_MAX] = {0};
220 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
222 g_variant_builder_init(&payload_builder, G_VARIANT_TYPE("av"));
224 g_variant_builder_add(&payload_builder, "v", ctx->payload);
226 if (ctx->dev_addr->addr && *ctx->dev_addr->addr)
227 snprintf(addr, sizeof(addr), "%s:%d", ctx->dev_addr->addr, ctx->dev_addr->port);
229 value = g_variant_new("(sia(qs)a(ss)iiavxx)",
237 ICD_POINTER_TO_INT64(ctx->request_h),
238 ICD_POINTER_TO_INT64(ctx->resource_h));
240 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_REQUEST_HANDLER,
242 if (IOTCON_ERROR_NONE != ret)
243 ERR("_ocprocess_response_signal() Fail(%d)", ret);
246 g_variant_builder_unref(ctx->options);
247 g_variant_builder_unref(ctx->query);
255 OCEntityHandlerResult icd_ioty_ocprocess_req_handler(OCEntityHandlerFlag flag,
256 OCEntityHandlerRequest *request, void *user_data)
260 unsigned int signal_number;
261 char *query_str, *query_key, *query_value;
262 char *token, *save_ptr1, *save_ptr2;
263 char *bus_name = NULL;
264 struct icd_req_context *req_ctx;
267 RETV_IF(NULL == request, OC_EH_ERROR);
269 req_ctx = calloc(1, sizeof(struct icd_req_context));
270 if (NULL == req_ctx) {
271 ERR("calloc() Fail(%d)", errno);
276 req_ctx->request_h = request->requestHandle;
277 req_ctx->resource_h = request->resource;
279 ret = icd_dbus_client_list_get_info(req_ctx->resource_h, &signal_number, &bus_name);
280 if (IOTCON_ERROR_NONE != ret) {
281 ERR("icd_dbus_client_list_get_info() Fail(%d)", ret);
286 /* signal number & bus_name */
287 req_ctx->signum = signal_number;
288 req_ctx->bus_name = bus_name;
290 dev_addr = calloc(1, sizeof(OCDevAddr));
291 if (NULL == dev_addr) {
292 ERR("calloc() Fail(%d)", errno);
296 memcpy(dev_addr, &request->devAddr, sizeof(OCDevAddr));
297 req_ctx->dev_addr = dev_addr;
300 if (OC_REQUEST_FLAG & flag) {
301 switch (request->method) {
303 req_ctx->types = IOTCON_REQUEST_GET;
304 req_ctx->payload = NULL;
306 if (OC_OBSERVE_FLAG & flag) {
307 req_ctx->types |= IOTCON_REQUEST_OBSERVE;
308 /* observation info*/
309 req_ctx->observer_id = request->obsInfo.obsId;
310 req_ctx->observe_action = request->obsInfo.action;
314 req_ctx->types = IOTCON_REQUEST_PUT;
315 req_ctx->payload = icd_payload_to_gvariant(request->payload);
318 req_ctx->types = IOTCON_REQUEST_POST;
319 req_ctx->payload = icd_payload_to_gvariant(request->payload);
322 req_ctx->types = IOTCON_REQUEST_DELETE;
323 req_ctx->payload = NULL;
326 free(req_ctx->bus_name);
333 req_ctx->options = _ocprocess_parse_header_options(
334 request->rcvdVendorSpecificHeaderOptions,
335 request->numRcvdVendorSpecificHeaderOptions);
338 req_ctx->query = g_variant_builder_new(G_VARIANT_TYPE("a(ss)"));
339 query_str = request->query;
340 while ((token = strtok_r(query_str, "&;", &save_ptr1))) {
341 while ((query_key = strtok_r(token, "=", &save_ptr2))) {
343 query_value = strtok_r(token, "=", &save_ptr2);
344 if (NULL == query_value)
347 g_variant_builder_add(req_ctx->query, "(ss)", query_key, query_value);
352 ret = _ocprocess_worker_start(_worker_req_handler, req_ctx);
353 if (IOTCON_ERROR_NONE != ret) {
354 ERR("_ocprocess_worker_start() Fail(%d)", ret);
355 free(req_ctx->bus_name);
356 if (req_ctx->payload)
357 g_variant_unref(req_ctx->payload);
358 g_variant_builder_unref(req_ctx->options);
359 g_variant_builder_unref(req_ctx->query);
360 free(req_ctx->dev_addr);
365 /* DO NOT FREE req_ctx. It MUST be freed in the _worker_req_handler func */
371 gpointer icd_ioty_ocprocess_thread(gpointer data)
374 OCStackResult result;
377 while (icd_ioty_alive) {
378 icd_ioty_csdk_lock();
379 result = OCProcess();
380 icd_ioty_csdk_unlock();
381 if (OC_STACK_OK != result) {
382 ERR("OCProcess() Fail(%d)", result);
386 /* TODO : SHOULD revise time or usleep */
394 static int _worker_find_cb(void *context)
398 struct icd_find_context *ctx = context;
400 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
402 for (i = 0; ctx->payload[i]; i++) {
403 value = g_variant_new("(vi)", ctx->payload[i], ctx->conn_type);
404 /* TODO : If one device has multi resources, it comes as bulk data.
405 * To reduce the number of emit_signal, let's send signal only one time for one device.
406 * for ex, client list. */
407 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_FOUND_RESOURCE,
409 if (IOTCON_ERROR_NONE != ret) {
410 ERR("_ocprocess_response_signal() Fail(%d)", ret);
411 g_variant_unref(value);
416 /* ctx was allocated from icd_ioty_ocprocess_find_cb() */
424 OCStackApplicationResult icd_ioty_ocprocess_find_cb(void *ctx, OCDoHandle handle,
425 OCClientResponse *resp)
428 struct icd_find_context *find_ctx;
429 icd_sig_ctx_s *sig_context = ctx;
431 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
432 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
433 if (NULL == resp->payload)
434 /* normal case : payload COULD be NULL */
435 return OC_STACK_KEEP_TRANSACTION;
436 RETVM_IF(PAYLOAD_TYPE_DISCOVERY != resp->payload->type,
437 OC_STACK_KEEP_TRANSACTION, "Invalid payload type(%d)", resp->payload->type);
439 find_ctx = calloc(1, sizeof(struct icd_find_context));
440 if (NULL == find_ctx) {
441 ERR("calloc() Fail(%d)", errno);
442 return OC_STACK_KEEP_TRANSACTION;
445 find_ctx->signum = sig_context->signum;
446 find_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
447 find_ctx->payload = icd_payload_res_to_gvariant(resp->payload, &resp->devAddr);
448 find_ctx->conn_type = icd_ioty_transport_flag_to_conn_type(resp->devAddr.adapter,
449 resp->devAddr.flags);
451 ret = _ocprocess_worker_start(_worker_find_cb, find_ctx);
452 if (IOTCON_ERROR_NONE != ret) {
453 ERR("_ocprocess_worker_start() Fail(%d)", ret);
454 free(find_ctx->bus_name);
455 ic_utils_gvariant_array_free(find_ctx->payload);
457 return OC_STACK_KEEP_TRANSACTION;
460 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
461 /* DO NOT FREE find_ctx. It MUST be freed in the _worker_find_cb func */
463 return OC_STACK_KEEP_TRANSACTION;
467 static int _worker_crud_cb(void *context)
470 struct icd_crud_context *ctx = context;
472 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
474 if (ICD_CRUD_DELETE == ctx->crud_type)
475 value = g_variant_new("(a(qs)i)", ctx->options, ctx->res);
477 value = g_variant_new("(a(qs)vi)", ctx->options, ctx->payload, ctx->res);
478 icd_ioty_complete(ctx->crud_type, ctx->invocation, value);
480 /* ctx was allocated from icd_ioty_ocprocess_xxx_cb() */
481 g_variant_builder_unref(ctx->options);
484 return IOTCON_ERROR_NONE;
488 static int _worker_info_cb(void *context)
491 const char *sig_name = NULL;
492 struct icd_info_context *ctx = context;
494 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
496 if (ICD_DEVICE_INFO == ctx->info_type)
497 sig_name = IC_DBUS_SIGNAL_DEVICE;
498 else if (ICD_PLATFORM_INFO == ctx->info_type)
499 sig_name = IC_DBUS_SIGNAL_PLATFORM;
501 ret = _ocprocess_response_signal(ctx->bus_name, sig_name, ctx->signum, ctx->payload);
502 if (IOTCON_ERROR_NONE != ret)
503 ERR("_ocprocess_response_signal() Fail(%d)", ret);
505 /* ctx was allocated from icd_ioty_ocprocess_info_cb() */
513 static int _ocprocess_worker(_ocprocess_cb cb, int type, OCPayload *payload, int res,
514 GVariantBuilder *options, void *ctx)
517 struct icd_crud_context *crud_ctx;
519 crud_ctx = calloc(1, sizeof(struct icd_crud_context));
520 if (NULL == crud_ctx) {
521 ERR("calloc() Fail(%d)", errno);
522 return IOTCON_ERROR_OUT_OF_MEMORY;
525 crud_ctx->crud_type = type;
526 crud_ctx->payload = icd_payload_to_gvariant(payload);
528 crud_ctx->options = options;
529 crud_ctx->invocation = ctx;
531 ret = _ocprocess_worker_start(cb, crud_ctx);
532 if (IOTCON_ERROR_NONE != ret) {
533 ERR("_ocprocess_worker_start() Fail(%d)", ret);
534 if (crud_ctx->payload)
535 g_variant_unref(crud_ctx->payload);
536 g_variant_builder_unref(crud_ctx->options);
540 /* DO NOT FREE crud_ctx. It MUST be freed in the _worker_crud_cb func */
546 static int _ocprocess_parse_oic_result(OCStackResult result)
552 res = IOTCON_RESPONSE_RESULT_OK;
554 case OC_STACK_RESOURCE_CREATED:
555 res = IOTCON_RESPONSE_RESULT_RESOURCE_CREATED;
557 case OC_STACK_RESOURCE_DELETED:
558 res = IOTCON_RESPONSE_RESULT_RESOURCE_DELETED;
560 case OC_STACK_UNAUTHORIZED_REQ:
561 res = IOTCON_RESPONSE_RESULT_FORBIDDEN;
564 WARN("response error(%d)", result);
565 res = IOTCON_RESPONSE_RESULT_ERROR;
573 OCStackApplicationResult icd_ioty_ocprocess_get_cb(void *ctx, OCDoHandle handle,
574 OCClientResponse *resp)
578 GVariantBuilder *options;
580 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
582 if (NULL == resp->payload) {
583 ERR("payload is empty");
584 icd_ioty_complete_error(ICD_CRUD_GET, ctx, IOTCON_ERROR_IOTIVITY);
585 return OC_STACK_DELETE_TRANSACTION;
588 res = _ocprocess_parse_oic_result(resp->result);
590 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
591 resp->numRcvdVendorSpecificHeaderOptions);
593 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_GET, resp->payload, res,
595 if (IOTCON_ERROR_NONE != ret) {
596 ERR("_ocprocess_worker() Fail(%d)", ret);
597 icd_ioty_complete_error(ICD_CRUD_GET, ctx, ret);
598 return OC_STACK_DELETE_TRANSACTION;
601 return OC_STACK_DELETE_TRANSACTION;
605 OCStackApplicationResult icd_ioty_ocprocess_put_cb(void *ctx, OCDoHandle handle,
606 OCClientResponse *resp)
610 GVariantBuilder *options;
612 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
614 if (NULL == resp->payload) {
615 ERR("payload is empty");
616 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, IOTCON_ERROR_IOTIVITY);
617 return OC_STACK_DELETE_TRANSACTION;
620 res = _ocprocess_parse_oic_result(resp->result);
622 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
623 resp->numRcvdVendorSpecificHeaderOptions);
625 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_PUT, resp->payload, res,
627 if (IOTCON_ERROR_NONE != ret) {
628 ERR("_ocprocess_worker() Fail(%d)", ret);
629 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, ret);
630 return OC_STACK_DELETE_TRANSACTION;
633 return OC_STACK_DELETE_TRANSACTION;
637 OCStackApplicationResult icd_ioty_ocprocess_post_cb(void *ctx, OCDoHandle handle,
638 OCClientResponse *resp)
642 GVariantBuilder *options;
644 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
646 if (NULL == resp->payload) {
647 ERR("payload is empty");
648 icd_ioty_complete_error(ICD_CRUD_POST, ctx, IOTCON_ERROR_IOTIVITY);
649 return OC_STACK_DELETE_TRANSACTION;
652 res = _ocprocess_parse_oic_result(resp->result);
654 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
655 resp->numRcvdVendorSpecificHeaderOptions);
657 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_POST, resp->payload, res,
659 if (IOTCON_ERROR_NONE != ret) {
660 ERR("_ocprocess_worker() Fail(%d)", ret);
661 icd_ioty_complete_error(ICD_CRUD_POST, ctx, ret);
662 return OC_STACK_DELETE_TRANSACTION;
665 return OC_STACK_DELETE_TRANSACTION;
669 OCStackApplicationResult icd_ioty_ocprocess_delete_cb(void *ctx, OCDoHandle handle,
670 OCClientResponse *resp)
674 GVariantBuilder *options;
676 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
678 if (NULL == resp->payload) {
679 ERR("payload is empty");
680 icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, IOTCON_ERROR_IOTIVITY);
681 return OC_STACK_DELETE_TRANSACTION;
684 res = _ocprocess_parse_oic_result(resp->result);
686 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
687 resp->numRcvdVendorSpecificHeaderOptions);
689 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_DELETE, NULL, res, options, ctx);
690 if (IOTCON_ERROR_NONE != ret) {
691 ERR("_ocprocess_worker() Fail(%d)", ret);
692 icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, ret);
693 return OC_STACK_DELETE_TRANSACTION;
696 return OC_STACK_DELETE_TRANSACTION;
700 static int _worker_observe_cb(void *context)
704 struct icd_observe_context *ctx = context;
706 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
708 value = g_variant_new("(a(qs)vii)", ctx->options, ctx->payload, ctx->res,
711 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_OBSERVE, ctx->signum,
713 if (IOTCON_ERROR_NONE != ret)
714 ERR("_ocprocess_response_signal() Fail(%d)", ret);
716 /* ctx was allocated from icd_ioty_ocprocess_observe_cb() */
718 g_variant_builder_unref(ctx->options);
725 static void _observe_cb_response_error(const char *dest, unsigned int signum, int ret_val)
730 GVariantBuilder options;
732 g_variant_builder_init(&options, G_VARIANT_TYPE("a(qs)"));
733 payload = icd_payload_representation_empty_gvariant();
735 value = g_variant_new("(a(qs)vii)", &options, payload, ret_val, 0);
737 ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_OBSERVE, signum, value);
738 if (IOTCON_ERROR_NONE != ret)
739 ERR("_ocprocess_response_signal() Fail(%d)", ret);
743 OCStackApplicationResult icd_ioty_ocprocess_observe_cb(void *ctx, OCDoHandle handle,
744 OCClientResponse *resp)
747 GVariantBuilder *options;
748 struct icd_observe_context *observe_ctx;
749 icd_sig_ctx_s *sig_context = ctx;
751 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
753 if (NULL == resp->payload) {
754 ERR("payload is empty");
755 _observe_cb_response_error(sig_context->bus_name, sig_context->signum,
756 IOTCON_ERROR_IOTIVITY);
757 return OC_STACK_KEEP_TRANSACTION;
760 observe_ctx = calloc(1, sizeof(struct icd_observe_context));
761 if (NULL == observe_ctx) {
762 ERR("calloc() Fail(%d)", errno);
763 _observe_cb_response_error(sig_context->bus_name, sig_context->signum,
764 IOTCON_ERROR_OUT_OF_MEMORY);
765 return OC_STACK_KEEP_TRANSACTION;
768 res = _ocprocess_parse_oic_result(resp->result);
770 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
771 resp->numRcvdVendorSpecificHeaderOptions);
773 observe_ctx->payload = icd_payload_to_gvariant(resp->payload);
774 observe_ctx->signum = sig_context->signum;
775 observe_ctx->res = res;
776 observe_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
777 observe_ctx->options = options;
779 ret = _ocprocess_worker_start(_worker_observe_cb, observe_ctx);
780 if (IOTCON_ERROR_NONE != ret) {
781 ERR("_ocprocess_worker_start() Fail(%d)", ret);
782 _observe_cb_response_error(sig_context->bus_name, sig_context->signum, ret);
783 free(observe_ctx->bus_name);
784 if (observe_ctx->payload)
785 g_variant_unref(observe_ctx->payload);
786 g_variant_builder_unref(observe_ctx->options);
788 return OC_STACK_KEEP_TRANSACTION;
791 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
792 /* DO NOT FREE observe_ctx. It MUST be freed in the _worker_observe_cb func */
794 return OC_STACK_KEEP_TRANSACTION;
798 static int _worker_presence_cb(void *context)
803 char addr[PATH_MAX] = {0};
804 struct icd_presence_context *ctx = context;
806 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
808 snprintf(addr, sizeof(addr), "%s:%d", ctx->dev_addr->addr, ctx->dev_addr->port);
810 value = g_variant_new("(ius)", ctx->result, ctx->nonce, addr);
812 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_PRESENCE, ctx->signum,
814 if (IOTCON_ERROR_NONE != ret)
815 ERR("_ocprocess_response_signal() Fail(%d)", ret);
817 /* ctx was allocated from icd_ioty_ocprocess_presence_cb() */
826 static void _presence_cb_response_error(const char *dest, unsigned int signum,
833 value = g_variant_new("(ius)", ret_val, 0, IC_STR_NULL);
835 ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_PRESENCE, signum, value);
836 if (IOTCON_ERROR_NONE != ret)
837 ERR("_ocprocess_response_signal() Fail(%d)", ret);
841 OCStackApplicationResult icd_ioty_ocprocess_presence_cb(void *ctx, OCDoHandle handle,
842 OCClientResponse *resp)
847 icd_sig_ctx_s *sig_context = ctx;
848 struct icd_presence_context *presence_ctx;
850 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
851 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
853 presence_ctx = calloc(1, sizeof(struct icd_presence_context));
854 if (NULL == presence_ctx) {
855 ERR("calloc() Fail(%d)", errno);
856 _presence_cb_response_error(sig_context->bus_name, sig_context->signum,
857 IOTCON_ERROR_OUT_OF_MEMORY);
858 return OC_STACK_KEEP_TRANSACTION;
861 dev_addr = calloc(1, sizeof(OCDevAddr));
862 if (NULL == dev_addr) {
863 ERR("calloc() Fail(%d)", errno);
864 _presence_cb_response_error(sig_context->bus_name, sig_context->signum,
865 IOTCON_ERROR_OUT_OF_MEMORY);
867 return OC_STACK_KEEP_TRANSACTION;
869 memcpy(dev_addr, &resp->devAddr, sizeof(OCDevAddr));
871 switch (resp->result) {
873 presence_ctx->result = IOTCON_PRESENCE_OK;
875 case OC_STACK_PRESENCE_STOPPED:
876 presence_ctx->result = IOTCON_PRESENCE_STOPPED;
878 case OC_STACK_PRESENCE_TIMEOUT:
879 presence_ctx->result = IOTCON_PRESENCE_TIMEOUT;
883 DBG("Presence error(%d)", resp->result);
884 presence_ctx->result = IOTCON_ERROR_IOTIVITY;
887 presence_ctx->signum = sig_context->signum;
888 presence_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
889 presence_ctx->nonce = resp->sequenceNumber;
890 presence_ctx->dev_addr = dev_addr;
892 ret = _ocprocess_worker_start(_worker_presence_cb, presence_ctx);
893 if (IOTCON_ERROR_NONE != ret) {
894 ERR("_ocprocess_worker_start() Fail(%d)", ret);
895 _presence_cb_response_error(sig_context->bus_name, sig_context->signum, ret);
896 free(presence_ctx->bus_name);
897 free(presence_ctx->dev_addr);
899 return OC_STACK_KEEP_TRANSACTION;
902 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
903 /* DO NOT FREE presence_ctx. It MUST be freed in the _worker_presence_cb func */
905 return OC_STACK_KEEP_TRANSACTION;
909 OCStackApplicationResult icd_ioty_ocprocess_info_cb(void *ctx, OCDoHandle handle,
910 OCClientResponse *resp)
914 struct icd_info_context *info_ctx;
915 icd_sig_ctx_s *sig_context = ctx;
917 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
918 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
919 RETV_IF(NULL == resp->payload, OC_STACK_KEEP_TRANSACTION);
921 if (PAYLOAD_TYPE_DEVICE == resp->payload->type)
922 info_type = ICD_DEVICE_INFO;
923 else if (PAYLOAD_TYPE_PLATFORM == resp->payload->type)
924 info_type = ICD_PLATFORM_INFO;
926 return OC_STACK_KEEP_TRANSACTION;
928 info_ctx = calloc(1, sizeof(struct icd_info_context));
929 if (NULL == info_ctx) {
930 ERR("calloc() Fail(%d)", errno);
931 return OC_STACK_KEEP_TRANSACTION;
934 info_ctx->info_type = info_type;
935 info_ctx->payload = icd_payload_to_gvariant(resp->payload);
936 info_ctx->signum = sig_context->signum;
937 info_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
939 ret = _ocprocess_worker_start(_worker_info_cb, info_ctx);
940 if (IOTCON_ERROR_NONE != ret) {
941 ERR("_ocprocess_worker_start() Fail(%d)", ret);
942 free(info_ctx->bus_name);
943 if (info_ctx->payload)
944 g_variant_unref(info_ctx->payload);
946 return OC_STACK_KEEP_TRANSACTION;
949 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
950 /* DO NOT FREE info_ctx. It MUST be freed in the _worker_info_cb func */
952 return OC_STACK_KEEP_TRANSACTION;
956 static int _worker_tizen_info_handler(void *context)
960 char *tizen_device_id;
961 OCStackResult result;
962 OCRepPayload *payload;
963 OCEntityHandlerResponse response = {0};
964 struct icd_tizen_info_context *ctx = context;
966 response.requestHandle = ctx->request_h;
967 response.resourceHandle = ctx->resource_h;
968 response.ehResult = OC_EH_OK;
971 ret = icd_ioty_tizen_info_get_property(&device_name, &tizen_device_id);
972 if (IOTCON_ERROR_NONE != ret) {
973 ERR("icd_ioty_tizen_info_get_property() Fail(%d)", ret);
974 response.ehResult = OC_EH_ERROR;
978 payload = OCRepPayloadCreate();
979 OCRepPayloadSetUri(payload, ICD_IOTY_TIZEN_INFO_URI);
980 OCRepPayloadAddResourceType(payload, ICD_IOTY_TIZEN_INFO_TYPE);
981 OCRepPayloadAddInterface(payload, IC_INTERFACE_DEFAULT);
983 OCRepPayloadSetPropString(payload, ICD_IOTY_TIZEN_INFO_DEVICE_NAME,
984 ic_utils_dbus_encode_str(device_name));
985 OCRepPayloadSetPropString(payload, ICD_IOTY_TIZEN_INFO_TIZEN_DEVICE_ID,
986 ic_utils_dbus_encode_str(tizen_device_id));
987 response.payload = (OCPayload*)payload;
989 icd_ioty_csdk_lock();
990 result = OCDoResponse(&response);
991 icd_ioty_csdk_unlock();
993 if (OC_STACK_OK != result) {
994 ERR("OCDoResponse() Fail(%d)", result);
996 return IOTCON_ERROR_IOTIVITY;
1000 return IOTCON_ERROR_NONE;
1004 OCEntityHandlerResult icd_ioty_ocprocess_tizen_info_handler(OCEntityHandlerFlag flag,
1005 OCEntityHandlerRequest *request, void *user_data)
1008 struct icd_tizen_info_context *tizen_info_ctx;
1010 if ((0 == (OC_REQUEST_FLAG & flag)) || (OC_REST_GET != request->method)) {
1011 ERR("Prohibited Action");
1012 return OC_EH_FORBIDDEN;
1015 tizen_info_ctx = calloc(1, sizeof(struct icd_tizen_info_context));
1016 if (NULL == tizen_info_ctx) {
1017 ERR("calloc() Fail(%d)", errno);
1021 tizen_info_ctx->request_h = request->requestHandle;
1022 tizen_info_ctx->resource_h = request->resource;
1024 ret = _ocprocess_worker_start(_worker_tizen_info_handler, tizen_info_ctx);
1025 if (IOTCON_ERROR_NONE != ret) {
1026 ERR("_ocprocess_worker_start() Fail(%d)", ret);
1027 free(tizen_info_ctx);
1035 OCStackApplicationResult icd_ioty_ocprocess_get_tizen_info_cb(void *ctx,
1036 OCDoHandle handle, OCClientResponse *resp)
1040 char *tizen_device_id;
1041 GVariant *tizen_info;
1042 OCRepPayload *payload;
1043 OCRepPayloadValue *val;
1045 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
1047 if (NULL == resp->payload) {
1048 ERR("payload is empty");
1049 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1050 return OC_STACK_DELETE_TRANSACTION;
1053 payload = (OCRepPayload*)resp->payload;
1054 val = payload->values;
1056 ERR("Invalid payload");
1057 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1058 return OC_STACK_DELETE_TRANSACTION;
1060 device_name = val->str;
1064 ERR("Invalid Payload");
1065 icd_ioty_complete_error(ICD_TIZEN_INFO, ctx, IOTCON_ERROR_IOTIVITY);
1066 return OC_STACK_DELETE_TRANSACTION;
1069 tizen_device_id = val->str;
1071 if (OC_STACK_OK == resp->result)
1072 res = IOTCON_RESPONSE_RESULT_OK;
1074 res = IOTCON_RESPONSE_RESULT_ERROR;
1076 tizen_info = g_variant_new("(ssi)", device_name, tizen_device_id, res);
1078 icd_ioty_complete(ICD_TIZEN_INFO, ctx, tizen_info);
1080 return OC_STACK_DELETE_TRANSACTION;