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.
27 #include "icl-options.h"
29 #include "icl-dbus-type.h"
30 #include "icl-representation.h"
31 #include "icl-response.h"
32 #include "icl-remote-resource.h"
33 #include "icl-payload.h"
36 iotcon_remote_resource_response_cb cb;
38 iotcon_remote_resource_h resource;
42 iotcon_remote_resource_observe_cb cb;
44 iotcon_remote_resource_h resource;
47 static GList *icl_crud_cb_list = NULL;
49 void icl_remote_resource_crud_stop(iotcon_remote_resource_h resource)
52 for (c = icl_crud_cb_list; c; c = c->next) {
53 icl_on_response_s *cb_container = c->data;
54 if (NULL == cb_container) {
55 ERR("cb_container is NULL");
58 if (cb_container->resource == resource)
59 cb_container->cb = NULL;
63 static iotcon_options_h _icl_parse_options_iter(GVariantIter *iter)
66 iotcon_options_h options = NULL;
71 if (g_variant_iter_n_children(iter)) {
72 unsigned short option_id;
75 ret = iotcon_options_create(&options);
76 if (IOTCON_ERROR_NONE != ret) {
77 ERR("iotcon_options_create() Fail(%d)", ret);
80 while (g_variant_iter_loop(iter, "(q&s)", &option_id, &option_data))
81 iotcon_options_add(options, option_id, option_data);
86 static int _icl_parse_crud_gvariant(iotcon_request_type_e request_type,
87 GVariant *gvar, iotcon_response_h *response)
90 GVariantIter *options_iter = NULL;
91 GVariant *repr_gvar = NULL;
92 iotcon_response_h resp = NULL;
93 iotcon_options_h options = NULL;
94 iotcon_representation_h repr = NULL;
96 if (IOTCON_REQUEST_DELETE == request_type)
97 g_variant_get(gvar, "(a(qs)i)", &options_iter, &res);
99 g_variant_get(gvar, "(a(qs)vi)", &options_iter, &repr_gvar, &res);
102 options = _icl_parse_options_iter(options_iter);
103 g_variant_iter_free(options_iter);
107 repr = icl_representation_from_gvariant(repr_gvar);
109 ERR("icl_representation_from_gvariant() Fail");
111 iotcon_options_destroy(options);
112 return IOTCON_ERROR_SYSTEM;
116 res = icl_dbus_convert_daemon_error(res);
118 resp = calloc(1, sizeof(struct icl_resource_response));
120 ERR("calloc() Fail(%d)", errno);
122 iotcon_representation_destroy(repr);
124 iotcon_options_destroy(options);
125 return IOTCON_ERROR_OUT_OF_MEMORY;
129 resp->header_options = options;
133 return IOTCON_ERROR_NONE;
136 static void _icl_on_crud_cb(iotcon_request_type_e request_type,
137 GObject *object, GAsyncResult *g_async_res, icl_on_response_s *cb_container)
140 iotcon_response_h response = NULL;
142 GError *error = NULL;
144 RET_IF(NULL == cb_container);
146 icl_crud_cb_list = g_list_remove(icl_crud_cb_list, cb_container);
148 switch (request_type) {
149 case IOTCON_REQUEST_GET:
150 ic_dbus_call_get_finish(IC_DBUS(object), &result, g_async_res, &error);
152 case IOTCON_REQUEST_PUT:
153 ic_dbus_call_put_finish(IC_DBUS(object), &result, g_async_res, &error);
155 case IOTCON_REQUEST_POST:
156 ic_dbus_call_post_finish(IC_DBUS(object), &result, g_async_res, &error);
158 case IOTCON_REQUEST_DELETE:
159 ic_dbus_call_delete_finish(IC_DBUS(object), &result, g_async_res, &error);
162 ERR("Invalid type(%d)", request_type);
167 ERR("ic_dbus_call_finish() Fail(%d, %s)", request_type, error->message);
168 if (cb_container->cb) {
169 int ret = icl_dbus_convert_dbus_error(error->code);
170 cb_container->cb(cb_container->resource, ret, request_type, NULL,
171 cb_container->user_data);
178 ret = _icl_parse_crud_gvariant(request_type, result, &response);
179 if (IOTCON_ERROR_NONE != ret) {
180 ERR("_icl_parse_crud_gvariant() Fail(%s)", ret);
181 if (cb_container->cb) {
182 cb_container->cb(cb_container->resource, ret, request_type, NULL,
183 cb_container->user_data);
188 if (cb_container->cb)
189 cb_container->cb(cb_container->resource, IOTCON_ERROR_NONE, request_type,
190 response, cb_container->user_data);
193 iotcon_response_destroy(response);
199 static void _icl_on_get_cb(GObject *object, GAsyncResult *g_async_res,
202 _icl_on_crud_cb(IOTCON_REQUEST_GET, object, g_async_res, user_data);
206 static void _icl_on_put_cb(GObject *object, GAsyncResult *g_async_res,
209 _icl_on_crud_cb(IOTCON_REQUEST_PUT, object, g_async_res, user_data);
213 static void _icl_on_post_cb(GObject *object, GAsyncResult *g_async_res,
216 _icl_on_crud_cb(IOTCON_REQUEST_POST, object, g_async_res, user_data);
220 API int iotcon_remote_resource_get(iotcon_remote_resource_h resource,
221 iotcon_query_h query, iotcon_remote_resource_response_cb cb, void *user_data)
224 GVariant *arg_remote_resource;
225 icl_on_response_s *cb_container;
227 RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
228 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
229 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
230 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
232 cb_container = calloc(1, sizeof(icl_on_response_s));
233 if (NULL == cb_container) {
234 ERR("calloc() Fail(%d)", errno);
235 return IOTCON_ERROR_OUT_OF_MEMORY;
238 cb_container->resource = resource;
239 cb_container->cb = cb;
240 cb_container->user_data = user_data;
242 arg_remote_resource = icl_dbus_remote_resource_to_gvariant(resource);
243 arg_query = icl_dbus_query_to_gvariant(query);
245 ic_dbus_call_get(icl_dbus_get_object(), arg_remote_resource, arg_query, NULL,
246 _icl_on_get_cb, cb_container);
248 icl_crud_cb_list = g_list_append(icl_crud_cb_list, cb_container);
250 return IOTCON_ERROR_NONE;
254 API int iotcon_remote_resource_put(iotcon_remote_resource_h resource,
255 iotcon_representation_h repr,
256 iotcon_query_h query,
257 iotcon_remote_resource_response_cb cb,
261 GVariant *arg_remote_resource;
263 icl_on_response_s *cb_container;
265 RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
266 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
267 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
268 RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
269 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
271 cb_container = calloc(1, sizeof(icl_on_response_s));
272 if (NULL == cb_container) {
273 ERR("calloc() Fail(%d)", errno);
274 return IOTCON_ERROR_OUT_OF_MEMORY;
277 cb_container->resource = resource;
278 cb_container->cb = cb;
279 cb_container->user_data = user_data;
281 arg_repr = icl_representation_to_gvariant(repr);
282 if (NULL == arg_repr) {
283 ERR("icl_representation_to_gvariant() Fail");
285 return IOTCON_ERROR_REPRESENTATION;
288 arg_remote_resource = icl_dbus_remote_resource_to_gvariant(resource);
289 arg_query = icl_dbus_query_to_gvariant(query);
291 ic_dbus_call_put(icl_dbus_get_object(), arg_remote_resource, arg_repr, arg_query,
292 NULL, _icl_on_put_cb, cb_container);
294 icl_crud_cb_list = g_list_append(icl_crud_cb_list, cb_container);
296 return IOTCON_ERROR_NONE;
300 API int iotcon_remote_resource_post(iotcon_remote_resource_h resource,
301 iotcon_representation_h repr,
302 iotcon_query_h query,
303 iotcon_remote_resource_response_cb cb,
308 GVariant *arg_remote_resource;
309 icl_on_response_s *cb_container;
311 RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
312 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
313 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
314 RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
315 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
317 cb_container = calloc(1, sizeof(icl_on_response_s));
318 if (NULL == cb_container) {
319 ERR("calloc() Fail(%d)", errno);
320 return IOTCON_ERROR_OUT_OF_MEMORY;
323 cb_container->resource = resource;
324 cb_container->cb = cb;
325 cb_container->user_data = user_data;
327 arg_repr = icl_representation_to_gvariant(repr);
328 if (NULL == arg_repr) {
329 ERR("icl_representation_to_gvariant() Fail");
331 return IOTCON_ERROR_REPRESENTATION;
334 arg_remote_resource = icl_dbus_remote_resource_to_gvariant(resource);
335 arg_query = icl_dbus_query_to_gvariant(query);
337 ic_dbus_call_post(icl_dbus_get_object(), arg_remote_resource, arg_repr, arg_query,
338 NULL, _icl_on_post_cb, cb_container);
340 icl_crud_cb_list = g_list_append(icl_crud_cb_list, cb_container);
342 return IOTCON_ERROR_NONE;
346 static void _icl_on_delete_cb(GObject *object, GAsyncResult *g_async_res,
349 _icl_on_crud_cb(IOTCON_REQUEST_DELETE, object, g_async_res, user_data);
353 API int iotcon_remote_resource_delete(iotcon_remote_resource_h resource,
354 iotcon_remote_resource_response_cb cb, void *user_data)
356 GVariant *arg_remote_resource;
357 icl_on_response_s *cb_container;
359 RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
360 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
361 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
362 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
364 cb_container = calloc(1, sizeof(icl_on_response_s));
365 if (NULL == cb_container) {
366 ERR("calloc() Fail(%d)", errno);
367 return IOTCON_ERROR_OUT_OF_MEMORY;
370 cb_container->resource = resource;
371 cb_container->cb = cb;
372 cb_container->user_data = user_data;
374 arg_remote_resource = icl_dbus_remote_resource_to_gvariant(resource);
376 ic_dbus_call_delete(icl_dbus_get_object(), arg_remote_resource, NULL,
377 _icl_on_delete_cb, cb_container);
379 icl_crud_cb_list = g_list_append(icl_crud_cb_list, cb_container);
381 return IOTCON_ERROR_NONE;
384 static void _icl_on_observe_cb(GDBusConnection *connection,
385 const gchar *sender_name,
386 const gchar *object_path,
387 const gchar *interface_name,
388 const gchar *signal_name,
389 GVariant *parameters,
394 GVariantIter *options_iter = NULL;
395 GVariant *repr_gvar = NULL;
396 iotcon_response_h response = NULL;
397 icl_on_observe_s *cb_container = user_data;
398 iotcon_options_h options = NULL;
399 iotcon_representation_h repr = NULL;
401 RET_IF(NULL == cb_container);
403 g_variant_get(parameters, "(a(qs)vii)", &options_iter, &repr_gvar, &res, &seq_number);
406 options = _icl_parse_options_iter(options_iter);
407 g_variant_iter_free(options_iter);
411 repr = icl_representation_from_gvariant(repr_gvar);
413 ERR("icl_representation_from_gvariant() Fail");
415 iotcon_options_destroy(options);
417 if (cb_container->cb)
418 cb_container->cb(cb_container->resource, IOTCON_ERROR_SYSTEM, -1,
419 NULL, cb_container->user_data);
424 res = icl_dbus_convert_daemon_error(res);
426 response = calloc(1, sizeof(struct icl_resource_response));
427 if (NULL == response) {
428 ERR("calloc() Fail(%d)", errno);
430 iotcon_representation_destroy(repr);
432 iotcon_options_destroy(options);
434 if (cb_container->cb)
435 cb_container->cb(cb_container->resource, IOTCON_ERROR_OUT_OF_MEMORY, -1,
436 NULL, cb_container->user_data);
439 response->result = res;
440 response->repr = repr;
441 response->header_options = options;
443 if (cb_container->cb)
444 cb_container->cb(cb_container->resource, IOTCON_ERROR_NONE, seq_number,
445 response, cb_container->user_data);
448 iotcon_response_destroy(response);
452 static void _icl_observe_conn_cleanup(icl_on_observe_s *cb_container)
454 cb_container->resource->observe_handle = 0;
455 cb_container->resource->observe_sub_id = 0;
456 icl_remote_resource_unref(cb_container->resource);
461 API int iotcon_remote_resource_observe_register(iotcon_remote_resource_h resource,
462 iotcon_observe_policy_e observe_policy,
463 iotcon_query_h query,
464 iotcon_remote_resource_observe_cb cb,
469 GError *error = NULL;
470 int64_t signal_number;
471 int64_t observe_handle;
472 icl_on_observe_s *cb_container;
473 GVariant *arg_query, *arg_remote_resource;
474 char signal_name[IC_DBUS_SIGNAL_LENGTH] = {0};
476 RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
477 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
478 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
479 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
480 RETV_IF(resource->observe_handle || resource->observe_sub_id, IOTCON_ERROR_ALREADY);
482 arg_remote_resource = icl_dbus_remote_resource_to_gvariant(resource);
483 arg_query = icl_dbus_query_to_gvariant(query);
485 cb_container = calloc(1, sizeof(icl_on_observe_s));
486 if (NULL == cb_container) {
487 ERR("calloc() Fail(%d)", errno);
488 g_variant_unref(arg_query);
489 g_variant_unref(arg_remote_resource);
490 return IOTCON_ERROR_OUT_OF_MEMORY;
493 cb_container->resource = resource;
494 cb_container->cb = cb;
495 cb_container->user_data = user_data;
497 ic_dbus_call_observer_start_sync(icl_dbus_get_object(), arg_remote_resource,
498 observe_policy, arg_query, &signal_number, &observe_handle, NULL, &error);
500 ERR("ic_dbus_call_observer_start_sync() Fail(%s)", error->message);
501 ret = icl_dbus_convert_dbus_error(error->code);
503 g_variant_unref(arg_query);
504 g_variant_unref(arg_remote_resource);
508 if (0 == observe_handle) {
509 ERR("iotcon-daemon Fail");
511 return IOTCON_ERROR_IOTIVITY;
514 snprintf(signal_name, sizeof(signal_name), "%s_%llx", IC_DBUS_SIGNAL_OBSERVE,
517 sub_id = icl_dbus_subscribe_signal(signal_name, cb_container,
518 _icl_observe_conn_cleanup, _icl_on_observe_cb);
520 ERR("icl_dbus_subscribe_signal() Fail");
522 return IOTCON_ERROR_DBUS;
525 resource->observe_sub_id = sub_id;
526 resource->observe_handle = observe_handle;
527 icl_remote_resource_ref(resource);
529 return IOTCON_ERROR_NONE;
533 API int iotcon_remote_resource_observe_deregister(iotcon_remote_resource_h resource)
536 GError *error = NULL;
537 GVariant *arg_options;
539 RETV_IF(false == ic_utils_check_oic_feature_supported(), IOTCON_ERROR_NOT_SUPPORTED);
540 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
541 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
542 if (0 == resource->observe_handle) {
543 ERR("It doesn't have a observe_handle");
544 return IOTCON_ERROR_INVALID_PARAMETER;
547 arg_options = icl_dbus_options_to_gvariant(resource->header_options);
549 ic_dbus_call_observer_stop_sync(icl_dbus_get_object(), resource->observe_handle,
550 arg_options, &ret, NULL, &error);
552 ERR("ic_dbus_call_observer_stop_sync() Fail(%s)", error->message);
553 ret = icl_dbus_convert_dbus_error(error->code);
557 if (IOTCON_ERROR_NONE != ret) {
558 ERR("iotcon-daemon Fail(%d)", ret);
559 return icl_dbus_convert_daemon_error(ret);
561 resource->observe_handle = 0;
563 icl_dbus_unsubscribe_signal(resource->observe_sub_id);
564 resource->observe_sub_id = 0;
567 return IOTCON_ERROR_NONE;