--- /dev/null
+/*
+ * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <glib.h>
+
+#include <tizen.h>
+#include <service_app.h>
+#include <iotcon.h>
+#include <Eina.h>
+
+#include "log.h"
+#include "connectivity.h"
+
+#define DOOR_RESOURCE_URI_PREFIX "/door"
+#define DOOR_RESOURCE_TYPE "org.tizen.door"
+
+struct _connectivity_resource_s {
+ char *device_id;
+ char *host_address;
+ char *device_name;
+ char *uri_path;
+ iotcon_presence_h presence;
+ iotcon_remote_resource_h resource;
+};
+
+static struct {
+ Eina_List *list;
+} connectivity_info = {
+ .list = NULL,
+};
+
+static void _response_query_cb(iotcon_remote_resource_h resource, iotcon_error_e err,
+ iotcon_request_type_e request_type, iotcon_response_h response, void *user_data);
+
+static void _observe_cb(iotcon_remote_resource_h resource, iotcon_error_e err, int sequence_number, iotcon_response_h response, void *user_data)
+{
+ int ret = -1;
+ bool opened = false;
+ iotcon_attributes_h attributes = NULL;
+ iotcon_representation_h repr = NULL;
+ iotcon_response_result_e response_result;
+
+ ret_if(IOTCON_ERROR_NONE != err);
+
+ ret = iotcon_response_get_result(response, &response_result);
+ if (IOTCON_ERROR_NONE != ret) {
+ _E("iotcon_response_get_result() Fail(%d)", ret);
+ return;
+ }
+
+ if (IOTCON_RESPONSE_OK != response_result) {
+ _E("_on_response_observe Response error(%d)", response_result);
+ return;
+ }
+
+ ret = iotcon_response_get_representation(response, &repr);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ ret = iotcon_representation_get_attributes(repr, &attributes);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ ret = iotcon_attributes_get_bool(attributes, "opened", &opened);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ if (opened) _I("[Door] opened.");
+ else _I("[Door] closed.");
+}
+
+static void _response_delete_query(iotcon_remote_resource_h resource, iotcon_response_h response, void *user_data)
+{
+ int ret = -1;
+ iotcon_response_result_e response_result;
+
+ ret = iotcon_response_get_result(response, &response_result);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ if (IOTCON_RESPONSE_OK != response_result
+ && IOTCON_RESPONSE_RESOURCE_DELETED != response_result) {
+ _E("_response_delete_query Response error(%d)", response_result);
+ return;
+ }
+
+ _I("DELETE request was successful");
+ /* FIXME : need to free resources? */
+ iotcon_remote_resource_destroy(resource);
+}
+
+static void _response_post_query(iotcon_remote_resource_h resource, iotcon_response_h response, void *user_data)
+{
+ int ret = -1;
+ char *host = NULL, *created_uri_path = NULL;
+ iotcon_connectivity_type_e connectivity_type;
+ iotcon_response_result_e response_result;
+ iotcon_attributes_h recv_attributes = NULL;
+ iotcon_resource_types_h types = NULL;
+ iotcon_resource_interfaces_h ifaces = NULL;
+ iotcon_remote_resource_h new_door_resource = NULL;
+ iotcon_representation_h recv_repr = NULL;
+
+ ret = iotcon_response_get_result(response, &response_result);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ if (IOTCON_RESPONSE_RESOURCE_CREATED != response_result) {
+ _E("_response_post_query Response error(%d)", response_result);
+ return;
+ }
+
+ _I("POST request was successful");
+
+ ret = iotcon_response_get_representation(response, &recv_repr);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ ret = iotcon_representation_get_attributes(recv_repr, &recv_attributes);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ ret = iotcon_attributes_get_str(recv_attributes, "createduripath", &created_uri_path);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ _D("New resource created : %s", created_uri_path);
+
+ ret = iotcon_remote_resource_get_host_address(resource, &host);
+ if (IOTCON_ERROR_NONE != ret) {
+ _E("iotcon_remote_resource_get_host_address() Fail(%d)", ret);
+ return;
+ }
+
+ ret = iotcon_remote_resource_get_connectivity_type(resource, &connectivity_type);
+ if (IOTCON_ERROR_NONE != ret) {
+ _E("iotcon_remote_resource_get_connectivity_type() Fail(%d)", ret);
+ return;
+ }
+
+ ret = iotcon_remote_resource_get_types(resource, &types);
+ if (IOTCON_ERROR_NONE != ret) {
+ _E("iotcon_remote_resource_get_types() Fail(%d)", ret);
+ return;
+ }
+
+ ret = iotcon_remote_resource_get_interfaces(resource, &ifaces);
+ if (IOTCON_ERROR_NONE != ret) {
+ _E("iotcon_remote_resource_get_interfaces() Fail(%d)", ret);
+ return;
+ }
+
+ ret = iotcon_remote_resource_create(host, connectivity_type, created_uri_path,
+ IOTCON_RESOURCE_SECURE, types, ifaces, &new_door_resource);
+ if (IOTCON_ERROR_NONE != ret) {
+ _E("iotcon_remote_resource_create() Fail(%d)", ret);
+ return;
+ }
+
+ ret = iotcon_remote_resource_delete(new_door_resource, _response_query_cb, NULL);
+ if (IOTCON_ERROR_NONE != ret) {
+ _E("iotcon_remote_resource_delete() Fail(%d)", ret);
+ iotcon_remote_resource_destroy(new_door_resource);
+ return;
+ }
+}
+
+static void _response_put_query(iotcon_remote_resource_h resource, iotcon_response_h response, void *user_data)
+{
+ int ret = -1;
+ iotcon_response_result_e response_result;
+ iotcon_representation_h send_repr = NULL;
+
+ ret = iotcon_response_get_result(response, &response_result);
+ if (IOTCON_ERROR_NONE != ret) {
+ _E("iotcon_response_get_result() Fail(%d)", ret);
+ return;
+ }
+
+ if (IOTCON_RESPONSE_RESOURCE_CHANGED != response_result) {
+ _E("_response_put_query Response error(%d)", response_result);
+ return;
+ }
+
+ _I("PUT request was successful");
+
+ ret = iotcon_representation_create(&send_repr);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ ret = iotcon_remote_resource_post(resource, send_repr, NULL, _response_query_cb, NULL);
+ goto_if(IOTCON_ERROR_NONE != ret, out);
+
+out:
+ iotcon_representation_destroy(send_repr);
+}
+
+static void _response_get_query(iotcon_remote_resource_h resource, iotcon_response_h response, void *user_data)
+{
+ bool opened = true;
+ char *resource_host = NULL;
+ int ret = -1;
+ iotcon_response_result_e response_result;
+ iotcon_representation_h send_repr = NULL;
+ iotcon_representation_h recv_repr = NULL;
+ iotcon_attributes_h send_attributes = NULL;
+ iotcon_attributes_h recv_attributes = NULL;
+
+ ret = iotcon_response_get_result(response, &response_result);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ if (IOTCON_RESPONSE_OK != response_result) {
+ _E("_response_get_query response error(%d)", response_result);
+ return;
+ }
+
+ iotcon_remote_resource_get_host_address(resource, &resource_host);
+ _I("Resource host : %s", resource_host);
+
+ ret = iotcon_response_get_representation(response, &recv_repr);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ ret = iotcon_representation_get_attributes(recv_repr, &recv_attributes);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ ret = iotcon_attributes_get_bool(recv_attributes, "opened", &opened);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ ret = iotcon_representation_create(&send_repr);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ ret = iotcon_attributes_create(&send_attributes);
+ goto_if(IOTCON_ERROR_NONE != ret, error);
+
+ ret = iotcon_attributes_add_bool(send_attributes, "opened", !opened);
+ goto_if(IOTCON_ERROR_NONE != ret, error);
+
+ ret = iotcon_representation_set_attributes(send_repr, send_attributes);
+ goto_if(IOTCON_ERROR_NONE != ret, error);
+
+ ret = iotcon_remote_resource_put(resource, send_repr, NULL, _response_query_cb, NULL);
+ goto_if(IOTCON_ERROR_NONE != ret, error);
+
+ iotcon_attributes_destroy(send_attributes);
+ iotcon_representation_destroy(send_repr);
+
+ return;
+
+error:
+ if (send_attributes) iotcon_attributes_destroy(send_attributes);
+ if (send_repr) iotcon_representation_destroy(send_repr);
+
+}
+
+static void _presence_cb(iotcon_presence_h presence, iotcon_error_e err,
+ iotcon_presence_response_h response, void *user_data)
+{
+ int ret = -1;
+ char *host_address = NULL;
+ char *resource_type = NULL;
+ iotcon_presence_result_e result;
+ iotcon_presence_trigger_e trigger;
+ iotcon_connectivity_type_e connectivity_type;
+
+ ret_if(IOTCON_ERROR_NONE != err);
+
+ ret = iotcon_presence_response_get_result(response, &result);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ _I("Presence callback's result : %d", result);
+
+ if (IOTCON_PRESENCE_OK == result) {
+ ret = iotcon_presence_response_get_trigger(response, &trigger);
+ ret_if(IOTCON_ERROR_NONE != ret);
+ _I("trigger : %d", trigger);
+ }
+
+ ret = iotcon_presence_response_get_host_address(response, &host_address);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ ret = iotcon_presence_response_get_connectivity_type(response, &connectivity_type);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ ret = iotcon_presence_response_get_resource_type(response, &resource_type);
+ ret_if(IOTCON_ERROR_NONE != ret);
+
+ _I("Host address : %s", host_address);
+ _I("Resource type : %s", resource_type);
+}
+
+static void _response_query_cb(iotcon_remote_resource_h resource,
+ iotcon_error_e err,
+ iotcon_request_type_e request_type,
+ iotcon_response_h response,
+ void *user_data)
+{
+ ret_if(IOTCON_ERROR_NONE != err);
+
+ _I("Request type[%d]", request_type);
+
+ switch (request_type) {
+ case IOTCON_REQUEST_GET:
+ _response_get_query(resource, response, user_data);
+ break;
+ case IOTCON_REQUEST_PUT:
+ _response_put_query(resource, response, user_data);
+ break;
+ case IOTCON_REQUEST_POST:
+ _response_post_query(resource, response, user_data);
+ break;
+ case IOTCON_REQUEST_DELETE:
+ _response_delete_query(resource, response, user_data);
+ break;
+ default:
+ _E("Invalid request type (%d)", request_type);
+ }
+}
+
+/* return values : -1 error, 0 not exist, 1 exist */
+static int _exist_device_id_in_list(iotcon_remote_resource_h resource)
+{
+ Eina_List *l = NULL, *ln = NULL;
+ connectivity_resource_s *temp = NULL;
+ char *device_id = NULL;
+ int ret = -1;
+
+ retv_if(!resource, -1);
+
+ ret = iotcon_remote_resource_get_device_id(resource, &device_id);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ EINA_LIST_FOREACH_SAFE(connectivity_info.list, l, ln, temp) {
+ continue_if(!temp->device_id);
+ if (!strncmp(temp->device_id, device_id, strlen(device_id))) {
+ _D("\"%s\" already found. skip !", device_id);
+ return 1;
+ }
+ }
+
+ _I("Resource[%s] is not in the list", device_id);
+
+ return 0;
+}
+
+static int _add_resource_info_into_list(connectivity_resource_s *info)
+{
+ retv_if(!info, -1);
+ connectivity_info.list = eina_list_append(connectivity_info.list, info);
+ return 0;
+}
+
+#if 0
+static connectivity_resource_s *_pop_device_id_from_list(const char *device_id)
+{
+ Eina_List *l = NULL, *ln = NULL;
+ connectivity_resource_s *temp = NULL;
+ connectivity_resource_s *info = NULL;
+
+ retv_if(!device_id, NULL);
+
+ EINA_LIST_FOREACH_SAFE(connectivity_info.list, l, ln, temp) {
+ continue_if(!temp->device_id);
+ if (!strncmp(temp->device_id, device_id, strlen(device_id))) {
+ connectivity_info.list = eina_list_remove(connectivity_info.list, temp);
+ info = temp;
+ break;
+ }
+ }
+
+ return info;
+}
+#endif
+
+static bool _get_res_iface_cb(const char *string, void *user_data)
+{
+ char *resource_uri_path = user_data;
+ _I("[%s] resource interface : %s", resource_uri_path, string);
+ return IOTCON_FUNC_CONTINUE;
+}
+
+static bool _get_res_type_cb(const char *string, void *user_data)
+{
+ char *resource_uri_path = user_data;
+ _I("[%s] resource type : %s", resource_uri_path, string);
+ return IOTCON_FUNC_CONTINUE;
+}
+
+static int _retrieve_resource_info(iotcon_remote_resource_h resource, connectivity_resource_s *info)
+{
+ int ret = -1;
+ char *device_id = NULL;
+ char *host_address = NULL;
+ char *device_name = NULL;
+ char *uri_path = NULL;
+ iotcon_resource_interfaces_h resource_interfaces;
+ iotcon_resource_types_h resource_types;
+ iotcon_connectivity_type_e connectivity_type;
+
+ retv_if(!info, -1);
+
+ ret = iotcon_remote_resource_get_device_id(resource, &device_id);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_remote_resource_get_host_address(resource, &host_address);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_remote_resource_get_device_name(resource, &device_name);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_remote_resource_get_uri_path(resource, &uri_path);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_remote_resource_get_connectivity_type(resource, &connectivity_type);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_remote_resource_get_interfaces(resource, &resource_interfaces);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_resource_interfaces_foreach(resource_interfaces, _get_res_iface_cb, uri_path);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_remote_resource_get_types(resource, &resource_types);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_resource_types_foreach(resource_types, _get_res_type_cb, uri_path);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_remote_resource_clone(resource, &info->resource);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ _I("Resource Addr[%s/%s] is in Device[%s]", host_address, uri_path, device_name);
+
+ info->device_id = strdup(device_id);
+ goto_if(!info->device_id, error);
+
+ info->host_address = strdup(host_address);
+ goto_if(!info->host_address, error);
+
+ info->device_name = strdup(device_name);
+ goto_if(!info->device_name, error);
+
+ info->uri_path = strdup(uri_path);
+ goto_if(!info->uri_path, error);
+
+ return 0;
+
+error:
+ if (info->resource) {
+ iotcon_remote_resource_destroy(info->resource);
+ info->resource = NULL;
+ }
+ if (info->uri_path) {
+ free(info->uri_path);
+ info->uri_path = NULL;
+ }
+ if (info->device_name) {
+ free(info->device_name);
+ info->device_name = NULL;
+ }
+ if (info->host_address) {
+ free(info->host_address);
+ info->host_address = NULL;
+ }
+ if (info->device_id) {
+ free(info->device_id);
+ info->device_id = NULL;
+ }
+
+ return -1;
+}
+
+static void _free_resource_info(connectivity_resource_s *info)
+{
+ ret_if(!info);
+
+ if (info->presence)
+ iotcon_remove_presence_cb(info->presence);
+
+ if (info->resource)
+ iotcon_remote_resource_destroy(info->resource);
+
+ if (info->uri_path)
+ free(info->uri_path);
+
+ if (info->device_name)
+ free(info->device_name);
+
+ if (info->host_address)
+ free(info->host_address);
+
+ if (info->device_id)
+ free(info->device_id);
+
+ free(info);
+}
+
+static void _free_resource_info_list(void)
+{
+ connectivity_resource_s *info = NULL;
+
+ EINA_LIST_FREE(connectivity_info.list, info) {
+ _free_resource_info(info);
+ }
+}
+
+
+static int _register_presence(iotcon_remote_resource_h resource, connectivity_resource_s *info)
+{
+ int ret = -1;
+ char *resource_host = NULL;
+ iotcon_connectivity_type_e connectivity_type;
+
+ ret = iotcon_remote_resource_get_host_address(resource, &resource_host);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_remote_resource_get_connectivity_type(resource, &connectivity_type);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ /* FIXME : We need to remove presence_cb when not needed */
+ ret = iotcon_add_presence_cb(resource_host,
+ connectivity_type,
+ DOOR_RESOURCE_TYPE,
+ _presence_cb,
+ NULL,
+ &info->presence);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ return 0;
+}
+
+#if 0
+static void _unregister_presence(connectivity_resource_s *info)
+{
+ ret_if(!info);
+ iotcon_remove_presence_cb(info->presence);
+ info->presence = NULL;
+}
+#endif
+
+static int _register_observe(connectivity_resource_s *info)
+{
+ int ret = -1;
+
+ /* resource is cloned data */
+ ret = iotcon_remote_resource_observe_register(info->resource,
+ IOTCON_OBSERVE_IGNORE_OUT_OF_ORDER,
+ NULL,
+ _observe_cb,
+ NULL);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ return 0;
+}
+
+#if 0
+static void _unregister_observe(connectivity_resource_s *info)
+{
+ ret_if(!info);
+ iotcon_remote_resource_observe_deregister(info->resource);
+}
+#endif
+
+static int _request_query(connectivity_resource_s *info)
+{
+ int ret = -1;
+ iotcon_query_h query = NULL;
+
+ ret = iotcon_query_create(&query);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_query_add(query, "query_key", "query_value");
+ goto_if(IOTCON_ERROR_NONE != ret, error);
+
+ ret = iotcon_remote_resource_get(info->resource, query, _response_query_cb, NULL);
+ goto_if(IOTCON_ERROR_NONE != ret, error);
+
+ iotcon_query_destroy(query);
+ return 0;
+
+error:
+ iotcon_query_destroy(query);
+ return -1;
+}
+
+static bool _found_resource_cb(iotcon_remote_resource_h resource, iotcon_error_e result, void *user_data)
+{
+ int ret = -1;
+ connectivity_resource_s *info = NULL;
+
+ _D("HELLO");
+ /* We should know where we get wrong results */
+ /* Can attackers send wrong messages to stop this? */
+ retv_if(IOTCON_ERROR_NONE != result, IOTCON_FUNC_STOP);
+ if (!resource) return IOTCON_FUNC_CONTINUE;
+
+ _I("Resource is found");
+
+ ret = _exist_device_id_in_list(resource);
+ retv_if(-1 == ret, IOTCON_FUNC_CONTINUE);
+ if (1 == ret) return IOTCON_FUNC_CONTINUE;
+
+ info = calloc(1, sizeof(connectivity_resource_s));
+ retv_if(!info, IOTCON_FUNC_CONTINUE);
+
+ ret = _add_resource_info_into_list(info);
+ goto_if(-1 == ret, error);
+
+ ret = _retrieve_resource_info(resource, info);
+ goto_if(-1 == ret, error);
+
+ /* FIXME : We have to develop these routines more for meaningful usecases */
+ /* We can think several scenarios like intentionally closing servers. */
+ ret = _register_presence(resource, info);
+ goto_if(-1 == ret, error);
+
+ if (-1 == _register_observe(info)) {
+ _E("Cannot observe [%s:%s:%s:%s]", info->device_id, info->host_address, info->device_name, info->uri_path);
+ }
+
+ if (-1 == _request_query(info)) {
+ _E("Cannot request query");
+ }
+
+ return IOTCON_FUNC_CONTINUE;
+
+error:
+ connectivity_info.list = eina_list_remove(connectivity_info.list, info);
+ if (info) _free_resource_info(info);
+ return IOTCON_FUNC_CONTINUE;
+}
+
+int connectivity_init(void)
+{
+ int ret = -1;
+
+ ret = iotcon_initialize("/usr/apps/org.tizen.position-finder-client/res/iotcon-test-svr-db-client.dat");
+ if (IOTCON_ERROR_NONE != ret) {
+ _E("iotcon_initialize() Fail(%d)", ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+int connectivity_fini(void)
+{
+ /* deinitialize iotcon */
+ _free_resource_info_list();
+ iotcon_deinitialize();
+ return 0;
+}
+
+int connectivity_find_resource(void)
+{
+ int ret = -1;
+ iotcon_query_h query = NULL;
+
+ _D("HELLO");
+
+ ret = iotcon_query_create(&query);
+ retv_if(IOTCON_ERROR_NONE != ret, -1);
+
+ ret = iotcon_query_set_resource_type(query, DOOR_RESOURCE_TYPE);
+ goto_if(IOTCON_ERROR_NONE != ret, error);
+
+ ret = iotcon_find_resource(IOTCON_MULTICAST_ADDRESS,
+ IOTCON_CONNECTIVITY_IP | IOTCON_CONNECTIVITY_PREFER_UDP,
+ query,
+ _found_resource_cb,
+ NULL);
+ goto_if(IOTCON_ERROR_NONE != ret, error);
+
+ _D("HELLO");
+ iotcon_query_destroy(query);
+ return 0;
+
+error:
+ iotcon_query_destroy(query);
+ return -1;
+}