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"
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,
44 GVariantIter *options;
45 unsigned short option_id;
48 GVariantIter *repr_iter;
51 struct icl_resource_request request = {0};
52 iotcon_resource_h resource = user_data;
53 iotcon_request_handler_cb cb = resource->cb;
56 g_variant_get(parameters, "(ia(qs)a(ss)iiavxx)",
60 &request.observation_info.action,
61 &request.observation_info.observer_id,
63 &request.oic_request_h,
64 &request.oic_resource_h);
66 if (g_variant_iter_n_children(options)) {
67 request.header_options = iotcon_options_new();
68 while (g_variant_iter_loop(options, "(q&s)", &option_id, &option_data))
69 iotcon_options_insert(request.header_options, option_id, option_data);
71 g_variant_iter_free(options);
73 if (g_variant_iter_n_children(query)) {
74 request.query = iotcon_query_new();
75 while (g_variant_iter_loop(query, "(&s&s)", &key, &value))
76 iotcon_query_insert(request.query, key, value);
78 g_variant_iter_free(query);
80 if (g_variant_iter_loop(repr_iter, "v", &repr_gvar)) {
81 request.repr = icl_repr_from_gvariant(repr_gvar);
82 if (NULL == request.repr) {
83 ERR("icl_repr_create_repr() Fail");
85 iotcon_query_free(request.query);
86 if (request.header_options)
87 iotcon_options_free(request.header_options);
92 /* TODO remove request.uri */
93 request.uri_path = "temp_uri_path";
96 cb(resource, &request, resource->user_data);
98 /* To avoid unnecessary ERR log (repr could be NULL) */
100 iotcon_repr_free(request.repr);
102 iotcon_query_free(request.query);
103 if (request.header_options)
104 iotcon_options_free(request.header_options);
108 static void _icl_resource_conn_cleanup(iotcon_resource_h resource)
110 resource->sub_id = 0;
112 if (resource->handle) {
113 resource->handle = 0;
117 iotcon_resource_types_free(resource->types);
118 free(resource->uri_path);
123 /* The length of uri_path should be less than or equal to 36. */
124 API iotcon_resource_h iotcon_register_resource(const char *uri_path,
125 iotcon_resource_types_h res_types,
128 iotcon_request_handler_cb cb,
133 GError *error = NULL;
135 char sig_name[IC_DBUS_SIGNAL_LENGTH];
136 iotcon_resource_h resource;
138 RETV_IF(NULL == icl_dbus_get_object(), NULL);
139 RETV_IF(NULL == uri_path, NULL);
140 RETVM_IF(IOTCON_URI_PATH_LENGTH_MAX < strlen(uri_path), NULL, "Invalid uri_path(%s)",
142 RETV_IF(NULL == res_types, NULL);
143 RETV_IF(NULL == cb, NULL);
145 resource = calloc(1, sizeof(struct icl_resource));
146 if (NULL == resource) {
147 ERR("calloc() Fail(%d)", errno);
151 types = icl_dbus_resource_types_to_array(res_types);
153 ERR("icl_dbus_resource_types_to_array() Fail");
158 signal_number = icl_dbus_generate_signal_number();
160 ic_dbus_call_register_resource_sync(icl_dbus_get_object(), uri_path, types, ifaces,
161 properties, signal_number, &(resource->handle), NULL, &error);
163 ERR("ic_dbus_call_register_resource_sync() Fail(%s)", error->message);
171 if (0 == resource->handle) {
172 ERR("iotcon-daemon Fail");
178 resource->user_data = user_data;
180 resource->types = icl_resource_types_ref(res_types);
181 resource->uri_path = ic_utils_strdup(uri_path);
182 resource->ifaces = ifaces;
183 resource->is_observable = properties & IOTCON_OBSERVABLE;
185 snprintf(sig_name, sizeof(sig_name), "%s_%u", IC_DBUS_SIGNAL_REQUEST_HANDLER,
188 sub_id = icl_dbus_subscribe_signal(sig_name, resource, _icl_resource_conn_cleanup,
189 _icl_request_handler);
191 ERR("icl_dbus_subscribe_signal() Fail");
196 resource->sub_id = sub_id;
202 API int iotcon_unregister_resource(iotcon_resource_h resource)
206 GError *error = NULL;
208 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
209 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
211 if (0 == resource->sub_id) {
212 WARN("Invalid Resource handle");
213 iotcon_resource_types_free(resource->types);
214 free(resource->uri_path);
216 return IOTCON_ERROR_NONE;
219 ic_dbus_call_unregister_resource_sync(icl_dbus_get_object(), resource->handle,
222 ERR("ic_dbus_call_unregister_resource_sync() Fail(%s)", error->message);
224 return IOTCON_ERROR_DBUS;
227 if (IOTCON_ERROR_NONE != ret) {
228 ERR("iotcon-daemon Fail(%d)", ret);
229 return icl_dbus_convert_daemon_error(ret);
231 resource->handle = 0;
233 icl_dbus_unsubscribe_signal(resource->sub_id);
235 return IOTCON_ERROR_NONE;
239 API int iotcon_bind_interface(iotcon_resource_h resource, iotcon_interface_e iface)
243 GError *error = NULL;
245 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
246 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
247 if (0 == resource->sub_id) {
248 ERR("Invalid Resource handle");
249 return IOTCON_ERROR_INVALID_PARAMETER;
252 ic_dbus_call_bind_interface_sync(icl_dbus_get_object(), resource->handle,
253 iface, &ret, NULL, &error);
255 ERR("ic_dbus_call_bind_interface_sync() Fail(%s)", error->message);
257 return IOTCON_ERROR_DBUS;
260 if (IOTCON_ERROR_NONE != ret) {
261 ERR("iotcon-daemon Fail(%d)", ret);
262 return icl_dbus_convert_daemon_error(ret);
269 API int iotcon_bind_type(iotcon_resource_h resource, const char *resource_type)
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 RETV_IF(NULL == resource_type, IOTCON_ERROR_INVALID_PARAMETER);
278 if (IOTCON_RESOURCE_TYPE_LENGTH_MAX < strlen(resource_type)) {
279 ERR("Invalid resource_type(%s)", resource_type);
280 return 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_type_sync(icl_dbus_get_object(), resource->handle, resource_type,
291 ERR("ic_dbus_call_bind_type_sync() Fail(%s)", error->message);
293 return IOTCON_ERROR_DBUS;
296 if (IOTCON_ERROR_NONE != ret) {
297 ERR("iotcon-daemon Fail(%d)", ret);
298 return icl_dbus_convert_daemon_error(ret);
305 API int iotcon_bind_request_handler(iotcon_resource_h resource,
306 iotcon_request_handler_cb cb)
308 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
309 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
311 WARN("Request handler is changed");
314 return IOTCON_ERROR_NONE;
318 API int iotcon_bind_resource(iotcon_resource_h parent, iotcon_resource_h child)
323 GError *error = NULL;
325 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
326 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
327 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
328 RETV_IF(parent == child, IOTCON_ERROR_INVALID_PARAMETER);
330 if (0 == parent->sub_id) {
331 ERR("Invalid Resource handle(parent)");
332 return IOTCON_ERROR_INVALID_PARAMETER;
334 if (0 == child->sub_id) {
335 ERR("Invalid Resource handle(child)");
336 return IOTCON_ERROR_INVALID_PARAMETER;
339 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
340 if (child == parent->children[i]) {
341 ERR("Child resource was already bound to parent resource.");
342 return IOTCON_ERROR_ALREADY;
346 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
347 if (NULL == parent->children[i]) {
348 ic_dbus_call_bind_resource_sync(icl_dbus_get_object(), parent->handle,
349 child->handle, &ret, NULL, &error);
351 ERR("ic_dbus_call_bind_resource_sync() Fail(%s)", error->message);
353 return IOTCON_ERROR_DBUS;
356 if (IOTCON_ERROR_NONE != ret) {
357 ERR("iotcon-daemon Fail(%d)", ret);
358 return icl_dbus_convert_daemon_error(ret);
361 parent->children[i] = child;
363 return IOTCON_ERROR_NONE;
367 ERR("There is no slot to bind a child resource");
368 return IOTCON_ERROR_OUT_OF_MEMORY;
372 API int iotcon_unbind_resource(iotcon_resource_h parent, iotcon_resource_h child)
376 GError *error = NULL;
378 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
379 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
380 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
382 if (0 == parent->sub_id) {
383 ERR("Invalid Resource handle(parent)");
384 return IOTCON_ERROR_INVALID_PARAMETER;
386 if (0 == child->sub_id) {
387 ERR("Invalid Resource handle(child)");
388 return IOTCON_ERROR_INVALID_PARAMETER;
391 ic_dbus_call_unbind_resource_sync(icl_dbus_get_object(), parent->handle,
392 child->handle, &ret, NULL, &error);
394 ERR("ic_dbus_call_unbind_resource_sync() Fail(%s)", error->message);
396 return IOTCON_ERROR_DBUS;
399 if (IOTCON_ERROR_NONE != ret) {
400 ERR("iotcon-daemon Fail(%d)", ret);
401 return icl_dbus_convert_daemon_error(ret);
404 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
405 if (child == parent->children[i])
406 parent->children[i] = NULL;
409 return IOTCON_ERROR_NONE;
413 API int iotcon_resource_get_number_of_children(iotcon_resource_h resource, int *number)
417 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
418 RETV_IF(NULL == number, IOTCON_ERROR_INVALID_PARAMETER);
421 for (i = 0; i < IOTCON_CONTAINED_RESOURCES_MAX; i++) {
422 if (resource->children[i])
426 return IOTCON_ERROR_NONE;
430 API int iotcon_resource_get_nth_child(iotcon_resource_h parent, int index,
431 iotcon_resource_h *child)
433 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
434 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
435 if ((index < 0) || (IOTCON_CONTAINED_RESOURCES_MAX <= index)) {
436 ERR("Invalid index(%d)", index);
437 return IOTCON_ERROR_INVALID_PARAMETER;
440 *child = parent->children[index];
442 return IOTCON_ERROR_NONE;
446 /* The content of the resource should not be freed by user. */
447 API int iotcon_resource_get_uri_path(iotcon_resource_h resource, char **uri_path)
449 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
450 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
452 *uri_path = resource->uri_path;
454 return IOTCON_ERROR_NONE;
458 /* The content of the resource should not be freed by user. */
459 API int iotcon_resource_get_types(iotcon_resource_h resource,
460 iotcon_resource_types_h *types)
462 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
463 RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
465 *types = resource->types;
467 return IOTCON_ERROR_NONE;
471 API int iotcon_resource_get_interfaces(iotcon_resource_h resource, int *ifaces)
473 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
474 RETV_IF(NULL == ifaces, IOTCON_ERROR_INVALID_PARAMETER);
476 *ifaces = resource->ifaces;
478 return IOTCON_ERROR_NONE;
482 API int iotcon_resource_is_observable(iotcon_resource_h resource, bool *observable)
484 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
485 RETV_IF(NULL == observable, IOTCON_ERROR_INVALID_PARAMETER);
487 *observable = resource->is_observable;
489 return IOTCON_ERROR_NONE;
493 API iotcon_notimsg_h iotcon_notimsg_new(iotcon_repr_h repr, iotcon_interface_e iface)
495 iotcon_notimsg_h msg;
497 RETV_IF(NULL == repr, NULL);
499 msg = calloc(1, sizeof(struct icl_notify_msg));
501 ERR("calloc() Fail(%d)", errno);
506 icl_repr_inc_ref_count(msg->repr);
508 msg->error_code = 200;
514 API void iotcon_notimsg_free(iotcon_notimsg_h msg)
518 iotcon_repr_free(msg->repr);
523 API int iotcon_notify_list_of_observers(iotcon_resource_h resource, iotcon_notimsg_h msg,
524 iotcon_observers_h observers)
527 GError *error = NULL;
531 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
532 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
533 RETV_IF(NULL == observers, IOTCON_ERROR_INVALID_PARAMETER);
535 if (0 == resource->sub_id) {
536 ERR("Invalid Resource handle");
537 return IOTCON_ERROR_INVALID_PARAMETER;
540 noti_msg = icl_dbus_notimsg_to_gvariant(msg);
541 if (NULL == noti_msg) {
542 ERR("icl_dbus_notimsg_to_gvariant() Fail");
543 return IOTCON_ERROR_REPRESENTATION;
545 obs = icl_dbus_observers_to_gvariant(observers);
547 ic_dbus_call_notify_list_of_observers_sync(icl_dbus_get_object(), resource->handle,
548 noti_msg, obs, &ret, NULL, &error);
550 ERR("ic_dbus_call_notify_list_of_observers_sync() Fail(%s)", error->message);
552 g_variant_unref(obs);
553 g_variant_unref(noti_msg);
554 return IOTCON_ERROR_DBUS;
557 if (IOTCON_ERROR_NONE != ret) {
558 ERR("iotcon-daemon Fail(%d)", ret);
559 return icl_dbus_convert_daemon_error(ret);
562 return IOTCON_ERROR_NONE;
566 API int iotcon_notify_all(iotcon_resource_h resource)
569 GError *error = NULL;
571 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
572 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
573 if (0 == resource->sub_id) {
574 ERR("Invalid Resource handle");
575 return IOTCON_ERROR_INVALID_PARAMETER;
578 ic_dbus_call_notify_all_sync(icl_dbus_get_object(), resource->handle, &ret, NULL,
581 ERR("ic_dbus_call_notify_all_sync() Fail(%s)", error->message);
583 return IOTCON_ERROR_DBUS;
586 if (IOTCON_ERROR_NONE != ret) {
587 ERR("iotcon-daemon Fail(%d)", ret);
588 return icl_dbus_convert_daemon_error(ret);
591 return IOTCON_ERROR_NONE;