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"
35 static void _icl_request_handler(GDBusConnection *connection,
36 const gchar *sender_name,
37 const gchar *object_path,
38 const gchar *interface_name,
39 const gchar *signal_name,
50 GVariantIter *options;
51 GVariantIter *repr_iter;
52 unsigned short option_id;
53 struct icl_resource_request request = {0};
54 iotcon_resource_h resource = user_data;
55 iotcon_request_handler_cb cb = resource->cb;
57 g_variant_get(parameters, "(ia(qs)a(ss)iiavxx)",
61 &request.observation_info.action,
62 &request.observation_info.observer_id,
64 &request.oic_request_h,
65 &request.oic_resource_h);
67 if (g_variant_iter_n_children(options)) {
68 ret = iotcon_options_create(&request.header_options);
69 if (IOTCON_ERROR_NONE != ret) {
70 ERR("iotcon_options_create() Fail(%d)", ret);
71 g_variant_iter_free(options);
72 g_variant_iter_free(query);
73 g_variant_iter_free(repr_iter);
77 while (g_variant_iter_loop(options, "(q&s)", &option_id, &option_data))
78 iotcon_options_add(request.header_options, option_id, option_data);
80 g_variant_iter_free(options);
82 if (g_variant_iter_n_children(query)) {
83 ret = iotcon_query_create(&request.query);
84 if (IOTCON_ERROR_NONE != ret) {
85 ERR("iotcon_query_create() Fail(%d)", ret);
86 g_variant_iter_free(query);
87 g_variant_iter_free(repr_iter);
88 if (request.header_options)
89 iotcon_options_destroy(request.header_options);
93 while (g_variant_iter_loop(query, "(&s&s)", &key, &value))
94 iotcon_query_add(request.query, key, value);
96 g_variant_iter_free(query);
98 if (g_variant_iter_loop(repr_iter, "v", &repr_gvar)) {
99 request.repr = icl_representation_from_gvariant(repr_gvar);
100 if (NULL == request.repr) {
101 ERR("icl_representation_from_gvariant() Fail");
103 iotcon_query_destroy(request.query);
104 if (request.header_options)
105 iotcon_options_destroy(request.header_options);
109 g_variant_iter_free(repr_iter);
111 /* for iotcon_resource_notify */
112 if (IOTCON_REQUEST_OBSERVE & request.types) {
113 int observer_id = request.observation_info.observer_id;
114 if (IOTCON_OBSERVE_REGISTER == request.observation_info.action) {
115 if (NULL == resource->observers)
116 iotcon_observers_create(&resource->observers);
117 iotcon_observers_add(resource->observers, observer_id);
118 } else if (IOTCON_OBSERVE_DEREGISTER == request.observation_info.action) {
119 iotcon_observers_remove(resource->observers, observer_id);
124 cb(resource, &request, resource->user_data);
126 /* To avoid unnecessary ERR log (representation could be NULL) */
128 iotcon_representation_destroy(request.repr);
130 iotcon_query_destroy(request.query);
131 if (request.header_options)
132 iotcon_options_destroy(request.header_options);
136 static void _icl_resource_conn_cleanup(iotcon_resource_h resource)
138 resource->sub_id = 0;
140 if (resource->handle) {
141 resource->handle = 0;
145 iotcon_resource_types_destroy(resource->types);
146 if (resource->observers)
147 iotcon_observers_destroy(resource->observers);
148 free(resource->uri_path);
153 /* The length of uri_path should be less than or equal to 36. */
154 API int iotcon_resource_create(const char *uri_path,
155 iotcon_resource_types_h res_types,
158 iotcon_request_handler_cb cb,
160 iotcon_resource_h *resource_handle)
163 GError *error = NULL;
165 iotcon_resource_h resource;
166 int signal_number, ret;
167 char sig_name[IC_DBUS_SIGNAL_LENGTH];
169 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
170 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
171 RETVM_IF(ICL_URI_PATH_LENGTH_MAX < strlen(uri_path),
172 IOTCON_ERROR_INVALID_PARAMETER, "Invalid uri_path(%s)", uri_path);
173 RETV_IF(NULL == res_types, IOTCON_ERROR_INVALID_PARAMETER);
174 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
176 resource = calloc(1, sizeof(struct icl_resource));
177 if (NULL == resource) {
178 ERR("calloc() Fail(%d)", errno);
179 return IOTCON_ERROR_OUT_OF_MEMORY;
182 types = icl_dbus_resource_types_to_array(res_types);
184 ERR("icl_dbus_resource_types_to_array() Fail");
186 return IOTCON_ERROR_OUT_OF_MEMORY;
189 signal_number = icl_dbus_generate_signal_number();
191 ic_dbus_call_register_resource_sync(icl_dbus_get_object(), uri_path, types, ifaces,
192 properties, signal_number, &(resource->handle), NULL, &error);
194 ERR("ic_dbus_call_register_resource_sync() Fail(%s)", error->message);
195 ret = icl_dbus_convert_dbus_error(error->code);
203 if (0 == resource->handle) {
204 ERR("iotcon-daemon Fail");
206 return IOTCON_ERROR_IOTIVITY;
210 resource->user_data = user_data;
212 resource->types = icl_resource_types_ref(res_types);
213 resource->uri_path = ic_utils_strdup(uri_path);
214 resource->ifaces = ifaces;
215 resource->is_observable = properties & IOTCON_OBSERVABLE;
217 snprintf(sig_name, sizeof(sig_name), "%s_%u", IC_DBUS_SIGNAL_REQUEST_HANDLER,
220 sub_id = icl_dbus_subscribe_signal(sig_name, resource, _icl_resource_conn_cleanup,
221 _icl_request_handler);
223 ERR("icl_dbus_subscribe_signal() Fail");
224 iotcon_resource_types_destroy(res_types);
225 free(resource->uri_path);
227 return IOTCON_ERROR_DBUS;
230 resource->sub_id = sub_id;
232 *resource_handle = resource;
234 return IOTCON_ERROR_NONE;
238 API int iotcon_resource_destroy(iotcon_resource_h resource)
242 GError *error = NULL;
244 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
245 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
247 if (0 == resource->sub_id) {
248 WARN("Invalid Resource handle");
249 iotcon_resource_types_destroy(resource->types);
250 if (resource->observers)
251 iotcon_observers_destroy(resource->observers);
252 free(resource->uri_path);
254 return IOTCON_ERROR_NONE;
257 ic_dbus_call_unregister_resource_sync(icl_dbus_get_object(), resource->handle, NULL,
260 ERR("ic_dbus_call_unregister_resource_sync() Fail(%s)", error->message);
261 ret = icl_dbus_convert_dbus_error(error->code);
266 resource->handle = 0;
268 icl_dbus_unsubscribe_signal(resource->sub_id);
270 return IOTCON_ERROR_NONE;
274 API int iotcon_resource_bind_interface(iotcon_resource_h resource,
275 iotcon_interface_e iface)
279 GError *error = NULL;
281 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
282 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
283 if (0 == resource->sub_id) {
284 ERR("Invalid Resource handle");
285 return IOTCON_ERROR_INVALID_PARAMETER;
288 ic_dbus_call_bind_interface_sync(icl_dbus_get_object(), resource->handle,
289 iface, &ret, NULL, &error);
291 ERR("ic_dbus_call_bind_interface_sync() Fail(%s)", error->message);
292 ret = icl_dbus_convert_dbus_error(error->code);
297 if (IOTCON_ERROR_NONE != ret) {
298 ERR("iotcon-daemon Fail(%d)", ret);
299 return icl_dbus_convert_daemon_error(ret);
306 API int iotcon_resource_bind_type(iotcon_resource_h resource, const char *resource_type)
310 GError *error = NULL;
312 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
313 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
314 RETV_IF(NULL == resource_type, IOTCON_ERROR_INVALID_PARAMETER);
315 if (ICL_RESOURCE_TYPE_LENGTH_MAX < strlen(resource_type)) {
316 ERR("Invalid resource_type(%s)", resource_type);
317 return IOTCON_ERROR_INVALID_PARAMETER;
320 if (0 == resource->sub_id) {
321 ERR("Invalid Resource handle");
322 return IOTCON_ERROR_INVALID_PARAMETER;
325 ic_dbus_call_bind_type_sync(icl_dbus_get_object(), resource->handle, resource_type,
328 ERR("ic_dbus_call_bind_type_sync() Fail(%s)", error->message);
329 ret = icl_dbus_convert_dbus_error(error->code);
334 if (IOTCON_ERROR_NONE != ret) {
335 ERR("iotcon-daemon Fail(%d)", ret);
336 return icl_dbus_convert_daemon_error(ret);
343 API int iotcon_resource_set_request_handler(iotcon_resource_h resource,
344 iotcon_request_handler_cb cb)
346 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
347 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
349 WARN("Request handler is changed");
352 return IOTCON_ERROR_NONE;
356 API int iotcon_resource_bind_child_resource(iotcon_resource_h parent,
357 iotcon_resource_h child)
359 GError *error = NULL;
362 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
363 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
364 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
365 RETV_IF(parent == child, IOTCON_ERROR_INVALID_PARAMETER);
367 if (0 == parent->sub_id) {
368 ERR("Invalid Resource handle(parent)");
369 return IOTCON_ERROR_INVALID_PARAMETER;
371 if (0 == child->sub_id) {
372 ERR("Invalid Resource handle(child)");
373 return IOTCON_ERROR_INVALID_PARAMETER;
376 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
377 if (child == parent->children[i]) {
378 ERR("Child resource was already bound to parent resource.");
379 return IOTCON_ERROR_ALREADY;
383 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
384 if (NULL == parent->children[i]) {
385 ic_dbus_call_bind_resource_sync(icl_dbus_get_object(), parent->handle,
386 child->handle, &ret, NULL, &error);
388 ERR("ic_dbus_call_bind_resource_sync() Fail(%s)", error->message);
389 ret = icl_dbus_convert_dbus_error(error->code);
394 if (IOTCON_ERROR_NONE != ret) {
395 ERR("iotcon-daemon Fail(%d)", ret);
396 return icl_dbus_convert_daemon_error(ret);
399 parent->children[i] = child;
401 return IOTCON_ERROR_NONE;
405 ERR("There is no slot to bind a child resource");
406 return IOTCON_ERROR_OUT_OF_MEMORY;
410 API int iotcon_resource_unbind_child_resource(iotcon_resource_h parent,
411 iotcon_resource_h child)
413 GError *error = NULL;
416 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
417 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
418 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
420 if (0 == parent->sub_id) {
421 ERR("Invalid Resource handle(parent)");
422 return IOTCON_ERROR_INVALID_PARAMETER;
424 if (0 == child->sub_id) {
425 ERR("Invalid Resource handle(child)");
426 return IOTCON_ERROR_INVALID_PARAMETER;
429 ic_dbus_call_unbind_resource_sync(icl_dbus_get_object(), parent->handle,
430 child->handle, &ret, NULL, &error);
432 ERR("ic_dbus_call_unbind_resource_sync() Fail(%s)", error->message);
433 ret = icl_dbus_convert_dbus_error(error->code);
438 if (IOTCON_ERROR_NONE != ret) {
439 ERR("iotcon-daemon Fail(%d)", ret);
440 return icl_dbus_convert_daemon_error(ret);
443 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
444 if (child == parent->children[i])
445 parent->children[i] = NULL;
448 return IOTCON_ERROR_NONE;
452 API int iotcon_resource_get_number_of_children(iotcon_resource_h resource, int *number)
456 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
457 RETV_IF(NULL == number, IOTCON_ERROR_INVALID_PARAMETER);
460 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
461 if (resource->children[i])
465 return IOTCON_ERROR_NONE;
469 API int iotcon_resource_get_nth_child(iotcon_resource_h parent, int index,
470 iotcon_resource_h *child)
472 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
473 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
474 if ((index < 0) || (ICL_CONTAINED_RESOURCES_MAX <= index)) {
475 ERR("Invalid index(%d)", index);
476 return IOTCON_ERROR_INVALID_PARAMETER;
479 *child = parent->children[index];
481 return IOTCON_ERROR_NONE;
485 /* The content of the resource should not be freed by user. */
486 API int iotcon_resource_get_uri_path(iotcon_resource_h resource, char **uri_path)
488 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
489 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
491 *uri_path = resource->uri_path;
493 return IOTCON_ERROR_NONE;
497 /* The content of the resource should not be freed by user. */
498 API int iotcon_resource_get_types(iotcon_resource_h resource,
499 iotcon_resource_types_h *types)
501 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
502 RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
504 *types = resource->types;
506 return IOTCON_ERROR_NONE;
510 API int iotcon_resource_get_interfaces(iotcon_resource_h resource, int *ifaces)
512 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
513 RETV_IF(NULL == ifaces, IOTCON_ERROR_INVALID_PARAMETER);
515 *ifaces = resource->ifaces;
517 return IOTCON_ERROR_NONE;
521 API int iotcon_resource_is_observable(iotcon_resource_h resource, bool *observable)
523 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
524 RETV_IF(NULL == observable, IOTCON_ERROR_INVALID_PARAMETER);
526 *observable = resource->is_observable;
528 return IOTCON_ERROR_NONE;
532 API int iotcon_notimsg_create(iotcon_representation_h repr, iotcon_interface_e iface,
533 iotcon_notimsg_h *notimsg_handle)
535 iotcon_notimsg_h msg;
537 RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
538 RETV_IF(NULL == notimsg_handle, IOTCON_ERROR_INVALID_PARAMETER);
540 msg = calloc(1, sizeof(struct icl_notify_msg));
542 ERR("calloc() Fail(%d)", errno);
543 return IOTCON_ERROR_OUT_OF_MEMORY;
547 icl_representation_inc_ref_count(msg->repr);
549 msg->error_code = 200;
551 *notimsg_handle = msg;
553 return IOTCON_ERROR_NONE;
557 API void iotcon_notimsg_destroy(iotcon_notimsg_h msg)
561 iotcon_representation_destroy(msg->repr);
565 API int iotcon_resource_notify(iotcon_resource_h resource, iotcon_notimsg_h msg,
566 iotcon_observers_h observers)
569 GError *error = NULL;
573 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
574 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
576 if (0 == resource->sub_id) {
577 ERR("Invalid Resource handle");
578 return IOTCON_ERROR_INVALID_PARAMETER;
581 /* TODO: Get default message if msg parameter is NULL */
582 noti_msg = icl_dbus_notimsg_to_gvariant(msg);
583 if (NULL == noti_msg) {
584 ERR("icl_dbus_notimsg_to_gvariant() Fail");
585 return IOTCON_ERROR_REPRESENTATION;
589 obs = icl_dbus_observers_to_gvariant(observers);
591 obs = icl_dbus_observers_to_gvariant(resource->observers);
593 ic_dbus_call_notify_sync(icl_dbus_get_object(), resource->handle, noti_msg, obs, &ret,
596 ERR("ic_dbus_call_notify_sync() Fail(%s)", error->message);
597 ret = icl_dbus_convert_dbus_error(error->code);
599 g_variant_unref(obs);
600 g_variant_unref(noti_msg);
604 if (IOTCON_ERROR_NONE != ret) {
605 ERR("iotcon-daemon Fail(%d)", ret);
606 return icl_dbus_convert_daemon_error(ret);
609 return IOTCON_ERROR_NONE;