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.
26 #include "icl-resource-types.h"
27 #include "icl-resource.h"
28 #include "icl-request.h"
31 #include "icl-dbus-type.h"
34 static void _icl_request_handler(GDBusConnection *connection,
35 const gchar *sender_name,
36 const gchar *object_path,
37 const gchar *interface_name,
38 const gchar *signal_name,
42 GVariantIter *options;
43 unsigned short option_id;
51 struct icl_resource_request request = {0};
52 iotcon_resource_h resource = user_data;
53 iotcon_request_handler_cb cb = resource->cb;
55 g_variant_get(parameters, "(ia(qs)a(ss)ii&sii)",
59 &request.observation_info.action,
60 &request.observation_info.observer_id,
65 if (g_variant_iter_n_children(options)) {
66 request.header_options = iotcon_options_new();
67 while (g_variant_iter_loop(options, "(q&s)", &option_id, &option_data))
68 iotcon_options_insert(request.header_options, option_id, option_data);
70 g_variant_iter_free(options);
72 if (g_variant_iter_n_children(query)) {
73 request.query = iotcon_query_new();
74 while (g_variant_iter_loop(query, "(&s&s)", &key, &value))
75 iotcon_query_insert(request.query, key, value);
77 g_variant_iter_free(query);
79 request.request_handle = GINT_TO_POINTER(request_handle);
80 request.resource_handle = GINT_TO_POINTER(resource_handle);
82 if (ic_utils_dbus_decode_str(repr_json)) {
83 request.repr = icl_repr_create_repr(repr_json);
84 if (NULL == request.repr) {
85 ERR("icl_repr_create_repr() Fail");
87 iotcon_query_free(request.query);
88 if (request.header_options)
89 iotcon_options_free(request.header_options);
94 /* TODO remove request.uri */
95 request.uri_path = "temp_uri_path";
98 cb(resource, &request, resource->user_data);
100 /* To avoid unnecessary ERR log (repr could be NULL) */
102 iotcon_repr_free(request.repr);
104 iotcon_query_free(request.query);
105 if (request.header_options)
106 iotcon_options_free(request.header_options);
110 static void _icl_resource_conn_cleanup(iotcon_resource_h resource)
112 resource->sub_id = 0;
113 resource->handle = 0;
117 /* The length of uri_path should be less than or equal to 36. */
118 API iotcon_resource_h iotcon_register_resource(const char *uri_path,
119 iotcon_resource_types_h res_types,
122 iotcon_request_handler_cb cb,
128 GError *error = NULL;
130 char sig_name[IC_DBUS_SIGNAL_LENGTH];
131 iotcon_resource_h resource;
133 RETV_IF(NULL == icl_dbus_get_object(), NULL);
134 RETV_IF(NULL == uri_path, NULL);
135 RETVM_IF(IOTCON_URI_PATH_LENGTH_MAX < strlen(uri_path), NULL, "Invalid uri_path(%s)",
137 RETV_IF(NULL == res_types, NULL);
138 RETV_IF(NULL == cb, NULL);
140 resource = calloc(1, sizeof(struct icl_resource));
141 if (NULL == resource) {
142 ERR("calloc() Fail(%d)", errno);
146 types = icl_dbus_resource_types_to_array(res_types);
148 ERR("icl_dbus_resource_types_to_array() Fail");
153 signal_number = icl_dbus_generate_signal_number();
155 ic_dbus_call_register_resource_sync(icl_dbus_get_object(), uri_path, types, ifaces,
156 properties, signal_number, &(resource->handle), NULL, &error);
158 ERR("ic_dbus_call_register_resource_sync() Fail(%s)", error->message);
166 if (0 == resource->handle) {
167 ERR("iotcon-daemon Fail");
173 resource->user_data = user_data;
175 resource->types = icl_resource_types_ref(res_types);
176 resource->uri_path = ic_utils_strdup(uri_path);
177 resource->ifaces = ifaces;
178 resource->is_observable = properties & IOTCON_OBSERVABLE;
180 snprintf(sig_name, sizeof(sig_name), "%s_%u", IC_DBUS_SIGNAL_REQUEST_HANDLER,
183 sub_id = icl_dbus_subscribe_signal(sig_name, resource, _icl_resource_conn_cleanup,
184 _icl_request_handler);
186 ERR("icl_dbus_subscribe_signal() Fail");
191 resource->sub_id = sub_id;
197 API int iotcon_unregister_resource(iotcon_resource_h resource)
201 GError *error = NULL;
203 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
204 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
206 if (0 == resource->sub_id) {
207 WARN("Invalid Resource handle");
208 iotcon_resource_types_free(resource->types);
209 free(resource->uri_path);
211 return IOTCON_ERROR_NONE;
214 ic_dbus_call_unregister_resource_sync(icl_dbus_get_object(), resource->handle,
217 ERR("ic_dbus_call_unregister_resource_sync() Fail(%s)", error->message);
219 return IOTCON_ERROR_DBUS;
222 if (IOTCON_ERROR_NONE != ret) {
223 ERR("iotcon-daemon Fail(%d)", ret);
224 return icl_dbus_convert_daemon_error(ret);
227 icl_dbus_unsubscribe_signal(resource->sub_id);
229 iotcon_resource_types_free(resource->types);
230 free(resource->uri_path);
233 return IOTCON_ERROR_NONE;
237 API int iotcon_bind_interface(iotcon_resource_h resource, iotcon_interface_e iface)
241 GError *error = NULL;
243 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
244 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
245 if (0 == resource->sub_id) {
246 ERR("Invalid Resource handle");
247 return IOTCON_ERROR_INVALID_PARAMETER;
250 ic_dbus_call_bind_interface_sync(icl_dbus_get_object(), resource->handle,
251 iface, &ret, NULL, &error);
253 ERR("ic_dbus_call_bind_interface_sync() Fail(%s)", error->message);
255 return IOTCON_ERROR_DBUS;
258 if (IOTCON_ERROR_NONE != ret) {
259 ERR("iotcon-daemon Fail(%d)", ret);
260 return icl_dbus_convert_daemon_error(ret);
267 API int iotcon_bind_type(iotcon_resource_h resource, const char *resource_type)
271 GError *error = NULL;
273 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
274 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
275 RETV_IF(NULL == resource_type, IOTCON_ERROR_INVALID_PARAMETER);
276 if (IOTCON_RESOURCE_TYPE_LENGTH_MAX < strlen(resource_type)) {
277 ERR("Invalid resource_type(%s)", resource_type);
278 return IOTCON_ERROR_INVALID_PARAMETER;
281 if (0 == resource->sub_id) {
282 ERR("Invalid Resource handle");
283 return IOTCON_ERROR_INVALID_PARAMETER;
286 ic_dbus_call_bind_type_sync(icl_dbus_get_object(), resource->handle, resource_type,
289 ERR("ic_dbus_call_bind_type_sync() Fail(%s)", error->message);
291 return IOTCON_ERROR_DBUS;
294 if (IOTCON_ERROR_NONE != ret) {
295 ERR("iotcon-daemon Fail(%d)", ret);
296 return icl_dbus_convert_daemon_error(ret);
303 API int iotcon_bind_request_handler(iotcon_resource_h resource,
304 iotcon_request_handler_cb cb)
306 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
307 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
309 WARN("Request handler is changed");
312 return IOTCON_ERROR_NONE;
316 API int iotcon_bind_resource(iotcon_resource_h parent, iotcon_resource_h child)
321 GError *error = NULL;
323 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
324 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
325 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
326 RETV_IF(parent == child, IOTCON_ERROR_INVALID_PARAMETER);
328 if (0 == parent->sub_id) {
329 ERR("Invalid Resource handle(parent)");
330 return IOTCON_ERROR_INVALID_PARAMETER;
332 if (0 == child->sub_id) {
333 ERR("Invalid Resource handle(child)");
334 return IOTCON_ERROR_INVALID_PARAMETER;
337 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
338 if (child == parent->children[i]) {
339 ERR("Child resource was already bound to parent resource.");
340 return IOTCON_ERROR_ALREADY;
344 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
345 if (NULL == parent->children[i]) {
346 ic_dbus_call_bind_resource_sync(icl_dbus_get_object(), parent->handle,
347 child->handle, &ret, NULL, &error);
349 ERR("ic_dbus_call_bind_resource_sync() Fail(%s)", error->message);
351 return IOTCON_ERROR_DBUS;
354 if (IOTCON_ERROR_NONE != ret) {
355 ERR("iotcon-daemon Fail(%d)", ret);
356 return icl_dbus_convert_daemon_error(ret);
359 parent->children[i] = child;
361 return IOTCON_ERROR_NONE;
365 ERR("There is no slot to bind a child resource");
366 return IOTCON_ERROR_OUT_OF_MEMORY;
370 API int iotcon_unbind_resource(iotcon_resource_h parent, iotcon_resource_h child)
374 GError *error = NULL;
376 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
377 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
378 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
380 if (0 == parent->sub_id) {
381 ERR("Invalid Resource handle(parent)");
382 return IOTCON_ERROR_INVALID_PARAMETER;
384 if (0 == child->sub_id) {
385 ERR("Invalid Resource handle(child)");
386 return IOTCON_ERROR_INVALID_PARAMETER;
389 ic_dbus_call_unbind_resource_sync(icl_dbus_get_object(), parent->handle,
390 child->handle, &ret, NULL, &error);
392 ERR("ic_dbus_call_unbind_resource_sync() Fail(%s)", error->message);
394 return IOTCON_ERROR_DBUS;
397 if (IOTCON_ERROR_NONE != ret) {
398 ERR("iotcon-daemon Fail(%d)", ret);
399 return icl_dbus_convert_daemon_error(ret);
402 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
403 if (child == parent->children[i])
404 parent->children[i] = NULL;
407 return IOTCON_ERROR_NONE;
411 API int iotcon_resource_get_number_of_children(iotcon_resource_h resource, int *number)
415 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
416 RETV_IF(NULL == number, IOTCON_ERROR_INVALID_PARAMETER);
419 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
420 if (resource->children[i])
424 return IOTCON_ERROR_NONE;
428 API int iotcon_resource_get_nth_child(iotcon_resource_h parent, int index,
429 iotcon_resource_h *child)
431 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
432 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
433 if ((index < 0) || (IOTCON_CONTAINED_RESOURCES_MAX <= index)) {
434 ERR("Invalid index(%d)", index);
435 return IOTCON_ERROR_INVALID_PARAMETER;
438 *child = parent->children[index];
440 return IOTCON_ERROR_NONE;
444 /* The content of the resource should not be freed by user. */
445 API int iotcon_resource_get_uri_path(iotcon_resource_h resource, char **uri_path)
447 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
448 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
450 *uri_path = resource->uri_path;
452 return IOTCON_ERROR_NONE;
456 /* The content of the resource should not be freed by user. */
457 API int iotcon_resource_get_types(iotcon_resource_h resource,
458 iotcon_resource_types_h *types)
460 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
461 RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
463 *types = resource->types;
465 return IOTCON_ERROR_NONE;
469 API int iotcon_resource_get_interfaces(iotcon_resource_h resource, int *ifaces)
471 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
472 RETV_IF(NULL == ifaces, IOTCON_ERROR_INVALID_PARAMETER);
474 *ifaces = resource->ifaces;
476 return IOTCON_ERROR_NONE;
480 API int iotcon_resource_is_observable(iotcon_resource_h resource, bool *observable)
482 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
483 RETV_IF(NULL == observable, IOTCON_ERROR_INVALID_PARAMETER);
485 *observable = resource->is_observable;
487 return IOTCON_ERROR_NONE;
491 API iotcon_notimsg_h iotcon_notimsg_new(iotcon_repr_h repr, iotcon_interface_e iface)
493 iotcon_notimsg_h msg;
495 RETV_IF(NULL == repr, NULL);
497 msg = calloc(1, sizeof(struct icl_notify_msg));
499 ERR("calloc() Fail(%d)", errno);
504 icl_repr_inc_ref_count(msg->repr);
506 msg->error_code = 200;
512 API void iotcon_notimsg_free(iotcon_notimsg_h msg)
516 iotcon_repr_free(msg->repr);
521 API int iotcon_notify_list_of_observers(iotcon_resource_h resource, iotcon_notimsg_h msg,
522 iotcon_observers_h observers)
525 GError *error = NULL;
529 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
530 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
531 RETV_IF(NULL == observers, IOTCON_ERROR_INVALID_PARAMETER);
533 if (0 == resource->sub_id) {
534 ERR("Invalid Resource handle");
535 return IOTCON_ERROR_INVALID_PARAMETER;
538 noti_msg = icl_dbus_notimsg_to_gvariant(msg);
539 if (NULL == noti_msg) {
540 ERR("icl_dbus_notimsg_to_gvariant() Fail");
541 return IOTCON_ERROR_REPRESENTATION;
543 obs = icl_dbus_observers_to_gvariant(observers);
545 ic_dbus_call_notify_list_of_observers_sync(icl_dbus_get_object(), resource->handle,
546 noti_msg, obs, &ret, NULL, &error);
548 ERR("ic_dbus_call_notify_list_of_observers_sync() Fail(%s)", error->message);
550 g_variant_unref(obs);
551 g_variant_unref(noti_msg);
552 return IOTCON_ERROR_DBUS;
555 if (IOTCON_ERROR_NONE != ret) {
556 ERR("iotcon-daemon Fail(%d)", ret);
557 return icl_dbus_convert_daemon_error(ret);
560 return IOTCON_ERROR_NONE;
564 API int iotcon_notify_all(iotcon_resource_h resource)
567 GError *error = NULL;
569 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
570 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
571 if (0 == resource->sub_id) {
572 ERR("Invalid Resource handle");
573 return IOTCON_ERROR_INVALID_PARAMETER;
576 ic_dbus_call_notify_all_sync(icl_dbus_get_object(), resource->handle, &ret, NULL,
579 ERR("ic_dbus_call_notify_all_sync() Fail(%s)", error->message);
581 return IOTCON_ERROR_DBUS;
584 if (IOTCON_ERROR_NONE != ret) {
585 ERR("iotcon-daemon Fail(%d)", ret);
586 return icl_dbus_convert_daemon_error(ret);
589 return IOTCON_ERROR_NONE;