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, "(siia(qs)a(ss)iiavxx)",
58 &request.host_address,
59 &request.connectivity_type,
63 &request.observation_info.action,
64 &request.observation_info.observer_id,
66 &request.oic_request_h,
67 &request.oic_resource_h);
69 if (g_variant_iter_n_children(options)) {
70 ret = iotcon_options_create(&request.header_options);
71 if (IOTCON_ERROR_NONE != ret) {
72 ERR("iotcon_options_create() Fail(%d)", ret);
73 g_variant_iter_free(options);
74 g_variant_iter_free(query);
75 g_variant_iter_free(repr_iter);
79 while (g_variant_iter_loop(options, "(q&s)", &option_id, &option_data))
80 iotcon_options_add(request.header_options, option_id, option_data);
82 g_variant_iter_free(options);
84 if (g_variant_iter_n_children(query)) {
85 ret = iotcon_query_create(&request.query);
86 if (IOTCON_ERROR_NONE != ret) {
87 ERR("iotcon_query_create() Fail(%d)", ret);
88 g_variant_iter_free(query);
89 g_variant_iter_free(repr_iter);
90 if (request.header_options)
91 iotcon_options_destroy(request.header_options);
95 while (g_variant_iter_loop(query, "(&s&s)", &key, &value))
96 iotcon_query_add(request.query, key, value);
98 g_variant_iter_free(query);
100 if (g_variant_iter_loop(repr_iter, "v", &repr_gvar)) {
101 request.repr = icl_representation_from_gvariant(repr_gvar);
102 if (NULL == request.repr) {
103 ERR("icl_representation_from_gvariant() Fail");
105 iotcon_query_destroy(request.query);
106 if (request.header_options)
107 iotcon_options_destroy(request.header_options);
111 g_variant_iter_free(repr_iter);
113 /* for iotcon_resource_notify */
114 if (IOTCON_REQUEST_OBSERVE & request.types) {
115 int observer_id = request.observation_info.observer_id;
116 if (IOTCON_OBSERVE_REGISTER == request.observation_info.action) {
117 if (NULL == resource->observers)
118 iotcon_observers_create(&resource->observers);
119 iotcon_observers_add(resource->observers, observer_id);
120 } else if (IOTCON_OBSERVE_DEREGISTER == request.observation_info.action) {
121 iotcon_observers_remove(resource->observers, observer_id);
126 cb(resource, &request, resource->user_data);
128 /* To avoid unnecessary ERR log (representation could be NULL) */
130 iotcon_representation_destroy(request.repr);
132 iotcon_query_destroy(request.query);
133 if (request.header_options)
134 iotcon_options_destroy(request.header_options);
138 static void _icl_resource_conn_cleanup(iotcon_resource_h resource)
140 resource->sub_id = 0;
142 if (resource->handle) {
143 resource->handle = 0;
147 iotcon_resource_types_destroy(resource->types);
148 if (resource->observers)
149 iotcon_observers_destroy(resource->observers);
150 free(resource->uri_path);
155 /* The length of uri_path should be less than or equal to 36. */
156 API int iotcon_resource_create(const char *uri_path,
157 iotcon_resource_types_h res_types,
160 iotcon_request_handler_cb cb,
162 iotcon_resource_h *resource_handle)
165 GError *error = NULL;
167 iotcon_resource_h resource;
168 int signal_number, ret;
169 char sig_name[IC_DBUS_SIGNAL_LENGTH];
171 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
172 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
173 RETVM_IF(ICL_URI_PATH_LENGTH_MAX < strlen(uri_path),
174 IOTCON_ERROR_INVALID_PARAMETER, "Invalid uri_path(%s)", uri_path);
175 RETV_IF(NULL == res_types, IOTCON_ERROR_INVALID_PARAMETER);
176 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
178 resource = calloc(1, sizeof(struct icl_resource));
179 if (NULL == resource) {
180 ERR("calloc() Fail(%d)", errno);
181 return IOTCON_ERROR_OUT_OF_MEMORY;
184 types = icl_dbus_resource_types_to_array(res_types);
186 ERR("icl_dbus_resource_types_to_array() Fail");
188 return IOTCON_ERROR_OUT_OF_MEMORY;
191 signal_number = icl_dbus_generate_signal_number();
193 ic_dbus_call_register_resource_sync(icl_dbus_get_object(), uri_path, types, ifaces,
194 properties, signal_number, &(resource->handle), NULL, &error);
196 ERR("ic_dbus_call_register_resource_sync() Fail(%s)", error->message);
197 ret = icl_dbus_convert_dbus_error(error->code);
205 if (0 == resource->handle) {
206 ERR("iotcon-daemon Fail");
208 return IOTCON_ERROR_IOTIVITY;
212 resource->user_data = user_data;
214 resource->types = icl_resource_types_ref(res_types);
215 resource->uri_path = ic_utils_strdup(uri_path);
216 resource->ifaces = ifaces;
217 resource->properties = properties;
219 snprintf(sig_name, sizeof(sig_name), "%s_%u", IC_DBUS_SIGNAL_REQUEST_HANDLER,
222 sub_id = icl_dbus_subscribe_signal(sig_name, resource, _icl_resource_conn_cleanup,
223 _icl_request_handler);
225 ERR("icl_dbus_subscribe_signal() Fail");
226 iotcon_resource_types_destroy(res_types);
227 free(resource->uri_path);
229 return IOTCON_ERROR_DBUS;
232 resource->sub_id = sub_id;
234 *resource_handle = resource;
236 return IOTCON_ERROR_NONE;
240 API int iotcon_resource_destroy(iotcon_resource_h resource)
244 GError *error = NULL;
246 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
247 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
249 if (0 == resource->sub_id) {
250 WARN("Invalid Resource handle");
251 iotcon_resource_types_destroy(resource->types);
252 if (resource->observers)
253 iotcon_observers_destroy(resource->observers);
254 free(resource->uri_path);
256 return IOTCON_ERROR_NONE;
259 ic_dbus_call_unregister_resource_sync(icl_dbus_get_object(), resource->handle, NULL,
262 ERR("ic_dbus_call_unregister_resource_sync() Fail(%s)", error->message);
263 ret = icl_dbus_convert_dbus_error(error->code);
268 resource->handle = 0;
270 icl_dbus_unsubscribe_signal(resource->sub_id);
272 return IOTCON_ERROR_NONE;
276 API int iotcon_resource_bind_interface(iotcon_resource_h resource,
277 iotcon_interface_e iface)
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 if (0 == resource->sub_id) {
286 ERR("Invalid Resource handle");
287 return IOTCON_ERROR_INVALID_PARAMETER;
290 ic_dbus_call_bind_interface_sync(icl_dbus_get_object(), resource->handle,
291 iface, &ret, NULL, &error);
293 ERR("ic_dbus_call_bind_interface_sync() Fail(%s)", error->message);
294 ret = icl_dbus_convert_dbus_error(error->code);
299 if (IOTCON_ERROR_NONE != ret) {
300 ERR("iotcon-daemon Fail(%d)", ret);
301 return icl_dbus_convert_daemon_error(ret);
308 API int iotcon_resource_bind_type(iotcon_resource_h resource, const char *resource_type)
312 GError *error = NULL;
314 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
315 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
316 RETV_IF(NULL == resource_type, IOTCON_ERROR_INVALID_PARAMETER);
317 if (ICL_RESOURCE_TYPE_LENGTH_MAX < strlen(resource_type)) {
318 ERR("Invalid resource_type(%s)", resource_type);
319 return IOTCON_ERROR_INVALID_PARAMETER;
322 if (0 == resource->sub_id) {
323 ERR("Invalid Resource handle");
324 return IOTCON_ERROR_INVALID_PARAMETER;
327 ic_dbus_call_bind_type_sync(icl_dbus_get_object(), resource->handle, resource_type,
330 ERR("ic_dbus_call_bind_type_sync() Fail(%s)", error->message);
331 ret = icl_dbus_convert_dbus_error(error->code);
336 if (IOTCON_ERROR_NONE != ret) {
337 ERR("iotcon-daemon Fail(%d)", ret);
338 return icl_dbus_convert_daemon_error(ret);
345 API int iotcon_resource_set_request_handler(iotcon_resource_h resource,
346 iotcon_request_handler_cb cb)
348 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
349 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
351 WARN("Request handler is changed");
354 return IOTCON_ERROR_NONE;
358 API int iotcon_resource_bind_child_resource(iotcon_resource_h parent,
359 iotcon_resource_h child)
361 GError *error = NULL;
364 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
365 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
366 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
367 RETV_IF(parent == child, IOTCON_ERROR_INVALID_PARAMETER);
369 if (0 == parent->sub_id) {
370 ERR("Invalid Resource handle(parent)");
371 return IOTCON_ERROR_INVALID_PARAMETER;
373 if (0 == child->sub_id) {
374 ERR("Invalid Resource handle(child)");
375 return IOTCON_ERROR_INVALID_PARAMETER;
378 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
379 if (child == parent->children[i]) {
380 ERR("Child resource was already bound to parent resource.");
381 return IOTCON_ERROR_ALREADY;
385 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
386 if (NULL == parent->children[i]) {
387 ic_dbus_call_bind_resource_sync(icl_dbus_get_object(), parent->handle,
388 child->handle, &ret, NULL, &error);
390 ERR("ic_dbus_call_bind_resource_sync() Fail(%s)", error->message);
391 ret = icl_dbus_convert_dbus_error(error->code);
396 if (IOTCON_ERROR_NONE != ret) {
397 ERR("iotcon-daemon Fail(%d)", ret);
398 return icl_dbus_convert_daemon_error(ret);
401 parent->children[i] = child;
403 return IOTCON_ERROR_NONE;
407 ERR("There is no slot to bind a child resource");
408 return IOTCON_ERROR_OUT_OF_MEMORY;
412 API int iotcon_resource_unbind_child_resource(iotcon_resource_h parent,
413 iotcon_resource_h child)
415 GError *error = NULL;
418 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
419 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
420 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
422 if (0 == parent->sub_id) {
423 ERR("Invalid Resource handle(parent)");
424 return IOTCON_ERROR_INVALID_PARAMETER;
426 if (0 == child->sub_id) {
427 ERR("Invalid Resource handle(child)");
428 return IOTCON_ERROR_INVALID_PARAMETER;
431 ic_dbus_call_unbind_resource_sync(icl_dbus_get_object(), parent->handle,
432 child->handle, &ret, NULL, &error);
434 ERR("ic_dbus_call_unbind_resource_sync() Fail(%s)", error->message);
435 ret = icl_dbus_convert_dbus_error(error->code);
440 if (IOTCON_ERROR_NONE != ret) {
441 ERR("iotcon-daemon Fail(%d)", ret);
442 return icl_dbus_convert_daemon_error(ret);
445 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
446 if (child == parent->children[i])
447 parent->children[i] = NULL;
450 return IOTCON_ERROR_NONE;
454 API int iotcon_resource_get_number_of_children(iotcon_resource_h resource, int *number)
458 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
459 RETV_IF(NULL == number, IOTCON_ERROR_INVALID_PARAMETER);
462 for (i = 0; i < ICL_CONTAINED_RESOURCES_MAX; i++) {
463 if (resource->children[i])
467 return IOTCON_ERROR_NONE;
471 API int iotcon_resource_get_nth_child(iotcon_resource_h parent, int index,
472 iotcon_resource_h *child)
474 RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
475 RETV_IF(NULL == child, IOTCON_ERROR_INVALID_PARAMETER);
476 if ((index < 0) || (ICL_CONTAINED_RESOURCES_MAX <= index)) {
477 ERR("Invalid index(%d)", index);
478 return IOTCON_ERROR_INVALID_PARAMETER;
481 *child = parent->children[index];
483 return IOTCON_ERROR_NONE;
487 /* The content of the resource should not be freed by user. */
488 API int iotcon_resource_get_uri_path(iotcon_resource_h resource, char **uri_path)
490 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
491 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
493 *uri_path = resource->uri_path;
495 return IOTCON_ERROR_NONE;
499 /* The content of the resource should not be freed by user. */
500 API int iotcon_resource_get_types(iotcon_resource_h resource,
501 iotcon_resource_types_h *types)
503 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
504 RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
506 *types = resource->types;
508 return IOTCON_ERROR_NONE;
512 API int iotcon_resource_get_interfaces(iotcon_resource_h resource, int *ifaces)
514 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
515 RETV_IF(NULL == ifaces, IOTCON_ERROR_INVALID_PARAMETER);
517 *ifaces = resource->ifaces;
519 return IOTCON_ERROR_NONE;
523 API int iotcon_resource_get_properties(iotcon_resource_h resource, int *properties)
525 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
526 RETV_IF(NULL == properties, IOTCON_ERROR_INVALID_PARAMETER);
528 *properties = resource->properties;
530 return IOTCON_ERROR_NONE;
534 API int iotcon_notimsg_create(iotcon_representation_h repr, iotcon_interface_e iface,
535 iotcon_notimsg_h *notimsg_handle)
537 iotcon_notimsg_h msg;
539 RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
540 RETV_IF(NULL == notimsg_handle, IOTCON_ERROR_INVALID_PARAMETER);
542 msg = calloc(1, sizeof(struct icl_notify_msg));
544 ERR("calloc() Fail(%d)", errno);
545 return IOTCON_ERROR_OUT_OF_MEMORY;
549 icl_representation_inc_ref_count(msg->repr);
551 msg->error_code = 200;
553 *notimsg_handle = msg;
555 return IOTCON_ERROR_NONE;
559 API void iotcon_notimsg_destroy(iotcon_notimsg_h msg)
563 iotcon_representation_destroy(msg->repr);
567 API int iotcon_resource_notify(iotcon_resource_h resource, iotcon_notimsg_h msg,
568 iotcon_observers_h observers)
571 GError *error = NULL;
575 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
576 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
578 if (0 == resource->sub_id) {
579 ERR("Invalid Resource handle");
580 return IOTCON_ERROR_INVALID_PARAMETER;
583 /* TODO: Get default message if msg parameter is NULL */
584 noti_msg = icl_dbus_notimsg_to_gvariant(msg);
585 if (NULL == noti_msg) {
586 ERR("icl_dbus_notimsg_to_gvariant() Fail");
587 return IOTCON_ERROR_REPRESENTATION;
591 obs = icl_dbus_observers_to_gvariant(observers);
593 obs = icl_dbus_observers_to_gvariant(resource->observers);
595 ic_dbus_call_notify_sync(icl_dbus_get_object(), resource->handle, noti_msg, obs, &ret,
598 ERR("ic_dbus_call_notify_sync() Fail(%s)", error->message);
599 ret = icl_dbus_convert_dbus_error(error->code);
601 g_variant_unref(obs);
602 g_variant_unref(noti_msg);
606 if (IOTCON_ERROR_NONE != ret) {
607 ERR("iotcon-daemon Fail(%d)", ret);
608 return icl_dbus_convert_daemon_error(ret);
611 return IOTCON_ERROR_NONE;