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.
29 #include "icl-request.h"
30 #include "icl-dbus-type.h"
31 #include "icl-resource-types.h"
32 #include "icl-resource.h"
33 #include "icl-payload.h"
36 * @brief The maximum length of uri_path path which can be held in a resource.
40 #define ICL_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,
58 GVariantIter *options;
59 GVariantIter *repr_iter;
60 unsigned short option_id;
61 struct icl_resource_request request = {0};
62 iotcon_resource_h resource = user_data;
63 iotcon_request_handler_cb cb = resource->cb;
65 g_variant_get(parameters, "(ia(qs)a(ss)iiavxx)",
69 &request.observation_info.action,
70 &request.observation_info.observer_id,
72 &request.oic_request_h,
73 &request.oic_resource_h);
75 if (g_variant_iter_n_children(options)) {
76 ret = iotcon_options_create(&request.header_options);
77 if (IOTCON_ERROR_NONE != ret) {
78 ERR("iotcon_options_create() Fail(%d)", ret);
79 g_variant_iter_free(options);
80 g_variant_iter_free(query);
81 g_variant_iter_free(repr_iter);
85 while (g_variant_iter_loop(options, "(q&s)", &option_id, &option_data))
86 iotcon_options_insert(request.header_options, option_id, option_data);
88 g_variant_iter_free(options);
90 if (g_variant_iter_n_children(query)) {
91 ret = iotcon_query_create(&request.query);
92 if (IOTCON_ERROR_NONE != ret) {
93 ERR("iotcon_query_create() Fail(%d)", ret);
94 g_variant_iter_free(query);
95 g_variant_iter_free(repr_iter);
99 while (g_variant_iter_loop(query, "(&s&s)", &key, &value))
100 iotcon_query_insert(request.query, key, value);
102 g_variant_iter_free(query);
104 if (g_variant_iter_loop(repr_iter, "v", &repr_gvar)) {
105 request.repr = icl_representation_from_gvariant(repr_gvar);
106 if (NULL == request.repr) {
107 ERR("icl_representation_from_gvariant() Fail");
109 iotcon_query_destroy(request.query);
110 if (request.header_options)
111 iotcon_options_destroy(request.header_options);
115 g_variant_iter_free(repr_iter);
117 /* TODO remove request.uri */
118 request.uri_path = "temp_uri_path";
121 cb(resource, &request, resource->user_data);
123 /* To avoid unnecessary ERR log (representation could be NULL) */
125 iotcon_representation_destroy(request.repr);
127 iotcon_query_destroy(request.query);
128 if (request.header_options)
129 iotcon_options_destroy(request.header_options);
133 static void _icl_resource_conn_cleanup(iotcon_resource_h resource)
135 resource->sub_id = 0;
137 if (resource->handle) {
138 resource->handle = 0;
142 iotcon_resource_types_destroy(resource->types);
143 free(resource->uri_path);
148 /* The length of uri_path should be less than or equal to 36. */
149 API int iotcon_register_resource(const char *uri_path,
150 iotcon_resource_types_h res_types,
153 iotcon_request_handler_cb cb,
155 iotcon_resource_h *resource_handle)
158 GError *error = NULL;
160 iotcon_resource_h resource;
161 int signal_number, error_code;
162 char sig_name[IC_DBUS_SIGNAL_LENGTH];
164 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_INVALID_PARAMETER);
165 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
166 RETVM_IF(ICL_URI_PATH_LENGTH_MAX < strlen(uri_path),
167 IOTCON_ERROR_INVALID_PARAMETER, "Invalid uri_path(%s)", uri_path);
168 RETV_IF(NULL == res_types, IOTCON_ERROR_INVALID_PARAMETER);
169 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
171 resource = calloc(1, sizeof(struct icl_resource));
172 if (NULL == resource) {
173 ERR("calloc() Fail(%d)", errno);
174 return IOTCON_ERROR_OUT_OF_MEMORY;
177 types = icl_dbus_resource_types_to_array(res_types);
179 ERR("icl_dbus_resource_types_to_array() Fail");
181 return IOTCON_ERROR_INVALID_PARAMETER;
184 signal_number = icl_dbus_generate_signal_number();
186 ic_dbus_call_register_resource_sync(icl_dbus_get_object(), uri_path, types, ifaces,
187 properties, signal_number, &(resource->handle), NULL, &error);
189 ERR("ic_dbus_call_register_resource_sync() Fail(%s)", error->message);
190 error_code = icl_dbus_convert_dbus_error(error->code);
198 if (0 == resource->handle) {
199 ERR("iotcon-daemon Fail");
201 return IOTCON_ERROR_IOTIVITY;
205 resource->user_data = user_data;
207 resource->types = icl_resource_types_ref(res_types);
208 resource->uri_path = ic_utils_strdup(uri_path);
209 resource->ifaces = ifaces;
210 resource->is_observable = properties & IOTCON_OBSERVABLE;
212 snprintf(sig_name, sizeof(sig_name), "%s_%u", IC_DBUS_SIGNAL_REQUEST_HANDLER,
215 sub_id = icl_dbus_subscribe_signal(sig_name, resource, _icl_resource_conn_cleanup,
216 _icl_request_handler);
218 ERR("icl_dbus_subscribe_signal() Fail");
220 return IOTCON_ERROR_DBUS;
223 resource->sub_id = sub_id;
225 *resource_handle = resource;
227 return IOTCON_ERROR_NONE;
231 API int iotcon_unregister_resource(iotcon_resource_h resource)
235 GError *error = NULL;
237 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
238 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
240 if (0 == resource->sub_id) {
241 WARN("Invalid Resource handle");
242 iotcon_resource_types_destroy(resource->types);
243 free(resource->uri_path);
245 return IOTCON_ERROR_NONE;
248 ic_dbus_call_unregister_resource_sync(icl_dbus_get_object(), resource->handle,
251 ERR("ic_dbus_call_unregister_resource_sync() Fail(%s)", error->message);
252 error_code = icl_dbus_convert_dbus_error(error->code);
257 if (IOTCON_ERROR_NONE != ret) {
258 ERR("iotcon-daemon Fail(%d)", ret);
259 return icl_dbus_convert_daemon_error(ret);
261 resource->handle = 0;
263 icl_dbus_unsubscribe_signal(resource->sub_id);
265 return IOTCON_ERROR_NONE;
269 API int iotcon_resource_bind_interface(iotcon_resource_h resource, int iface)
273 GError *error = NULL;
275 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
276 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
277 if (0 == resource->sub_id) {
278 ERR("Invalid Resource handle");
279 return IOTCON_ERROR_INVALID_PARAMETER;
282 ic_dbus_call_bind_interface_sync(icl_dbus_get_object(), resource->handle,
283 iface, &ret, NULL, &error);
285 ERR("ic_dbus_call_bind_interface_sync() Fail(%s)", error->message);
286 error_code = icl_dbus_convert_dbus_error(error->code);
291 if (IOTCON_ERROR_NONE != ret) {
292 ERR("iotcon-daemon Fail(%d)", ret);
293 return icl_dbus_convert_daemon_error(ret);
300 API int iotcon_resource_bind_type(iotcon_resource_h resource, const char *resource_type)
304 GError *error = NULL;
306 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
307 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
308 RETV_IF(NULL == resource_type, IOTCON_ERROR_INVALID_PARAMETER);
309 if (ICL_RESOURCE_TYPE_LENGTH_MAX < strlen(resource_type)) {
310 ERR("Invalid resource_type(%s)", resource_type);
311 return IOTCON_ERROR_INVALID_PARAMETER;
314 if (0 == resource->sub_id) {
315 ERR("Invalid Resource handle");
316 return IOTCON_ERROR_INVALID_PARAMETER;
319 ic_dbus_call_bind_type_sync(icl_dbus_get_object(), resource->handle, resource_type,
322 ERR("ic_dbus_call_bind_type_sync() Fail(%s)", error->message);
323 error_code = icl_dbus_convert_dbus_error(error->code);
328 if (IOTCON_ERROR_NONE != ret) {
329 ERR("iotcon-daemon Fail(%d)", ret);
330 return icl_dbus_convert_daemon_error(ret);
337 API int iotcon_resource_bind_request_handler(iotcon_resource_h resource,
338 iotcon_request_handler_cb cb)
340 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
341 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
343 WARN("Request handler is changed");
346 return IOTCON_ERROR_NONE;
350 API int iotcon_resource_bind_child_resource(iotcon_resource_h parent,
351 iotcon_resource_h child)
353 GError *error = NULL;
354 int i, ret, error_code;
356 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
357 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
358 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
359 RETV_IF(parent == child, IOTCON_ERROR_INVALID_PARAMETER);
361 if (0 == parent->sub_id) {
362 ERR("Invalid Resource handle(parent)");
363 return IOTCON_ERROR_INVALID_PARAMETER;
365 if (0 == child->sub_id) {
366 ERR("Invalid Resource handle(child)");
367 return IOTCON_ERROR_INVALID_PARAMETER;
370 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
371 if (child == parent->children[i]) {
372 ERR("Child resource was already bound to parent resource.");
373 return IOTCON_ERROR_ALREADY;
377 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
378 if (NULL == parent->children[i]) {
379 ic_dbus_call_bind_resource_sync(icl_dbus_get_object(), parent->handle,
380 child->handle, &ret, NULL, &error);
382 ERR("ic_dbus_call_bind_resource_sync() Fail(%s)", error->message);
383 error_code = icl_dbus_convert_dbus_error(error->code);
388 if (IOTCON_ERROR_NONE != ret) {
389 ERR("iotcon-daemon Fail(%d)", ret);
390 return icl_dbus_convert_daemon_error(ret);
393 parent->children[i] = child;
395 return IOTCON_ERROR_NONE;
399 ERR("There is no slot to bind a child resource");
400 return IOTCON_ERROR_OUT_OF_MEMORY;
404 API int iotcon_resource_unbind_child_resource(iotcon_resource_h parent,
405 iotcon_resource_h child)
407 GError *error = NULL;
408 int i, ret, error_code;
410 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
411 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
412 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
414 if (0 == parent->sub_id) {
415 ERR("Invalid Resource handle(parent)");
416 return IOTCON_ERROR_INVALID_PARAMETER;
418 if (0 == child->sub_id) {
419 ERR("Invalid Resource handle(child)");
420 return IOTCON_ERROR_INVALID_PARAMETER;
423 ic_dbus_call_unbind_resource_sync(icl_dbus_get_object(), parent->handle,
424 child->handle, &ret, NULL, &error);
426 ERR("ic_dbus_call_unbind_resource_sync() Fail(%s)", error->message);
427 error_code = icl_dbus_convert_dbus_error(error->code);
432 if (IOTCON_ERROR_NONE != ret) {
433 ERR("iotcon-daemon Fail(%d)", ret);
434 return icl_dbus_convert_daemon_error(ret);
437 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
438 if (child == parent->children[i])
439 parent->children[i] = NULL;
442 return IOTCON_ERROR_NONE;
446 API int iotcon_resource_get_number_of_children(iotcon_resource_h resource, int *number)
450 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
451 RETV_IF(NULL == number, IOTCON_ERROR_INVALID_PARAMETER);
454 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
455 if (resource->children[i])
459 return IOTCON_ERROR_NONE;
463 API int iotcon_resource_get_nth_child(iotcon_resource_h parent, int index,
464 iotcon_resource_h *child)
466 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
467 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
468 if ((index < 0) || (ICL_CONTAINED_RESOURCES_MAX <= index)) {
469 ERR("Invalid index(%d)", index);
470 return IOTCON_ERROR_INVALID_PARAMETER;
473 *child = parent->children[index];
475 return IOTCON_ERROR_NONE;
479 /* The content of the resource should not be freed by user. */
480 API int iotcon_resource_get_uri_path(iotcon_resource_h resource, char **uri_path)
482 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
483 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
485 *uri_path = resource->uri_path;
487 return IOTCON_ERROR_NONE;
491 /* The content of the resource should not be freed by user. */
492 API int iotcon_resource_get_types(iotcon_resource_h resource,
493 iotcon_resource_types_h *types)
495 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
496 RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
498 *types = resource->types;
500 return IOTCON_ERROR_NONE;
504 API int iotcon_resource_get_interfaces(iotcon_resource_h resource, int *ifaces)
506 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
507 RETV_IF(NULL == ifaces, IOTCON_ERROR_INVALID_PARAMETER);
509 *ifaces = resource->ifaces;
511 return IOTCON_ERROR_NONE;
515 API int iotcon_resource_is_observable(iotcon_resource_h resource, bool *observable)
517 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
518 RETV_IF(NULL == observable, IOTCON_ERROR_INVALID_PARAMETER);
520 *observable = resource->is_observable;
522 return IOTCON_ERROR_NONE;
526 API int iotcon_notimsg_create(iotcon_representation_h repr, int iface,
527 iotcon_notimsg_h *notimsg_handle)
529 iotcon_notimsg_h msg;
531 RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
533 msg = calloc(1, sizeof(struct icl_notify_msg));
535 ERR("calloc() Fail(%d)", errno);
536 return IOTCON_ERROR_OUT_OF_MEMORY;
540 icl_representation_inc_ref_count(msg->repr);
542 msg->error_code = 200;
544 *notimsg_handle = msg;
546 return IOTCON_ERROR_NONE;
550 API void iotcon_notimsg_destroy(iotcon_notimsg_h msg)
554 iotcon_representation_destroy(msg->repr);
559 API int iotcon_notify_list_of_observers(iotcon_resource_h resource, iotcon_notimsg_h msg,
560 iotcon_observers_h observers)
563 GError *error = NULL;
567 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
568 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
569 RETV_IF(NULL == observers, IOTCON_ERROR_INVALID_PARAMETER);
571 if (0 == resource->sub_id) {
572 ERR("Invalid Resource handle");
573 return IOTCON_ERROR_INVALID_PARAMETER;
576 noti_msg = icl_dbus_notimsg_to_gvariant(msg);
577 if (NULL == noti_msg) {
578 ERR("icl_dbus_notimsg_to_gvariant() Fail");
579 return IOTCON_ERROR_REPRESENTATION;
581 obs = icl_dbus_observers_to_gvariant(observers);
583 ic_dbus_call_notify_list_of_observers_sync(icl_dbus_get_object(), resource->handle,
584 noti_msg, obs, &ret, NULL, &error);
586 ERR("ic_dbus_call_notify_list_of_observers_sync() Fail(%s)", error->message);
587 error_code = icl_dbus_convert_dbus_error(error->code);
589 g_variant_unref(obs);
590 g_variant_unref(noti_msg);
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;
603 API int iotcon_resource_notify_all(iotcon_resource_h resource)
606 GError *error = NULL;
608 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
609 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
610 if (0 == resource->sub_id) {
611 ERR("Invalid Resource handle");
612 return IOTCON_ERROR_INVALID_PARAMETER;
615 ic_dbus_call_notify_all_sync(icl_dbus_get_object(), resource->handle, &ret, NULL,
618 ERR("ic_dbus_call_notify_all_sync() Fail(%s)", error->message);
619 error_code = icl_dbus_convert_dbus_error(error->code);
624 if (IOTCON_ERROR_NONE != ret) {
625 ERR("iotcon-daemon Fail(%d)", ret);
626 return icl_dbus_convert_daemon_error(ret);
629 return IOTCON_ERROR_NONE;