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.
23 #include "iotcon-types.h"
26 #include "icl-options.h"
28 #include "icl-representation.h"
29 #include "icl-remote-resource.h"
30 #include "icl-resource-types.h"
31 #include "icl-payload.h"
33 #define ICL_REMOTE_RESOURCE_MAX_TIME_INTERVAL 3600 /* 60 min */
36 iotcon_found_resource_cb cb;
40 } icl_found_resource_s;
42 static iotcon_remote_resource_h _icl_remote_resource_from_gvariant(GVariant *payload,
43 iotcon_connectivity_type_e connectivity_type);
45 static void _icl_found_resource_cb(GDBusConnection *connection,
46 const gchar *sender_name,
47 const gchar *object_path,
48 const gchar *interface_name,
49 const gchar *signal_name,
54 int connectivity_type;
55 iotcon_remote_resource_h resource;
58 icl_found_resource_s *cb_container = user_data;
59 iotcon_found_resource_cb cb = cb_container->cb;
61 if (cb_container->timeout_id)
62 cb_container->timeout_id = 0;
64 g_variant_get(parameters, "(vi)", &payload, &connectivity_type);
66 resource = _icl_remote_resource_from_gvariant(payload, connectivity_type);
67 if (NULL == resource) {
68 ERR("icl_remote_resource_from_gvariant() Fail");
73 cb(resource, IOTCON_ERROR_NONE, cb_container->user_data);
75 iotcon_remote_resource_destroy(resource);
78 static gboolean _icl_timeout_find_resource(gpointer p)
80 icl_found_resource_s *cb_container = p;
82 if (NULL == cb_container) {
83 ERR("cb_container is NULL");
84 return G_SOURCE_REMOVE;
87 if (cb_container->timeout_id && cb_container->cb)
88 cb_container->cb(NULL, IOTCON_ERROR_TIMEOUT, cb_container->user_data);
90 icl_dbus_unsubscribe_signal(cb_container->id);
93 return G_SOURCE_REMOVE;
97 /* The length of resource_type should be less than or equal to 61.
98 * If resource_type is NULL, then All resources in host are discovered. */
99 API int iotcon_find_resource(const char *host_address,
100 iotcon_connectivity_type_e connectivity_type,
101 const char *resource_type,
103 iotcon_found_resource_cb cb,
108 GError *error = NULL;
109 int64_t signal_number;
110 icl_found_resource_s *cb_container;
111 char signal_name[IC_DBUS_SIGNAL_LENGTH] = {0};
113 RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
114 RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
115 if (resource_type && (ICL_RESOURCE_TYPE_LENGTH_MAX < strlen(resource_type))) {
116 ERR("The length of resource_type(%s) is invalid", resource_type);
117 return IOTCON_ERROR_INVALID_PARAMETER;
120 timeout = icl_dbus_get_timeout();
122 ic_dbus_call_find_resource_sync(icl_dbus_get_object(),
123 ic_utils_dbus_encode_str(host_address),
125 ic_utils_dbus_encode_str(resource_type),
133 ERR("ic_dbus_call_find_resource_sync() Fail(%s)", error->message);
134 ret = icl_dbus_convert_dbus_error(error->code);
139 if (IOTCON_ERROR_NONE != ret) {
140 ERR("iotcon-daemon Fail(%d)", ret);
141 return icl_dbus_convert_daemon_error(ret);
144 snprintf(signal_name, sizeof(signal_name), "%s_%llx", IC_DBUS_SIGNAL_FOUND_RESOURCE,
147 cb_container = calloc(1, sizeof(icl_found_resource_s));
148 if (NULL == cb_container) {
149 ERR("calloc() Fail(%d)", errno);
150 return IOTCON_ERROR_OUT_OF_MEMORY;
153 cb_container->cb = cb;
154 cb_container->user_data = user_data;
156 sub_id = icl_dbus_subscribe_signal(signal_name, cb_container, free,
157 _icl_found_resource_cb);
159 ERR("icl_dbus_subscribe_signal() Fail");
160 return IOTCON_ERROR_DBUS;
163 cb_container->id = sub_id;
165 cb_container->timeout_id = g_timeout_add_seconds(timeout, _icl_timeout_find_resource,
172 /* If you know the information of resource, then you can make a proxy of the resource. */
173 API int iotcon_remote_resource_create(const char *host_address,
174 iotcon_connectivity_type_e connectivity_type,
175 const char *uri_path,
177 iotcon_resource_types_h resource_types,
179 iotcon_remote_resource_h *resource_handle)
182 iotcon_remote_resource_h resource = NULL;
184 RETV_IF(NULL == host_address, IOTCON_ERROR_INVALID_PARAMETER);
185 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
186 RETV_IF(NULL == resource_types, IOTCON_ERROR_INVALID_PARAMETER);
187 RETV_IF(NULL == resource_handle, IOTCON_ERROR_INVALID_PARAMETER);
189 resource = calloc(1, sizeof(struct icl_remote_resource));
190 if (NULL == resource) {
191 ERR("calloc() Fail(%d)", errno);
192 return IOTCON_ERROR_OUT_OF_MEMORY;
195 resource->host_address = ic_utils_strdup(host_address);
196 resource->connectivity_type = connectivity_type;
197 resource->uri_path = ic_utils_strdup(uri_path);
198 resource->properties = properties;
199 resource->types = icl_resource_types_ref(resource_types);
200 resource->ifaces = resource_ifs;
202 *resource_handle = resource;
204 return IOTCON_ERROR_NONE;
208 API void iotcon_remote_resource_destroy(iotcon_remote_resource_h resource)
210 RET_IF(NULL == resource);
212 if (resource->observe_handle)
213 iotcon_remote_resource_observe_deregister(resource);
215 icl_remote_resource_crud_stop(resource);
217 if (0 != resource->caching_sub_id)
218 iotcon_remote_resource_stop_caching(resource);
219 if (0 != resource->monitoring_sub_id)
220 iotcon_remote_resource_stop_monitoring(resource);
222 free(resource->uri_path);
223 free(resource->host_address);
224 free(resource->device_id);
225 iotcon_resource_types_destroy(resource->types);
227 /* null COULD be allowed */
228 if (resource->header_options)
229 iotcon_options_destroy(resource->header_options);
234 static bool _icl_remote_resource_header_foreach_cb(unsigned short id,
235 const char *data, void *user_data)
238 iotcon_remote_resource_h resource = user_data;
240 RETV_IF(NULL == resource, IOTCON_FUNC_STOP);
242 if (NULL == resource->header_options) {
243 ret = iotcon_options_create(&resource->header_options);
244 if (IOTCON_ERROR_NONE != ret) {
245 ERR("resource->header_options() Fail(%d)", ret);
246 return IOTCON_FUNC_STOP;
250 ret = iotcon_options_add(resource->header_options, id, data);
251 if (IOTCON_ERROR_NONE != ret) {
252 ERR("iotcon_options_add() Fail(%d)", ret);
253 return IOTCON_FUNC_STOP;
256 return IOTCON_FUNC_CONTINUE;
259 API int iotcon_remote_resource_clone(iotcon_remote_resource_h src,
260 iotcon_remote_resource_h *dest)
263 iotcon_remote_resource_h resource = NULL;
265 RETV_IF(NULL == src, IOTCON_ERROR_INVALID_PARAMETER);
267 resource = calloc(1, sizeof(struct icl_remote_resource));
268 if (NULL == resource) {
269 ERR("calloc() Fail(%d)", errno);
270 return IOTCON_ERROR_OUT_OF_MEMORY;
273 resource->uri_path = ic_utils_strdup(src->uri_path);
274 resource->host_address = ic_utils_strdup(src->host_address);
275 resource->connectivity_type = src->connectivity_type;
276 resource->device_id = ic_utils_strdup(src->device_id);
277 resource->properties = src->properties;
279 if (src->header_options) {
280 ret = iotcon_options_foreach(src->header_options,
281 _icl_remote_resource_header_foreach_cb, resource);
282 if (IOTCON_ERROR_NONE != ret) {
283 ERR("iotcon_options_foreach() Fail(%d)", ret);
284 iotcon_remote_resource_destroy(resource);
290 ret = iotcon_resource_types_clone(src->types, &resource->types);
291 if (IOTCON_ERROR_NONE != ret) {
292 ERR("iotcon_resource_types_clone() Fail(%d)", ret);
293 iotcon_remote_resource_destroy(resource);
298 resource->ifaces = src->ifaces;
299 resource->connectivity_type = src->connectivity_type;
303 return IOTCON_ERROR_NONE;
307 /* The content of the resource should not be freed by user. */
308 API int iotcon_remote_resource_get_uri_path(iotcon_remote_resource_h resource,
311 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
312 RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
314 *uri_path = resource->uri_path;
316 return IOTCON_ERROR_NONE;
320 /* The content of the resource should not be freed by user. */
321 API int iotcon_remote_resource_get_host_address(iotcon_remote_resource_h resource,
324 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
325 RETV_IF(NULL == host_address, IOTCON_ERROR_INVALID_PARAMETER);
327 *host_address = resource->host_address;
329 return IOTCON_ERROR_NONE;
333 /* The content of the resource should not be freed by user. */
334 API int iotcon_remote_resource_get_connectivity_type(iotcon_remote_resource_h resource,
335 iotcon_connectivity_type_e *connectivity_type)
337 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
338 RETV_IF(NULL == connectivity_type, IOTCON_ERROR_INVALID_PARAMETER);
340 *connectivity_type = resource->connectivity_type;
342 return IOTCON_ERROR_NONE;
346 /* The content of the resource should not be freed by user. */
347 API int iotcon_remote_resource_get_device_id(iotcon_remote_resource_h resource,
350 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
351 RETV_IF(NULL == device_id, IOTCON_ERROR_INVALID_PARAMETER);
353 *device_id = resource->device_id;
355 return IOTCON_ERROR_NONE;
358 /* The content of the resource should not be freed by user. */
359 API int iotcon_remote_resource_get_types(iotcon_remote_resource_h resource,
360 iotcon_resource_types_h *types)
362 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
363 RETV_IF(NULL == types, IOTCON_ERROR_INVALID_PARAMETER);
365 *types = resource->types;
367 return IOTCON_ERROR_NONE;
371 API int iotcon_remote_resource_get_interfaces(iotcon_remote_resource_h resource,
374 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
375 RETV_IF(NULL == ifaces, IOTCON_ERROR_INVALID_PARAMETER);
377 *ifaces = resource->ifaces;
379 return IOTCON_ERROR_NONE;
383 API int iotcon_remote_resource_get_properties(iotcon_remote_resource_h resource,
386 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
387 RETV_IF(NULL == properties, IOTCON_ERROR_INVALID_PARAMETER);
389 *properties = resource->properties;
391 return IOTCON_ERROR_NONE;
394 API int iotcon_remote_resource_get_options(iotcon_remote_resource_h resource,
395 iotcon_options_h *options)
397 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
398 RETV_IF(NULL == options, IOTCON_ERROR_INVALID_PARAMETER);
400 *options = resource->header_options;
402 return IOTCON_ERROR_NONE;
405 /* if header_options is NULL, then client's header_options is unset */
406 API int iotcon_remote_resource_set_options(iotcon_remote_resource_h resource,
407 iotcon_options_h options)
409 RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
411 if (resource->header_options)
412 iotcon_options_destroy(resource->header_options);
415 resource->header_options = icl_options_ref(options);
417 resource->header_options = NULL;
419 return IOTCON_ERROR_NONE;
423 static iotcon_remote_resource_h _icl_remote_resource_from_gvariant(GVariant *payload,
424 iotcon_connectivity_type_e connectivity_type)
427 iotcon_remote_resource_h resource;
428 GVariantIter *types_iter;
429 char host_addr[PATH_MAX] = {0};
430 iotcon_resource_types_h res_types;
431 char *uri_path, *device_id, *res_type, *addr;
432 int ifaces, properties, is_secure, port;
434 g_variant_get(payload, "(&s&siasib&si)", &uri_path, &device_id, &ifaces, &types_iter,
435 &properties, &is_secure, &addr, &port);
437 switch (connectivity_type) {
438 case IOTCON_CONNECTIVITY_IPV6:
439 snprintf(host_addr, sizeof(host_addr), "[%s]:%d", addr, port);
441 case IOTCON_CONNECTIVITY_IPV4:
442 snprintf(host_addr, sizeof(host_addr), "%s:%d", addr, port);
444 case IOTCON_CONNECTIVITY_BT_EDR:
446 snprintf(host_addr, sizeof(host_addr), "%s", addr);
449 ret = iotcon_resource_types_create(&res_types);
450 if (IOTCON_ERROR_NONE != ret) {
451 ERR("iotcon_resource_types_create() Fail(%d)", ret);
455 while (g_variant_iter_loop(types_iter, "s", &res_type))
456 iotcon_resource_types_add(res_types, res_type);
458 ret = iotcon_remote_resource_create(host_addr, connectivity_type, uri_path,
459 properties, res_types, ifaces, &resource);
461 iotcon_resource_types_destroy(res_types);
463 if (IOTCON_ERROR_NONE != ret) {
464 ERR("iotcon_remote_resource_create() Fail");
468 resource->device_id = strdup(device_id);
469 if (NULL == resource->device_id) {
470 ERR("strdup(device_id) Fail(%d)", errno);
471 iotcon_remote_resource_destroy(resource);
474 resource->connectivity_type = connectivity_type;
475 resource->properties = properties;
481 API int iotcon_remote_resource_get_time_interval(int *time_interval)
483 GError *error = NULL;
484 int ret, arg_time_interval;
486 RETV_IF(NULL == time_interval, IOTCON_ERROR_INVALID_PARAMETER);
488 ic_dbus_call_encap_get_time_interval_sync(icl_dbus_get_object(), &arg_time_interval,
491 ERR("ic_dbus_call_encap_get_time_interval_sync() Fail(%s)", error->message);
492 ret = icl_dbus_convert_dbus_error(error->code);
497 *time_interval = arg_time_interval;
499 return IOTCON_ERROR_NONE;
503 API int iotcon_remote_resource_set_time_interval(int time_interval)
506 GError *error = NULL;
508 RETV_IF(ICL_REMOTE_RESOURCE_MAX_TIME_INTERVAL < time_interval || time_interval <= 0,
509 IOTCON_ERROR_INVALID_PARAMETER);
511 ic_dbus_call_encap_set_time_interval_sync(icl_dbus_get_object(), time_interval,
514 ERR("ic_dbus_call_encap_set_time_interval_sync() Fail(%s)", error->message);
515 ret = icl_dbus_convert_dbus_error(error->code);
520 return IOTCON_ERROR_NONE;