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_observe_context {
90 GVariantBuilder *options;
94 struct icd_presence_context {
103 void icd_ioty_ocprocess_stop()
109 static void* _ocprocess_worker_thread(void *data)
112 struct icd_ioty_worker *worker = data;
115 ERR("worker is NULL");
119 ret = worker->cb(worker->ctx);
120 if (IOTCON_ERROR_NONE != ret)
121 ERR("cb() Fail(%d)", ret);
123 /* worker was allocated from _ocprocess_worker_start() */
126 /* GCC warning happen if use g_thread_exit() */
131 static int _ocprocess_worker_start(_ocprocess_cb cb, void *ctx)
135 struct icd_ioty_worker *worker;
137 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
139 worker = calloc(1, sizeof(struct icd_ioty_worker));
140 if (NULL == worker) {
141 ERR("calloc() Fail(%d)", errno);
142 return IOTCON_ERROR_OUT_OF_MEMORY;
148 /* TODO : consider thread pool mechanism */
149 thread = g_thread_try_new("worker_thread", _ocprocess_worker_thread, worker, &error);
150 if (NULL == thread) {
151 ERR("g_thread_try_new() Fail(%s)", error->message);
154 return IOTCON_ERROR_SYSTEM;
157 /* DO NOT join thread. It was already detached by calling g_thread_unref() */
158 g_thread_unref(thread);
160 /* DO NOT FREE worker. It MUST be freed in the _ocprocess_worker_thread() */
162 return IOTCON_ERROR_NONE;
166 static int _ocprocess_response_signal(const char *dest, const char *signal,
167 unsigned int signum, GVariant *value)
170 char sig_name[IC_DBUS_SIGNAL_LENGTH] = {0};
172 ret = snprintf(sig_name, sizeof(sig_name), "%s_%u", signal, signum);
173 if (ret <= 0 || sizeof(sig_name) <= ret) {
174 ERR("snprintf() Fail(%d)", ret);
175 return IOTCON_ERROR_IO_ERROR;
178 ret = icd_dbus_emit_signal(dest, sig_name, value);
179 if (IOTCON_ERROR_NONE != ret) {
180 ERR("icd_dbus_emit_signal() Fail(%d)", ret);
184 return IOTCON_ERROR_NONE;
188 static inline GVariantBuilder* _ocprocess_parse_header_options(
189 OCHeaderOption *oic_option, int option_size)
192 GVariantBuilder *options;
194 options = g_variant_builder_new(G_VARIANT_TYPE("a(qs)"));
195 for (i = 0; i < option_size; i++) {
196 g_variant_builder_add(options, "(qs)", oic_option[i].optionID,
197 oic_option[i].optionData);
204 static int _worker_req_handler(void *context)
208 struct icd_req_context *ctx = context;
209 GVariantBuilder payload_builder;
211 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
213 g_variant_builder_init(&payload_builder, G_VARIANT_TYPE("av"));
215 g_variant_builder_add(&payload_builder, "v", ctx->payload);
217 value = g_variant_new("(ia(qs)a(ss)iiavxx)",
224 ICD_POINTER_TO_INT64(ctx->request_h),
225 ICD_POINTER_TO_INT64(ctx->resource_h));
227 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_REQUEST_HANDLER,
229 if (IOTCON_ERROR_NONE != ret)
230 ERR("_ocprocess_response_signal() Fail(%d)", ret);
233 g_variant_builder_unref(ctx->options);
234 g_variant_builder_unref(ctx->query);
241 OCEntityHandlerResult icd_ioty_ocprocess_req_handler(OCEntityHandlerFlag flag,
242 OCEntityHandlerRequest *request, void *user_data)
246 unsigned int signal_number;
247 char *query_str, *query_key, *query_value;
248 char *token, *save_ptr1, *save_ptr2;
249 char *bus_name = NULL;
250 struct icd_req_context *req_ctx;
252 RETV_IF(NULL == request, OC_EH_ERROR);
254 req_ctx = calloc(1, sizeof(struct icd_req_context));
255 if (NULL == req_ctx) {
256 ERR("calloc() Fail(%d)", errno);
261 req_ctx->request_h = request->requestHandle;
262 req_ctx->resource_h = request->resource;
264 ret = icd_dbus_client_list_get_info(req_ctx->resource_h, &signal_number, &bus_name);
265 if (IOTCON_ERROR_NONE != ret) {
266 ERR("icd_dbus_client_list_get_info() Fail(%d)", ret);
271 /* signal number & bus_name */
272 req_ctx->signum = signal_number;
273 req_ctx->bus_name = bus_name;
276 if (OC_REQUEST_FLAG & flag) {
277 switch (request->method) {
279 req_ctx->types = IOTCON_REQUEST_GET;
280 req_ctx->payload = NULL;
282 if (OC_OBSERVE_FLAG & flag) {
283 req_ctx->types |= IOTCON_REQUEST_OBSERVE;
284 /* observation info*/
285 req_ctx->observer_id = request->obsInfo.obsId;
286 req_ctx->observe_action = request->obsInfo.action;
290 req_ctx->types = IOTCON_REQUEST_PUT;
291 req_ctx->payload = icd_payload_to_gvariant(request->payload);
294 req_ctx->types = IOTCON_REQUEST_POST;
295 req_ctx->payload = icd_payload_to_gvariant(request->payload);
298 req_ctx->types = IOTCON_REQUEST_DELETE;
299 req_ctx->payload = NULL;
302 free(req_ctx->bus_name);
309 req_ctx->options = _ocprocess_parse_header_options(
310 request->rcvdVendorSpecificHeaderOptions,
311 request->numRcvdVendorSpecificHeaderOptions);
314 req_ctx->query = g_variant_builder_new(G_VARIANT_TYPE("a(ss)"));
315 query_str = request->query;
316 while ((token = strtok_r(query_str, "&;", &save_ptr1))) {
317 while ((query_key = strtok_r(token, "=", &save_ptr2))) {
319 query_value = strtok_r(token, "=", &save_ptr2);
320 if (NULL == query_value)
323 g_variant_builder_add(req_ctx->query, "(ss)", query_key, query_value);
328 ret = _ocprocess_worker_start(_worker_req_handler, req_ctx);
329 if (IOTCON_ERROR_NONE != ret) {
330 ERR("_ocprocess_worker_start() Fail(%d)", ret);
331 free(req_ctx->bus_name);
332 if (req_ctx->payload)
333 g_variant_unref(req_ctx->payload);
334 g_variant_builder_unref(req_ctx->options);
335 g_variant_builder_unref(req_ctx->query);
340 /* DO NOT FREE req_ctx. It MUST be freed in the _worker_req_handler func */
346 gpointer icd_ioty_ocprocess_thread(gpointer data)
349 OCStackResult result;
352 while (icd_ioty_alive) {
353 icd_ioty_csdk_lock();
354 result = OCProcess();
355 icd_ioty_csdk_unlock();
356 if (OC_STACK_OK != result) {
357 ERR("OCProcess() Fail(%d)", result);
361 /* TODO : SHOULD revise time or usleep */
369 static int _worker_find_cb(void *context)
373 struct icd_find_context *ctx = context;
375 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
377 for (i = 0; ctx->payload[i]; i++) {
378 value = g_variant_new("(vi)", ctx->payload[i], ctx->conn_type);
379 /* TODO : If one device has multi resources, it comes as bulk data.
380 * To reduce the number of emit_signal, let's send signal only one time for one device.
381 * for ex, client list. */
382 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_FOUND_RESOURCE,
384 if (IOTCON_ERROR_NONE != ret) {
385 ERR("_ocprocess_response_signal() Fail(%d)", ret);
386 g_variant_unref(value);
391 /* ctx was allocated from icd_ioty_ocprocess_find_cb() */
399 OCStackApplicationResult icd_ioty_ocprocess_find_cb(void *ctx, OCDoHandle handle,
400 OCClientResponse *resp)
403 struct icd_find_context *find_ctx;
404 icd_sig_ctx_s *sig_context = ctx;
406 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
407 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
408 if (NULL == resp->payload)
409 /* normal case : payload COULD be NULL */
410 return OC_STACK_KEEP_TRANSACTION;
411 RETVM_IF(PAYLOAD_TYPE_DISCOVERY != resp->payload->type,
412 OC_STACK_KEEP_TRANSACTION, "Invalid payload type(%d)", resp->payload->type);
414 find_ctx = calloc(1, sizeof(struct icd_find_context));
415 if (NULL == find_ctx) {
416 ERR("calloc() Fail(%d)", errno);
417 return OC_STACK_KEEP_TRANSACTION;
420 find_ctx->signum = sig_context->signum;
421 find_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
422 find_ctx->payload = icd_payload_res_to_gvariant(resp->payload, &resp->devAddr);
423 find_ctx->conn_type = icd_ioty_transport_flag_to_conn_type(resp->devAddr.adapter,
424 resp->devAddr.flags);
426 ret = _ocprocess_worker_start(_worker_find_cb, find_ctx);
427 if (IOTCON_ERROR_NONE != ret) {
428 ERR("_ocprocess_worker_start() Fail(%d)", ret);
429 free(find_ctx->bus_name);
430 ic_utils_gvariant_array_free(find_ctx->payload);
432 return OC_STACK_KEEP_TRANSACTION;
435 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
436 /* DO NOT FREE find_ctx. It MUST be freed in the _worker_find_cb func */
438 return OC_STACK_KEEP_TRANSACTION;
442 static int _worker_crud_cb(void *context)
445 struct icd_crud_context *ctx = context;
447 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
449 if (ICD_CRUD_DELETE == ctx->crud_type)
450 value = g_variant_new("(a(qs)i)", ctx->options, ctx->res);
452 value = g_variant_new("(a(qs)vi)", ctx->options, ctx->payload, ctx->res);
453 icd_ioty_complete(ctx->crud_type, ctx->invocation, value);
455 /* ctx was allocated from icd_ioty_ocprocess_xxx_cb() */
456 g_variant_builder_unref(ctx->options);
459 return IOTCON_ERROR_NONE;
463 static int _worker_info_cb(void *context)
466 const char *sig_name = NULL;
467 struct icd_info_context *ctx = context;
469 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
471 if (ICD_DEVICE_INFO == ctx->info_type)
472 sig_name = IC_DBUS_SIGNAL_DEVICE;
473 else if (ICD_PLATFORM_INFO == ctx->info_type)
474 sig_name = IC_DBUS_SIGNAL_PLATFORM;
476 ret = _ocprocess_response_signal(ctx->bus_name, sig_name, ctx->signum, ctx->payload);
477 if (IOTCON_ERROR_NONE != ret)
478 ERR("_ocprocess_response_signal() Fail(%d)", ret);
480 /* ctx was allocated from icd_ioty_ocprocess_info_cb() */
488 static int _ocprocess_worker(_ocprocess_cb cb, int type, OCPayload *payload, int res,
489 GVariantBuilder *options, void *ctx)
492 struct icd_crud_context *crud_ctx;
494 crud_ctx = calloc(1, sizeof(struct icd_crud_context));
495 if (NULL == crud_ctx) {
496 ERR("calloc() Fail(%d)", errno);
497 return IOTCON_ERROR_OUT_OF_MEMORY;
500 crud_ctx->crud_type = type;
501 crud_ctx->payload = icd_payload_to_gvariant(payload);
503 crud_ctx->options = options;
504 crud_ctx->invocation = ctx;
506 ret = _ocprocess_worker_start(cb, crud_ctx);
507 if (IOTCON_ERROR_NONE != ret) {
508 ERR("_ocprocess_worker_start() Fail(%d)", ret);
509 if (crud_ctx->payload)
510 g_variant_unref(crud_ctx->payload);
511 g_variant_builder_unref(crud_ctx->options);
515 /* DO NOT FREE crud_ctx. It MUST be freed in the _worker_crud_cb func */
521 OCStackApplicationResult icd_ioty_ocprocess_get_cb(void *ctx, OCDoHandle handle,
522 OCClientResponse *resp)
526 OCStackResult result;
527 GVariantBuilder *options;
529 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
531 if (NULL == resp->payload) {
532 ERR("payload is empty");
533 icd_ioty_complete_error(ICD_CRUD_GET, ctx, IOTCON_ERROR_IOTIVITY);
534 return OC_STACK_DELETE_TRANSACTION;
537 result = resp->result;
538 if (OC_STACK_OK == result) {
539 res = IOTCON_RESPONSE_RESULT_OK;
540 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
541 resp->numRcvdVendorSpecificHeaderOptions);
543 WARN("resp error(%d)", result);
544 res = IOTCON_RESPONSE_RESULT_ERROR;
548 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_GET, resp->payload, res,
550 if (IOTCON_ERROR_NONE != ret) {
551 ERR("_ocprocess_worker() Fail(%d)", ret);
552 icd_ioty_complete_error(ICD_CRUD_GET, ctx, ret);
553 return OC_STACK_DELETE_TRANSACTION;
556 return OC_STACK_DELETE_TRANSACTION;
560 OCStackApplicationResult icd_ioty_ocprocess_put_cb(void *ctx, OCDoHandle handle,
561 OCClientResponse *resp)
565 OCStackResult result;
566 GVariantBuilder *options;
568 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
570 if (NULL == resp->payload) {
571 ERR("payload is empty");
572 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, IOTCON_ERROR_IOTIVITY);
573 return OC_STACK_DELETE_TRANSACTION;
576 result = resp->result;
579 res = IOTCON_RESPONSE_RESULT_OK;
581 case OC_STACK_RESOURCE_CREATED:
582 res = IOTCON_RESPONSE_RESULT_RESOURCE_CREATED;
585 WARN("resp error(%d)", result);
586 res = IOTCON_RESPONSE_RESULT_ERROR;
590 if (IOTCON_RESPONSE_RESULT_ERROR != res) {
591 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
592 resp->numRcvdVendorSpecificHeaderOptions);
595 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_PUT, resp->payload, res,
597 if (IOTCON_ERROR_NONE != ret) {
598 ERR("_ocprocess_worker() Fail(%d)", ret);
599 icd_ioty_complete_error(ICD_CRUD_PUT, ctx, ret);
600 return OC_STACK_DELETE_TRANSACTION;
603 return OC_STACK_DELETE_TRANSACTION;
607 OCStackApplicationResult icd_ioty_ocprocess_post_cb(void *ctx, OCDoHandle handle,
608 OCClientResponse *resp)
612 OCStackResult result;
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_POST, ctx, IOTCON_ERROR_IOTIVITY);
620 return OC_STACK_DELETE_TRANSACTION;
623 result = resp->result;
626 res = IOTCON_RESPONSE_RESULT_OK;
628 case OC_STACK_RESOURCE_CREATED:
629 res = IOTCON_RESPONSE_RESULT_RESOURCE_CREATED;
632 WARN("resp error(%d)", result);
633 res = IOTCON_RESPONSE_RESULT_ERROR;
637 if (IOTCON_RESPONSE_RESULT_ERROR != res) {
638 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
639 resp->numRcvdVendorSpecificHeaderOptions);
642 ret = _ocprocess_worker(_worker_crud_cb, ICD_CRUD_POST, resp->payload, res,
644 if (IOTCON_ERROR_NONE != ret) {
645 ERR("_ocprocess_worker() Fail(%d)", ret);
646 icd_ioty_complete_error(ICD_CRUD_POST, ctx, ret);
647 return OC_STACK_DELETE_TRANSACTION;
650 return OC_STACK_DELETE_TRANSACTION;
654 OCStackApplicationResult icd_ioty_ocprocess_delete_cb(void *ctx, OCDoHandle handle,
655 OCClientResponse *resp)
659 OCStackResult result;
660 GVariantBuilder *options;
662 RETV_IF(NULL == ctx, OC_STACK_DELETE_TRANSACTION);
664 if (NULL == resp->payload) {
665 ERR("payload is empty");
666 icd_ioty_complete_error(ICD_CRUD_DELETE, ctx, IOTCON_ERROR_IOTIVITY);
667 return OC_STACK_DELETE_TRANSACTION;
670 result = resp->result;
673 res = IOTCON_RESPONSE_RESULT_OK;
675 case OC_STACK_RESOURCE_DELETED:
676 res = IOTCON_RESPONSE_RESULT_RESOURCE_DELETED;
679 WARN("resp error(%d)", result);
680 res = IOTCON_RESPONSE_RESULT_ERROR;
684 if (IOTCON_RESPONSE_RESULT_ERROR != res) {
685 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
686 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 value = g_variant_new("(a(qs)vii)", NULL, NULL, ret_val, 0);
732 ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_OBSERVE, signum, value);
733 if (IOTCON_ERROR_NONE != ret)
734 ERR("_ocprocess_response_signal() Fail(%d)", ret);
738 OCStackApplicationResult icd_ioty_ocprocess_observe_cb(void *ctx, OCDoHandle handle,
739 OCClientResponse *resp)
742 OCStackResult result;
743 GVariantBuilder *options;
744 struct icd_observe_context *observe_ctx;
745 icd_sig_ctx_s *sig_context = ctx;
747 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
749 if (NULL == resp->payload) {
750 ERR("payload is empty");
751 _observe_cb_response_error(sig_context->bus_name, sig_context->signum,
752 IOTCON_ERROR_IOTIVITY);
753 return OC_STACK_KEEP_TRANSACTION;
756 observe_ctx = calloc(1, sizeof(struct icd_observe_context));
757 if (NULL == observe_ctx) {
758 ERR("calloc() Fail(%d)", errno);
759 _observe_cb_response_error(sig_context->bus_name, sig_context->signum,
760 IOTCON_ERROR_OUT_OF_MEMORY);
761 return OC_STACK_KEEP_TRANSACTION;
764 result = resp->result;
765 if (OC_STACK_OK == result) {
766 res = IOTCON_RESPONSE_RESULT_OK;
767 options = _ocprocess_parse_header_options(resp->rcvdVendorSpecificHeaderOptions,
768 resp->numRcvdVendorSpecificHeaderOptions);
770 WARN("resp error(%d)", result);
771 res = IOTCON_RESPONSE_RESULT_ERROR;
775 observe_ctx->payload = icd_payload_to_gvariant(resp->payload);
776 observe_ctx->signum = sig_context->signum;
777 observe_ctx->res = res;
778 observe_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
779 observe_ctx->options = options;
781 ret = _ocprocess_worker_start(_worker_observe_cb, observe_ctx);
782 if (IOTCON_ERROR_NONE != ret) {
783 ERR("_ocprocess_worker_start() Fail(%d)", ret);
784 _observe_cb_response_error(sig_context->bus_name, sig_context->signum, ret);
785 free(observe_ctx->bus_name);
786 if (observe_ctx->payload)
787 g_variant_unref(observe_ctx->payload);
788 g_variant_builder_unref(observe_ctx->options);
790 return OC_STACK_KEEP_TRANSACTION;
793 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
794 /* DO NOT FREE observe_ctx. It MUST be freed in the _worker_observe_cb func */
796 return OC_STACK_KEEP_TRANSACTION;
800 static int _worker_presence_cb(void *context)
805 char addr[PATH_MAX] = {0};
806 struct icd_presence_context *ctx = context;
808 RETV_IF(NULL == ctx, IOTCON_ERROR_INVALID_PARAMETER);
810 snprintf(addr, sizeof(addr), "%s:%d", ctx->dev_addr->addr, ctx->dev_addr->port);
812 value = g_variant_new("(ius)", ctx->result, ctx->nonce, addr);
814 ret = _ocprocess_response_signal(ctx->bus_name, IC_DBUS_SIGNAL_PRESENCE, ctx->signum,
816 if (IOTCON_ERROR_NONE != ret)
817 ERR("_ocprocess_response_signal() Fail(%d)", ret);
819 /* ctx was allocated from icd_ioty_ocprocess_presence_cb() */
828 static void _presence_cb_response_error(const char *dest, unsigned int signum,
835 value = g_variant_new("(ius)", ret_val, 0, IC_STR_NULL);
837 ret = _ocprocess_response_signal(dest, IC_DBUS_SIGNAL_PRESENCE, signum, value);
838 if (IOTCON_ERROR_NONE != ret)
839 ERR("_ocprocess_response_signal() Fail(%d)", ret);
843 OCStackApplicationResult icd_ioty_ocprocess_presence_cb(void *ctx, OCDoHandle handle,
844 OCClientResponse *resp)
849 icd_sig_ctx_s *sig_context = ctx;
850 struct icd_presence_context *presence_ctx;
852 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
853 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
855 presence_ctx = calloc(1, sizeof(struct icd_presence_context));
856 if (NULL == presence_ctx) {
857 ERR("calloc() Fail(%d)", errno);
858 _presence_cb_response_error(sig_context->bus_name, sig_context->signum,
859 IOTCON_ERROR_OUT_OF_MEMORY);
860 return OC_STACK_KEEP_TRANSACTION;
863 dev_addr = calloc(1, sizeof(OCDevAddr));
864 if (NULL == dev_addr) {
865 ERR("calloc() Fail(%d)", errno);
866 _presence_cb_response_error(sig_context->bus_name, sig_context->signum,
867 IOTCON_ERROR_OUT_OF_MEMORY);
869 return OC_STACK_KEEP_TRANSACTION;
871 memcpy(dev_addr, &resp->devAddr, sizeof(OCDevAddr));
873 switch (resp->result) {
875 presence_ctx->result = IOTCON_PRESENCE_OK;
877 case OC_STACK_PRESENCE_STOPPED:
878 presence_ctx->result = IOTCON_PRESENCE_STOPPED;
880 case OC_STACK_PRESENCE_TIMEOUT:
881 presence_ctx->result = IOTCON_PRESENCE_TIMEOUT;
885 DBG("Presence error(%d)", resp->result);
886 presence_ctx->result = IOTCON_ERROR_IOTIVITY;
889 presence_ctx->signum = sig_context->signum;
890 presence_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
891 presence_ctx->nonce = resp->sequenceNumber;
892 presence_ctx->dev_addr = dev_addr;
894 ret = _ocprocess_worker_start(_worker_presence_cb, presence_ctx);
895 if (IOTCON_ERROR_NONE != ret) {
896 ERR("_ocprocess_worker_start() Fail(%d)", ret);
897 _presence_cb_response_error(sig_context->bus_name, sig_context->signum, ret);
898 free(presence_ctx->bus_name);
899 free(presence_ctx->dev_addr);
901 return OC_STACK_KEEP_TRANSACTION;
904 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
905 /* DO NOT FREE presence_ctx. It MUST be freed in the _worker_presence_cb func */
907 return OC_STACK_KEEP_TRANSACTION;
911 OCStackApplicationResult icd_ioty_ocprocess_info_cb(void *ctx, OCDoHandle handle,
912 OCClientResponse *resp)
916 struct icd_info_context *info_ctx;
917 icd_sig_ctx_s *sig_context = ctx;
919 RETV_IF(NULL == ctx, OC_STACK_KEEP_TRANSACTION);
920 RETV_IF(NULL == resp, OC_STACK_KEEP_TRANSACTION);
921 RETV_IF(NULL == resp->payload, OC_STACK_KEEP_TRANSACTION);
923 if (PAYLOAD_TYPE_DEVICE == resp->payload->type)
924 info_type = ICD_DEVICE_INFO;
925 else if (PAYLOAD_TYPE_PLATFORM == resp->payload->type)
926 info_type = ICD_PLATFORM_INFO;
928 return OC_STACK_KEEP_TRANSACTION;
930 info_ctx = calloc(1, sizeof(struct icd_info_context));
931 if (NULL == info_ctx) {
932 ERR("calloc() Fail(%d)", errno);
933 return OC_STACK_KEEP_TRANSACTION;
936 info_ctx->info_type = info_type;
937 info_ctx->payload = icd_payload_to_gvariant(resp->payload);
938 info_ctx->signum = sig_context->signum;
939 info_ctx->bus_name = ic_utils_strdup(sig_context->bus_name);
941 ret = _ocprocess_worker_start(_worker_info_cb, info_ctx);
942 if (IOTCON_ERROR_NONE != ret) {
943 ERR("_ocprocess_worker_start() Fail(%d)", ret);
944 free(info_ctx->bus_name);
945 if (info_ctx->payload)
946 g_variant_unref(info_ctx->payload);
948 return OC_STACK_KEEP_TRANSACTION;
951 /* DO NOT FREE sig_context. It MUST be freed in the ocstack */
952 /* DO NOT FREE info_ctx. It MUST be freed in the _worker_info_cb func */
954 return OC_STACK_KEEP_TRANSACTION;