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"
33 #include "icl-payload.h"
36 * @brief The maximum length of uri_path path which can be held in a resource.
40 #define IOTCON_URI_PATH_LENGTH_MAX 36
43 static void _icl_request_handler(GDBusConnection *connection,
44 const gchar *sender_name,
45 const gchar *object_path,
46 const gchar *interface_name,
47 const gchar *signal_name,
52 GVariantIter *options;
53 unsigned short option_id;
56 GVariantIter *repr_iter;
59 struct icl_resource_request request = {0};
60 iotcon_resource_h resource = user_data;
61 iotcon_request_handler_cb cb = resource->cb;
64 g_variant_get(parameters, "(ia(qs)a(ss)iiavxx)",
68 &request.observation_info.action,
69 &request.observation_info.observer_id,
71 &request.oic_request_h,
72 &request.oic_resource_h);
74 if (g_variant_iter_n_children(options)) {
75 request.header_options = iotcon_options_new();
76 while (g_variant_iter_loop(options, "(q&s)", &option_id, &option_data))
77 iotcon_options_insert(request.header_options, option_id, option_data);
79 g_variant_iter_free(options);
81 if (g_variant_iter_n_children(query)) {
82 request.query = iotcon_query_new();
83 while (g_variant_iter_loop(query, "(&s&s)", &key, &value))
84 iotcon_query_insert(request.query, key, value);
86 g_variant_iter_free(query);
88 if (g_variant_iter_loop(repr_iter, "v", &repr_gvar)) {
89 request.repr = icl_repr_from_gvariant(repr_gvar);
90 if (NULL == request.repr) {
91 ERR("icl_repr_create_repr() Fail");
93 iotcon_query_free(request.query);
94 if (request.header_options)
95 iotcon_options_free(request.header_options);
100 /* TODO remove request.uri */
101 request.uri_path = "temp_uri_path";
104 cb(resource, &request, resource->user_data);
106 /* To avoid unnecessary ERR log (repr could be NULL) */
108 iotcon_repr_free(request.repr);
110 iotcon_query_free(request.query);
111 if (request.header_options)
112 iotcon_options_free(request.header_options);
116 static void _icl_resource_conn_cleanup(iotcon_resource_h resource)
118 resource->sub_id = 0;
120 if (resource->handle) {
121 resource->handle = 0;
125 iotcon_resource_types_free(resource->types);
126 free(resource->uri_path);
131 /* The length of uri_path should be less than or equal to 36. */
132 API iotcon_resource_h iotcon_register_resource(const char *uri_path,
133 iotcon_resource_types_h res_types,
136 iotcon_request_handler_cb cb,
141 GError *error = NULL;
143 char sig_name[IC_DBUS_SIGNAL_LENGTH];
144 iotcon_resource_h resource;
146 RETV_IF(NULL == icl_dbus_get_object(), NULL);
147 RETV_IF(NULL == uri_path, NULL);
148 RETVM_IF(IOTCON_URI_PATH_LENGTH_MAX < strlen(uri_path), NULL, "Invalid uri_path(%s)",
150 RETV_IF(NULL == res_types, NULL);
151 RETV_IF(NULL == cb, NULL);
153 resource = calloc(1, sizeof(struct icl_resource));
154 if (NULL == resource) {
155 ERR("calloc() Fail(%d)", errno);
159 types = icl_dbus_resource_types_to_array(res_types);
161 ERR("icl_dbus_resource_types_to_array() Fail");
166 signal_number = icl_dbus_generate_signal_number();
168 ic_dbus_call_register_resource_sync(icl_dbus_get_object(), uri_path, types, ifaces,
169 properties, signal_number, &(resource->handle), NULL, &error);
171 ERR("ic_dbus_call_register_resource_sync() Fail(%s)", error->message);
179 if (0 == resource->handle) {
180 ERR("iotcon-daemon Fail");
186 resource->user_data = user_data;
188 resource->types = icl_resource_types_ref(res_types);
189 resource->uri_path = ic_utils_strdup(uri_path);
190 resource->ifaces = ifaces;
191 resource->is_observable = properties & IOTCON_OBSERVABLE;
193 snprintf(sig_name, sizeof(sig_name), "%s_%u", IC_DBUS_SIGNAL_REQUEST_HANDLER,
196 sub_id = icl_dbus_subscribe_signal(sig_name, resource, _icl_resource_conn_cleanup,
197 _icl_request_handler);
199 ERR("icl_dbus_subscribe_signal() Fail");
204 resource->sub_id = sub_id;
210 API int iotcon_unregister_resource(iotcon_resource_h resource)
214 GError *error = NULL;
216 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
217 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
219 if (0 == resource->sub_id) {
220 WARN("Invalid Resource handle");
221 iotcon_resource_types_free(resource->types);
222 free(resource->uri_path);
224 return IOTCON_ERROR_NONE;
227 ic_dbus_call_unregister_resource_sync(icl_dbus_get_object(), resource->handle,
230 ERR("ic_dbus_call_unregister_resource_sync() Fail(%s)", error->message);
232 return IOTCON_ERROR_DBUS;
235 if (IOTCON_ERROR_NONE != ret) {
236 ERR("iotcon-daemon Fail(%d)", ret);
237 return icl_dbus_convert_daemon_error(ret);
239 resource->handle = 0;
241 icl_dbus_unsubscribe_signal(resource->sub_id);
243 return IOTCON_ERROR_NONE;
247 API int iotcon_bind_interface(iotcon_resource_h resource, iotcon_interface_e iface)
251 GError *error = NULL;
253 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
254 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
255 if (0 == resource->sub_id) {
256 ERR("Invalid Resource handle");
257 return IOTCON_ERROR_INVALID_PARAMETER;
260 ic_dbus_call_bind_interface_sync(icl_dbus_get_object(), resource->handle,
261 iface, &ret, NULL, &error);
263 ERR("ic_dbus_call_bind_interface_sync() Fail(%s)", error->message);
265 return IOTCON_ERROR_DBUS;
268 if (IOTCON_ERROR_NONE != ret) {
269 ERR("iotcon-daemon Fail(%d)", ret);
270 return icl_dbus_convert_daemon_error(ret);
277 API int iotcon_bind_type(iotcon_resource_h resource, const char *resource_type)
281 GError *error = NULL;
283 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
284 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
285 RETV_IF(NULL == resource_type, IOTCON_ERROR_INVALID_PARAMETER);
286 if (IOTCON_RESOURCE_TYPE_LENGTH_MAX < strlen(resource_type)) {
287 ERR("Invalid resource_type(%s)", resource_type);
288 return IOTCON_ERROR_INVALID_PARAMETER;
291 if (0 == resource->sub_id) {
292 ERR("Invalid Resource handle");
293 return IOTCON_ERROR_INVALID_PARAMETER;
296 ic_dbus_call_bind_type_sync(icl_dbus_get_object(), resource->handle, resource_type,
299 ERR("ic_dbus_call_bind_type_sync() Fail(%s)", error->message);
301 return IOTCON_ERROR_DBUS;
304 if (IOTCON_ERROR_NONE != ret) {
305 ERR("iotcon-daemon Fail(%d)", ret);
306 return icl_dbus_convert_daemon_error(ret);
313 API int iotcon_bind_request_handler(iotcon_resource_h resource,
314 iotcon_request_handler_cb cb)
316 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
317 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
319 WARN("Request handler is changed");
322 return IOTCON_ERROR_NONE;
326 API int iotcon_bind_resource(iotcon_resource_h parent, iotcon_resource_h child)
331 GError *error = NULL;
333 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
334 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
335 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
336 RETV_IF(parent == child, IOTCON_ERROR_INVALID_PARAMETER);
338 if (0 == parent->sub_id) {
339 ERR("Invalid Resource handle(parent)");
340 return IOTCON_ERROR_INVALID_PARAMETER;
342 if (0 == child->sub_id) {
343 ERR("Invalid Resource handle(child)");
344 return IOTCON_ERROR_INVALID_PARAMETER;
347 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
348 if (child == parent->children[i]) {
349 ERR("Child resource was already bound to parent resource.");
350 return IOTCON_ERROR_ALREADY;
354 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
355 if (NULL == parent->children[i]) {
356 ic_dbus_call_bind_resource_sync(icl_dbus_get_object(), parent->handle,
357 child->handle, &ret, NULL, &error);
359 ERR("ic_dbus_call_bind_resource_sync() Fail(%s)", error->message);
361 return IOTCON_ERROR_DBUS;
364 if (IOTCON_ERROR_NONE != ret) {
365 ERR("iotcon-daemon Fail(%d)", ret);
366 return icl_dbus_convert_daemon_error(ret);
369 parent->children[i] = child;
371 return IOTCON_ERROR_NONE;
375 ERR("There is no slot to bind a child resource");
376 return IOTCON_ERROR_OUT_OF_MEMORY;
380 API int iotcon_unbind_resource(iotcon_resource_h parent, iotcon_resource_h child)
384 GError *error = NULL;
386 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
387 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
388 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
390 if (0 == parent->sub_id) {
391 ERR("Invalid Resource handle(parent)");
392 return IOTCON_ERROR_INVALID_PARAMETER;
394 if (0 == child->sub_id) {
395 ERR("Invalid Resource handle(child)");
396 return IOTCON_ERROR_INVALID_PARAMETER;
399 ic_dbus_call_unbind_resource_sync(icl_dbus_get_object(), parent->handle,
400 child->handle, &ret, NULL, &error);
402 ERR("ic_dbus_call_unbind_resource_sync() Fail(%s)", error->message);
404 return IOTCON_ERROR_DBUS;
407 if (IOTCON_ERROR_NONE != ret) {
408 ERR("iotcon-daemon Fail(%d)", ret);
409 return icl_dbus_convert_daemon_error(ret);
412 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
413 if (child == parent->children[i])
414 parent->children[i] = NULL;
417 return IOTCON_ERROR_NONE;
421 API int iotcon_resource_get_number_of_children(iotcon_resource_h resource, int *number)
425 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
426 RETV_IF(NULL == number, IOTCON_ERROR_INVALID_PARAMETER);
429 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
430 if (resource->children[i])
434 return IOTCON_ERROR_NONE;
438 API int iotcon_resource_get_nth_child(iotcon_resource_h parent, int index,
439 iotcon_resource_h *child)
441 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
442 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
443 if ((index < 0) || (IOTCON_CONTAINED_RESOURCES_MAX <= index)) {
444 ERR("Invalid index(%d)", index);
445 return IOTCON_ERROR_INVALID_PARAMETER;
448 *child = parent->children[index];
450 return IOTCON_ERROR_NONE;
454 /* The content of the resource should not be freed by user. */
455 API int iotcon_resource_get_uri_path(iotcon_resource_h resource, char **uri_path)
457 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
458 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
460 *uri_path = resource->uri_path;
462 return IOTCON_ERROR_NONE;
466 /* The content of the resource should not be freed by user. */
467 API int iotcon_resource_get_types(iotcon_resource_h resource,
468 iotcon_resource_types_h *types)
470 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
471 RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
473 *types = resource->types;
475 return IOTCON_ERROR_NONE;
479 API int iotcon_resource_get_interfaces(iotcon_resource_h resource, int *ifaces)
481 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
482 RETV_IF(NULL == ifaces, IOTCON_ERROR_INVALID_PARAMETER);
484 *ifaces = resource->ifaces;
486 return IOTCON_ERROR_NONE;
490 API int iotcon_resource_is_observable(iotcon_resource_h resource, bool *observable)
492 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
493 RETV_IF(NULL == observable, IOTCON_ERROR_INVALID_PARAMETER);
495 *observable = resource->is_observable;
497 return IOTCON_ERROR_NONE;
501 API iotcon_notimsg_h iotcon_notimsg_new(iotcon_repr_h repr, iotcon_interface_e iface)
503 iotcon_notimsg_h msg;
505 RETV_IF(NULL == repr, NULL);
507 msg = calloc(1, sizeof(struct icl_notify_msg));
509 ERR("calloc() Fail(%d)", errno);
514 icl_repr_inc_ref_count(msg->repr);
516 msg->error_code = 200;
522 API void iotcon_notimsg_free(iotcon_notimsg_h msg)
526 iotcon_repr_free(msg->repr);
531 API int iotcon_notify_list_of_observers(iotcon_resource_h resource, iotcon_notimsg_h msg,
532 iotcon_observers_h observers)
535 GError *error = NULL;
539 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
540 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
541 RETV_IF(NULL == observers, IOTCON_ERROR_INVALID_PARAMETER);
543 if (0 == resource->sub_id) {
544 ERR("Invalid Resource handle");
545 return IOTCON_ERROR_INVALID_PARAMETER;
548 noti_msg = icl_dbus_notimsg_to_gvariant(msg);
549 if (NULL == noti_msg) {
550 ERR("icl_dbus_notimsg_to_gvariant() Fail");
551 return IOTCON_ERROR_REPRESENTATION;
553 obs = icl_dbus_observers_to_gvariant(observers);
555 ic_dbus_call_notify_list_of_observers_sync(icl_dbus_get_object(), resource->handle,
556 noti_msg, obs, &ret, NULL, &error);
558 ERR("ic_dbus_call_notify_list_of_observers_sync() Fail(%s)", error->message);
560 g_variant_unref(obs);
561 g_variant_unref(noti_msg);
562 return IOTCON_ERROR_DBUS;
565 if (IOTCON_ERROR_NONE != ret) {
566 ERR("iotcon-daemon Fail(%d)", ret);
567 return icl_dbus_convert_daemon_error(ret);
570 return IOTCON_ERROR_NONE;
574 API int iotcon_notify_all(iotcon_resource_h resource)
577 GError *error = NULL;
579 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
580 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
581 if (0 == resource->sub_id) {
582 ERR("Invalid Resource handle");
583 return IOTCON_ERROR_INVALID_PARAMETER;
586 ic_dbus_call_notify_all_sync(icl_dbus_get_object(), resource->handle, &ret, NULL,
589 ERR("ic_dbus_call_notify_all_sync() Fail(%s)", error->message);
591 return IOTCON_ERROR_DBUS;
594 if (IOTCON_ERROR_NONE != ret) {
595 ERR("iotcon-daemon Fail(%d)", ret);
596 return icl_dbus_convert_daemon_error(ret);
599 return IOTCON_ERROR_NONE;