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_add(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);
96 if (request.header_options)
97 iotcon_options_destroy(request.header_options);
101 while (g_variant_iter_loop(query, "(&s&s)", &key, &value))
102 iotcon_query_add(request.query, key, value);
104 g_variant_iter_free(query);
106 if (g_variant_iter_loop(repr_iter, "v", &repr_gvar)) {
107 request.repr = icl_representation_from_gvariant(repr_gvar);
108 if (NULL == request.repr) {
109 ERR("icl_representation_from_gvariant() Fail");
111 iotcon_query_destroy(request.query);
112 if (request.header_options)
113 iotcon_options_destroy(request.header_options);
117 g_variant_iter_free(repr_iter);
119 /* for iotcon_resource_notify */
120 if (IOTCON_REQUEST_OBSERVE & request.types) {
121 int observer_id = request.observation_info.observer_id;
122 if (IOTCON_OBSERVE_REGISTER == request.observation_info.action) {
123 if (NULL == resource->observers)
124 iotcon_observers_create(&resource->observers);
125 iotcon_observers_add(resource->observers, observer_id);
126 } else if (IOTCON_OBSERVE_DEREGISTER == request.observation_info.action) {
127 iotcon_observers_remove(resource->observers, observer_id);
132 cb(resource, &request, resource->user_data);
134 /* To avoid unnecessary ERR log (representation could be NULL) */
136 iotcon_representation_destroy(request.repr);
138 iotcon_query_destroy(request.query);
139 if (request.header_options)
140 iotcon_options_destroy(request.header_options);
144 static void _icl_resource_conn_cleanup(iotcon_resource_h resource)
146 resource->sub_id = 0;
148 if (resource->handle) {
149 resource->handle = 0;
153 iotcon_resource_types_destroy(resource->types);
154 if (resource->observers)
155 iotcon_observers_destroy(resource->observers);
156 free(resource->uri_path);
161 /* The length of uri_path should be less than or equal to 36. */
162 API int iotcon_resource_create(const char *uri_path,
163 iotcon_resource_types_h res_types,
166 iotcon_request_handler_cb cb,
168 iotcon_resource_h *resource_handle)
171 GError *error = NULL;
173 iotcon_resource_h resource;
174 int signal_number, ret;
175 char sig_name[IC_DBUS_SIGNAL_LENGTH];
177 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
178 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
179 RETVM_IF(ICL_URI_PATH_LENGTH_MAX < strlen(uri_path),
180 IOTCON_ERROR_INVALID_PARAMETER, "Invalid uri_path(%s)", uri_path);
181 RETV_IF(NULL == res_types, IOTCON_ERROR_INVALID_PARAMETER);
182 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
184 resource = calloc(1, sizeof(struct icl_resource));
185 if (NULL == resource) {
186 ERR("calloc() Fail(%d)", errno);
187 return IOTCON_ERROR_OUT_OF_MEMORY;
190 types = icl_dbus_resource_types_to_array(res_types);
192 ERR("icl_dbus_resource_types_to_array() Fail");
194 return IOTCON_ERROR_INVALID_PARAMETER;
197 signal_number = icl_dbus_generate_signal_number();
199 ic_dbus_call_register_resource_sync(icl_dbus_get_object(), uri_path, types, ifaces,
200 properties, signal_number, &(resource->handle), NULL, &error);
202 ERR("ic_dbus_call_register_resource_sync() Fail(%s)", error->message);
203 ret = icl_dbus_convert_dbus_error(error->code);
211 if (0 == resource->handle) {
212 ERR("iotcon-daemon Fail");
214 return IOTCON_ERROR_IOTIVITY;
218 resource->user_data = user_data;
220 resource->types = icl_resource_types_ref(res_types);
221 resource->uri_path = ic_utils_strdup(uri_path);
222 resource->ifaces = ifaces;
223 resource->is_observable = properties & IOTCON_OBSERVABLE;
225 snprintf(sig_name, sizeof(sig_name), "%s_%u", IC_DBUS_SIGNAL_REQUEST_HANDLER,
228 sub_id = icl_dbus_subscribe_signal(sig_name, resource, _icl_resource_conn_cleanup,
229 _icl_request_handler);
231 ERR("icl_dbus_subscribe_signal() Fail");
232 iotcon_resource_types_destroy(res_types);
233 free(resource->uri_path);
235 return IOTCON_ERROR_DBUS;
238 resource->sub_id = sub_id;
240 *resource_handle = resource;
242 return IOTCON_ERROR_NONE;
246 API int iotcon_resource_destroy(iotcon_resource_h resource)
250 GError *error = NULL;
252 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
253 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
255 if (0 == resource->sub_id) {
256 WARN("Invalid Resource handle");
257 iotcon_resource_types_destroy(resource->types);
258 if (resource->observers)
259 iotcon_observers_destroy(resource->observers);
260 free(resource->uri_path);
262 return IOTCON_ERROR_NONE;
265 ic_dbus_call_unregister_resource_sync(icl_dbus_get_object(), resource->handle, NULL,
268 ERR("ic_dbus_call_unregister_resource_sync() Fail(%s)", error->message);
269 ret = icl_dbus_convert_dbus_error(error->code);
274 resource->handle = 0;
276 icl_dbus_unsubscribe_signal(resource->sub_id);
278 return IOTCON_ERROR_NONE;
282 API int iotcon_resource_bind_interface(iotcon_resource_h resource,
283 iotcon_interface_e iface)
287 GError *error = NULL;
289 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
290 RETV_IF(NULL == resource, 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_interface_sync(icl_dbus_get_object(), resource->handle,
297 iface, &ret, NULL, &error);
299 ERR("ic_dbus_call_bind_interface_sync() Fail(%s)", error->message);
300 ret = icl_dbus_convert_dbus_error(error->code);
305 if (IOTCON_ERROR_NONE != ret) {
306 ERR("iotcon-daemon Fail(%d)", ret);
307 return icl_dbus_convert_daemon_error(ret);
314 API int iotcon_resource_bind_type(iotcon_resource_h resource, const char *resource_type)
318 GError *error = NULL;
320 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
321 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
322 RETV_IF(NULL == resource_type, IOTCON_ERROR_INVALID_PARAMETER);
323 if (ICL_RESOURCE_TYPE_LENGTH_MAX < strlen(resource_type)) {
324 ERR("Invalid resource_type(%s)", resource_type);
325 return IOTCON_ERROR_INVALID_PARAMETER;
328 if (0 == resource->sub_id) {
329 ERR("Invalid Resource handle");
330 return IOTCON_ERROR_INVALID_PARAMETER;
333 ic_dbus_call_bind_type_sync(icl_dbus_get_object(), resource->handle, resource_type,
336 ERR("ic_dbus_call_bind_type_sync() Fail(%s)", error->message);
337 ret = icl_dbus_convert_dbus_error(error->code);
342 if (IOTCON_ERROR_NONE != ret) {
343 ERR("iotcon-daemon Fail(%d)", ret);
344 return icl_dbus_convert_daemon_error(ret);
351 API int iotcon_resource_set_request_handler(iotcon_resource_h resource,
352 iotcon_request_handler_cb cb)
354 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
355 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
357 WARN("Request handler is changed");
360 return IOTCON_ERROR_NONE;
364 API int iotcon_resource_bind_child_resource(iotcon_resource_h parent,
365 iotcon_resource_h child)
367 GError *error = NULL;
370 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
371 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
372 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
373 RETV_IF(parent == child, IOTCON_ERROR_INVALID_PARAMETER);
375 if (0 == parent->sub_id) {
376 ERR("Invalid Resource handle(parent)");
377 return IOTCON_ERROR_INVALID_PARAMETER;
379 if (0 == child->sub_id) {
380 ERR("Invalid Resource handle(child)");
381 return IOTCON_ERROR_INVALID_PARAMETER;
384 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
385 if (child == parent->children[i]) {
386 ERR("Child resource was already bound to parent resource.");
387 return IOTCON_ERROR_ALREADY;
391 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
392 if (NULL == parent->children[i]) {
393 ic_dbus_call_bind_resource_sync(icl_dbus_get_object(), parent->handle,
394 child->handle, &ret, NULL, &error);
396 ERR("ic_dbus_call_bind_resource_sync() Fail(%s)", error->message);
397 ret = icl_dbus_convert_dbus_error(error->code);
402 if (IOTCON_ERROR_NONE != ret) {
403 ERR("iotcon-daemon Fail(%d)", ret);
404 return icl_dbus_convert_daemon_error(ret);
407 parent->children[i] = child;
409 return IOTCON_ERROR_NONE;
413 ERR("There is no slot to bind a child resource");
414 return IOTCON_ERROR_OUT_OF_MEMORY;
418 API int iotcon_resource_unbind_child_resource(iotcon_resource_h parent,
419 iotcon_resource_h child)
421 GError *error = NULL;
424 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
425 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
426 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
428 if (0 == parent->sub_id) {
429 ERR("Invalid Resource handle(parent)");
430 return IOTCON_ERROR_INVALID_PARAMETER;
432 if (0 == child->sub_id) {
433 ERR("Invalid Resource handle(child)");
434 return IOTCON_ERROR_INVALID_PARAMETER;
437 ic_dbus_call_unbind_resource_sync(icl_dbus_get_object(), parent->handle,
438 child->handle, &ret, NULL, &error);
440 ERR("ic_dbus_call_unbind_resource_sync() Fail(%s)", error->message);
441 ret = icl_dbus_convert_dbus_error(error->code);
446 if (IOTCON_ERROR_NONE != ret) {
447 ERR("iotcon-daemon Fail(%d)", ret);
448 return icl_dbus_convert_daemon_error(ret);
451 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
452 if (child == parent->children[i])
453 parent->children[i] = NULL;
456 return IOTCON_ERROR_NONE;
460 API int iotcon_resource_get_number_of_children(iotcon_resource_h resource, int *number)
464 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
465 RETV_IF(NULL == number, IOTCON_ERROR_INVALID_PARAMETER);
468 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
469 if (resource->children[i])
473 return IOTCON_ERROR_NONE;
477 API int iotcon_resource_get_nth_child(iotcon_resource_h parent, int index,
478 iotcon_resource_h *child)
480 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
481 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
482 if ((index < 0) || (ICL_CONTAINED_RESOURCES_MAX <= index)) {
483 ERR("Invalid index(%d)", index);
484 return IOTCON_ERROR_INVALID_PARAMETER;
487 *child = parent->children[index];
489 return IOTCON_ERROR_NONE;
493 /* The content of the resource should not be freed by user. */
494 API int iotcon_resource_get_uri_path(iotcon_resource_h resource, char **uri_path)
496 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
497 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
499 *uri_path = resource->uri_path;
501 return IOTCON_ERROR_NONE;
505 /* The content of the resource should not be freed by user. */
506 API int iotcon_resource_get_types(iotcon_resource_h resource,
507 iotcon_resource_types_h *types)
509 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
510 RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
512 *types = resource->types;
514 return IOTCON_ERROR_NONE;
518 API int iotcon_resource_get_interfaces(iotcon_resource_h resource, int *ifaces)
520 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
521 RETV_IF(NULL == ifaces, IOTCON_ERROR_INVALID_PARAMETER);
523 *ifaces = resource->ifaces;
525 return IOTCON_ERROR_NONE;
529 API int iotcon_resource_is_observable(iotcon_resource_h resource, bool *observable)
531 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
532 RETV_IF(NULL == observable, IOTCON_ERROR_INVALID_PARAMETER);
534 *observable = resource->is_observable;
536 return IOTCON_ERROR_NONE;
540 API int iotcon_notimsg_create(iotcon_representation_h repr, iotcon_interface_e iface,
541 iotcon_notimsg_h *notimsg_handle)
543 iotcon_notimsg_h msg;
545 RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
546 RETV_IF(NULL == notimsg_handle, IOTCON_ERROR_INVALID_PARAMETER);
548 msg = calloc(1, sizeof(struct icl_notify_msg));
550 ERR("calloc() Fail(%d)", errno);
551 return IOTCON_ERROR_OUT_OF_MEMORY;
555 icl_representation_inc_ref_count(msg->repr);
557 msg->error_code = 200;
559 *notimsg_handle = msg;
561 return IOTCON_ERROR_NONE;
565 API void iotcon_notimsg_destroy(iotcon_notimsg_h msg)
569 iotcon_representation_destroy(msg->repr);
573 API int iotcon_resource_notify(iotcon_resource_h resource, iotcon_notimsg_h msg,
574 iotcon_observers_h observers)
577 GError *error = NULL;
581 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
582 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
584 if (0 == resource->sub_id) {
585 ERR("Invalid Resource handle");
586 return IOTCON_ERROR_INVALID_PARAMETER;
589 /* TODO: Get default message if msg parameter is NULL */
590 noti_msg = icl_dbus_notimsg_to_gvariant(msg);
591 if (NULL == noti_msg) {
592 ERR("icl_dbus_notimsg_to_gvariant() Fail");
593 return IOTCON_ERROR_REPRESENTATION;
597 obs = icl_dbus_observers_to_gvariant(observers);
599 obs = icl_dbus_observers_to_gvariant(resource->observers);
601 ic_dbus_call_notify_sync(icl_dbus_get_object(), resource->handle, noti_msg, obs, &ret,
604 ERR("ic_dbus_call_notify_sync() Fail(%s)", error->message);
605 ret = icl_dbus_convert_dbus_error(error->code);
607 g_variant_unref(obs);
608 g_variant_unref(noti_msg);
612 if (IOTCON_ERROR_NONE != ret) {
613 ERR("iotcon-daemon Fail(%d)", ret);
614 return icl_dbus_convert_daemon_error(ret);
617 return IOTCON_ERROR_NONE;