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.
23 #include <glib-object.h>
27 #include "icl-resource-types.h"
28 #include "icl-resource.h"
29 #include "icl-request.h"
32 #include "icl-dbus-type.h"
36 * @brief global context
38 static bool icl_is_init = false;
40 API int iotcon_initialize()
45 RETVM_IF(true == icl_is_init, IOTCON_ERROR_ALREADY, "already initialized");
47 #if !GLIB_CHECK_VERSION(2, 35, 0)
51 ret = icl_dbus_start();
52 if (IOTCON_ERROR_NONE != ret) {
53 ERR("icl_dbus_start() Fail(%d)", ret);
59 return IOTCON_ERROR_NONE;
63 API void iotcon_deinitialize()
67 RETM_IF(false == icl_is_init, "Not initialized");
75 API int iotcon_add_connection_changed_cb(iotcon_connection_changed_cb cb, void *user_data)
79 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
81 ret = icl_dbus_add_connection_changed_cb(cb, user_data);
82 if (IOTCON_ERROR_NONE != ret) {
83 ERR("icl_dbus_add_connection_changed_cb() Fail(%d)", ret);
91 API int iotcon_remove_connection_changed_cb(iotcon_connection_changed_cb cb,
96 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
98 ret = icl_dbus_remove_connection_changed_cb(cb, user_data);
99 if (IOTCON_ERROR_NONE != ret) {
100 ERR("icl_dbus_remove_connection_changed_cb() Fail(%d)", ret);
108 static void _icl_request_handler(GDBusConnection *connection,
109 const gchar *sender_name,
110 const gchar *object_path,
111 const gchar *interface_name,
112 const gchar *signal_name,
113 GVariant *parameters,
116 GVariantIter *options;
117 unsigned short option_id;
125 struct icl_resource_request request = {0};
126 iotcon_resource_h resource = user_data;
127 iotcon_request_handler_cb cb = resource->cb;
129 g_variant_get(parameters, "(ia(qs)a(ss)ii&sii)",
133 &request.observation_info.action,
134 &request.observation_info.observer_id,
139 if (g_variant_iter_n_children(options)) {
140 request.header_options = iotcon_options_new();
141 while (g_variant_iter_loop(options, "(q&s)", &option_id, &option_data))
142 iotcon_options_insert(request.header_options, option_id, option_data);
144 g_variant_iter_free(options);
146 if (g_variant_iter_n_children(query)) {
147 request.query = iotcon_query_new();
148 while (g_variant_iter_loop(query, "(&s&s)", &key, &value))
149 iotcon_query_insert(request.query, key, value);
151 g_variant_iter_free(query);
153 request.request_handle = GINT_TO_POINTER(request_handle);
154 request.resource_handle = GINT_TO_POINTER(resource_handle);
156 if (ic_utils_dbus_decode_str(repr_json)) {
157 request.repr = icl_repr_create_repr(repr_json);
158 if (NULL == request.repr) {
159 ERR("icl_repr_create_repr() Fail");
161 iotcon_query_free(request.query);
162 if (request.header_options)
163 iotcon_options_free(request.header_options);
168 /* TODO remove request.uri */
169 request.uri_path = "temp_uri_path";
172 cb(resource, &request, resource->user_data);
174 /* To avoid unnecessary ERR log (repr could be NULL) */
176 iotcon_repr_free(request.repr);
178 iotcon_query_free(request.query);
179 if (request.header_options)
180 iotcon_options_free(request.header_options);
184 static void _icl_resource_conn_cleanup(iotcon_resource_h resource)
186 resource->sub_id = 0;
187 resource->handle = 0;
191 /* The length of uri_path should be less than or equal to 36. */
192 API iotcon_resource_h iotcon_register_resource(const char *uri_path,
193 iotcon_resource_types_h res_types,
196 iotcon_request_handler_cb cb,
202 GError *error = NULL;
204 char sig_name[IC_DBUS_SIGNAL_LENGTH];
205 iotcon_resource_h resource;
207 RETV_IF(NULL == icl_dbus_get_object(), NULL);
208 RETV_IF(NULL == uri_path, NULL);
209 RETVM_IF(IOTCON_URI_PATH_LENGTH_MAX < strlen(uri_path), NULL, "Invalid uri_path(%s)",
211 RETV_IF(NULL == res_types, NULL);
212 RETV_IF(NULL == cb, NULL);
214 resource = calloc(1, sizeof(struct icl_resource));
215 if (NULL == resource) {
216 ERR("calloc() Fail(%d)", errno);
220 types = icl_dbus_resource_types_to_array(res_types);
222 ERR("icl_dbus_resource_types_to_array() Fail");
227 signal_number = icl_dbus_generate_signal_number();
229 ic_dbus_call_register_resource_sync(icl_dbus_get_object(), uri_path, types, ifaces,
230 properties, signal_number, &(resource->handle), NULL, &error);
232 ERR("ic_dbus_call_register_resource_sync() Fail(%s)", error->message);
240 if (0 == resource->handle) {
241 ERR("iotcon-daemon Fail");
247 resource->user_data = user_data;
249 resource->types = icl_resource_types_ref(res_types);
250 resource->uri_path = ic_utils_strdup(uri_path);
251 resource->ifaces = ifaces;
252 resource->is_observable = properties & IOTCON_OBSERVABLE;
254 snprintf(sig_name, sizeof(sig_name), "%s_%u", IC_DBUS_SIGNAL_REQUEST_HANDLER,
257 sub_id = icl_dbus_subscribe_signal(sig_name, resource, _icl_resource_conn_cleanup,
258 _icl_request_handler);
260 ERR("icl_dbus_subscribe_signal() Fail");
265 resource->sub_id = sub_id;
271 API int iotcon_unregister_resource(iotcon_resource_h resource)
275 GError *error = NULL;
277 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
278 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
280 if (0 == resource->sub_id) {
281 WARN("Invalid Resource handle");
282 iotcon_resource_types_free(resource->types);
283 free(resource->uri_path);
285 return IOTCON_ERROR_NONE;
288 ic_dbus_call_unregister_resource_sync(icl_dbus_get_object(), resource->handle,
291 ERR("ic_dbus_call_unregister_resource_sync() Fail(%s)", error->message);
293 return IOTCON_ERROR_DBUS;
296 if (IOTCON_ERROR_NONE != ret) {
297 ERR("iotcon-daemon Fail(%d)", ret);
298 return icl_dbus_convert_daemon_error(ret);
301 icl_dbus_unsubscribe_signal(resource->sub_id);
303 iotcon_resource_types_free(resource->types);
304 free(resource->uri_path);
307 return IOTCON_ERROR_NONE;
311 API int iotcon_bind_interface(iotcon_resource_h resource, iotcon_interface_e iface)
315 GError *error = NULL;
317 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
318 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
319 if (0 == resource->sub_id) {
320 ERR("Invalid Resource handle");
321 return IOTCON_ERROR_INVALID_PARAMETER;
324 ic_dbus_call_bind_interface_sync(icl_dbus_get_object(), resource->handle,
325 iface, &ret, NULL, &error);
327 ERR("ic_dbus_call_bind_interface_sync() Fail(%s)", error->message);
329 return IOTCON_ERROR_DBUS;
332 if (IOTCON_ERROR_NONE != ret) {
333 ERR("iotcon-daemon Fail(%d)", ret);
334 return icl_dbus_convert_daemon_error(ret);
341 API int iotcon_bind_type(iotcon_resource_h resource, const char *resource_type)
345 GError *error = NULL;
347 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
348 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
349 RETV_IF(NULL == resource_type, IOTCON_ERROR_INVALID_PARAMETER);
350 if (IOTCON_RESOURCE_TYPE_LENGTH_MAX < strlen(resource_type)) {
351 ERR("Invalid resource_type(%s)", resource_type);
352 return IOTCON_ERROR_INVALID_PARAMETER;
355 if (0 == resource->sub_id) {
356 ERR("Invalid Resource handle");
357 return IOTCON_ERROR_INVALID_PARAMETER;
360 ic_dbus_call_bind_type_sync(icl_dbus_get_object(), resource->handle, resource_type,
363 ERR("ic_dbus_call_bind_type_sync() Fail(%s)", error->message);
365 return IOTCON_ERROR_DBUS;
368 if (IOTCON_ERROR_NONE != ret) {
369 ERR("iotcon-daemon Fail(%d)", ret);
370 return icl_dbus_convert_daemon_error(ret);
377 API int iotcon_bind_request_handler(iotcon_resource_h resource,
378 iotcon_request_handler_cb cb)
380 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
381 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
383 WARN("Request handler is changed");
386 return IOTCON_ERROR_NONE;
390 API int iotcon_bind_resource(iotcon_resource_h parent, iotcon_resource_h child)
395 GError *error = NULL;
397 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
398 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
399 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
400 RETV_IF(parent == child, IOTCON_ERROR_INVALID_PARAMETER);
402 if (0 == parent->sub_id) {
403 ERR("Invalid Resource handle(parent)");
404 return IOTCON_ERROR_INVALID_PARAMETER;
406 if (0 == child->sub_id) {
407 ERR("Invalid Resource handle(child)");
408 return IOTCON_ERROR_INVALID_PARAMETER;
411 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
412 if (child == parent->children[i]) {
413 ERR("Child resource was already bound to parent resource.");
414 return IOTCON_ERROR_ALREADY;
418 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
419 if (NULL == parent->children[i]) {
420 ic_dbus_call_bind_resource_sync(icl_dbus_get_object(), parent->handle,
421 child->handle, &ret, NULL, &error);
423 ERR("ic_dbus_call_bind_resource_sync() Fail(%s)", error->message);
425 return IOTCON_ERROR_DBUS;
428 if (IOTCON_ERROR_NONE != ret) {
429 ERR("iotcon-daemon Fail(%d)", ret);
430 return icl_dbus_convert_daemon_error(ret);
433 parent->children[i] = child;
435 return IOTCON_ERROR_NONE;
439 ERR("There is no slot to bind a child resource");
440 return IOTCON_ERROR_OUT_OF_MEMORY;
444 API int iotcon_unbind_resource(iotcon_resource_h parent, iotcon_resource_h child)
448 GError *error = NULL;
450 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
451 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
452 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
454 if (0 == parent->sub_id) {
455 ERR("Invalid Resource handle(parent)");
456 return IOTCON_ERROR_INVALID_PARAMETER;
458 if (0 == child->sub_id) {
459 ERR("Invalid Resource handle(child)");
460 return IOTCON_ERROR_INVALID_PARAMETER;
463 ic_dbus_call_unbind_resource_sync(icl_dbus_get_object(), parent->handle,
464 child->handle, &ret, NULL, &error);
466 ERR("ic_dbus_call_unbind_resource_sync() Fail(%s)", error->message);
468 return IOTCON_ERROR_DBUS;
471 if (IOTCON_ERROR_NONE != ret) {
472 ERR("iotcon-daemon Fail(%d)", ret);
473 return icl_dbus_convert_daemon_error(ret);
476 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
477 if (child == parent->children[i])
478 parent->children[i] = NULL;
481 return IOTCON_ERROR_NONE;
485 API int iotcon_resource_get_number_of_children(iotcon_resource_h resource, int *number)
489 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
490 RETV_IF(NULL == number, IOTCON_ERROR_INVALID_PARAMETER);
493 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
494 if (resource->children[i])
498 return IOTCON_ERROR_NONE;
502 API int iotcon_resource_get_nth_child(iotcon_resource_h parent, int index,
503 iotcon_resource_h *child)
505 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
506 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
507 if ((index < 0) || (IOTCON_CONTAINED_RESOURCES_MAX <= index)) {
508 ERR("Invalid index(%d)", index);
509 return IOTCON_ERROR_INVALID_PARAMETER;
512 *child = parent->children[index];
514 return IOTCON_ERROR_NONE;
518 /* The content of the resource should not be freed by user. */
519 API int iotcon_resource_get_uri_path(iotcon_resource_h resource, char **uri_path)
521 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
522 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
524 *uri_path = resource->uri_path;
526 return IOTCON_ERROR_NONE;
530 /* The content of the resource should not be freed by user. */
531 API int iotcon_resource_get_types(iotcon_resource_h resource,
532 iotcon_resource_types_h *types)
534 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
535 RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
537 *types = resource->types;
539 return IOTCON_ERROR_NONE;
543 API int iotcon_resource_get_interfaces(iotcon_resource_h resource, int *ifaces)
545 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
546 RETV_IF(NULL == ifaces, IOTCON_ERROR_INVALID_PARAMETER);
548 *ifaces = resource->ifaces;
550 return IOTCON_ERROR_NONE;
554 API int iotcon_resource_is_observable(iotcon_resource_h resource, bool *observable)
556 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
557 RETV_IF(NULL == observable, IOTCON_ERROR_INVALID_PARAMETER);
559 *observable = resource->is_observable;
561 return IOTCON_ERROR_NONE;
565 API iotcon_notimsg_h iotcon_notimsg_new(iotcon_repr_h repr, iotcon_interface_e iface)
567 iotcon_notimsg_h msg;
569 RETV_IF(NULL == repr, NULL);
571 msg = calloc(1, sizeof(struct icl_notify_msg));
573 ERR("calloc() Fail(%d)", errno);
578 icl_repr_inc_ref_count(msg->repr);
580 msg->error_code = 200;
586 API void iotcon_notimsg_free(iotcon_notimsg_h msg)
590 iotcon_repr_free(msg->repr);
595 API int iotcon_notify_list_of_observers(iotcon_resource_h resource, iotcon_notimsg_h msg,
596 iotcon_observers_h observers)
599 GError *error = NULL;
603 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
604 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
605 RETV_IF(NULL == observers, IOTCON_ERROR_INVALID_PARAMETER);
607 if (0 == resource->sub_id) {
608 ERR("Invalid Resource handle");
609 return IOTCON_ERROR_INVALID_PARAMETER;
612 noti_msg = icl_dbus_notimsg_to_gvariant(msg);
613 if (NULL == noti_msg) {
614 ERR("icl_dbus_notimsg_to_gvariant() Fail");
615 return IOTCON_ERROR_REPRESENTATION;
617 obs = icl_dbus_observers_to_gvariant(observers);
619 ic_dbus_call_notify_list_of_observers_sync(icl_dbus_get_object(), resource->handle,
620 noti_msg, obs, &ret, NULL, &error);
622 ERR("ic_dbus_call_notify_list_of_observers_sync() Fail(%s)", error->message);
624 g_variant_unref(obs);
625 g_variant_unref(noti_msg);
626 return IOTCON_ERROR_DBUS;
629 if (IOTCON_ERROR_NONE != ret) {
630 ERR("iotcon-daemon Fail(%d)", ret);
631 return icl_dbus_convert_daemon_error(ret);
634 return IOTCON_ERROR_NONE;
638 API int iotcon_notify_all(iotcon_resource_h resource)
641 GError *error = NULL;
643 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
644 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
645 if (0 == resource->sub_id) {
646 ERR("Invalid Resource handle");
647 return IOTCON_ERROR_INVALID_PARAMETER;
650 ic_dbus_call_notify_all_sync(icl_dbus_get_object(), resource->handle, &ret, NULL,
653 ERR("ic_dbus_call_notify_all_sync() Fail(%s)", error->message);
655 return IOTCON_ERROR_DBUS;
658 if (IOTCON_ERROR_NONE != ret) {
659 ERR("iotcon-daemon Fail(%d)", ret);
660 return icl_dbus_convert_daemon_error(ret);
663 return IOTCON_ERROR_NONE;