fix the problem when structures are destoried, repeatedly
[platform/core/iot/iotcon.git] / lib / icl-resource.c
index 4c0e5bf..b077a6c 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <glib.h>
+#include <tizen_type.h>
 
 #include "iotcon.h"
 #include "ic-utils.h"
 #include "icl.h"
-#include "icl-repr.h"
+#include "icl-representation.h"
 #include "icl-dbus.h"
 #include "icl-request.h"
 #include "icl-dbus-type.h"
 #include "icl-resource.h"
 #include "icl-payload.h"
 
-/**
- * @brief The maximum length of uri_path path which can be held in a resource.
- *
- * @since_tizen 3.0
- */
-#define ICL_URI_PATH_LENGTH_MAX 36
-
-
 static void _icl_request_handler(GDBusConnection *connection,
                const gchar *sender_name,
                const gchar *object_path,
@@ -62,12 +54,14 @@ static void _icl_request_handler(GDBusConnection *connection,
        iotcon_resource_h resource = user_data;
        iotcon_request_handler_cb cb = resource->cb;
 
-       g_variant_get(parameters, "(ia(qs)a(ss)iiavxx)",
-                       &request.types,
+       g_variant_get(parameters, "(siia(qs)a(ss)iiavxx)",
+                       &request.host_address,
+                       &request.connectivity_type,
+                       &request.type,
                        &options,
                        &query,
                        &request.observation_info.action,
-                       &request.observation_info.observer_id,
+                       &request.observation_info.observe_id,
                        &repr_iter,
                        &request.oic_request_h,
                        &request.oic_resource_h);
@@ -83,7 +77,7 @@ static void _icl_request_handler(GDBusConnection *connection,
                }
 
                while (g_variant_iter_loop(options, "(q&s)", &option_id, &option_data))
-                       iotcon_options_insert(request.header_options, option_id, option_data);
+                       iotcon_options_add(request.header_options, option_id, option_data);
        }
        g_variant_iter_free(options);
 
@@ -93,11 +87,13 @@ static void _icl_request_handler(GDBusConnection *connection,
                        ERR("iotcon_query_create() Fail(%d)", ret);
                        g_variant_iter_free(query);
                        g_variant_iter_free(repr_iter);
+                       if (request.header_options)
+                               iotcon_options_destroy(request.header_options);
                        return;
                }
 
                while (g_variant_iter_loop(query, "(&s&s)", &key, &value))
-                       iotcon_query_insert(request.query, key, value);
+                       iotcon_query_add(request.query, key, value);
        }
        g_variant_iter_free(query);
 
@@ -114,8 +110,14 @@ static void _icl_request_handler(GDBusConnection *connection,
        }
        g_variant_iter_free(repr_iter);
 
-       /* TODO remove request.uri */
-       request.uri_path = "temp_uri_path";
+       /* for iotcon_resource_notify */
+       if (IOTCON_OBSERVE_REGISTER == request.observation_info.action) {
+               if (NULL == resource->observers)
+                       iotcon_observers_create(&resource->observers);
+               iotcon_observers_add(resource->observers, request.observation_info.observe_id);
+       } else if (IOTCON_OBSERVE_DEREGISTER == request.observation_info.action) {
+               iotcon_observers_remove(resource->observers, request.observation_info.observe_id);
+       }
 
        if (cb)
                cb(resource, &request, resource->user_data);
@@ -140,28 +142,31 @@ static void _icl_resource_conn_cleanup(iotcon_resource_h resource)
        }
 
        iotcon_resource_types_destroy(resource->types);
+       if (resource->observers)
+               iotcon_observers_destroy(resource->observers);
        free(resource->uri_path);
        free(resource);
 }
 
 
 /* The length of uri_path should be less than or equal to 36. */
-API int iotcon_register_resource(const char *uri_path,
+API int iotcon_resource_create(const char *uri_path,
                iotcon_resource_types_h res_types,
                int ifaces,
-               uint8_t properties,
+               int properties,
                iotcon_request_handler_cb cb,
                void *user_data,
                iotcon_resource_h *resource_handle)
 {
+       int ret;
        unsigned int sub_id;
-       GError *error = NULL;
        const gchar **types;
+       GError *error = NULL;
        iotcon_resource_h resource;
-       int signal_number, error_code;
-       char sig_name[IC_DBUS_SIGNAL_LENGTH];
+       int64_t signal_number;
+       char signal_name[IC_DBUS_SIGNAL_LENGTH];
 
-       RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
        RETV_IF(NULL == uri_path, IOTCON_ERROR_INVALID_PARAMETER);
        RETVM_IF(ICL_URI_PATH_LENGTH_MAX < strlen(uri_path),
                        IOTCON_ERROR_INVALID_PARAMETER, "Invalid uri_path(%s)", uri_path);
@@ -178,20 +183,18 @@ API int iotcon_register_resource(const char *uri_path,
        if (NULL == types) {
                ERR("icl_dbus_resource_types_to_array() Fail");
                free(resource);
-               return IOTCON_ERROR_INVALID_PARAMETER;
+               return IOTCON_ERROR_OUT_OF_MEMORY;
        }
 
-       signal_number = icl_dbus_generate_signal_number();
-
        ic_dbus_call_register_resource_sync(icl_dbus_get_object(), uri_path, types, ifaces,
-                       properties, signal_number, &(resource->handle), NULL, &error);
+                       properties, &signal_number, &(resource->handle), NULL, &error);
        if (error) {
                ERR("ic_dbus_call_register_resource_sync() Fail(%s)", error->message);
-               error_code = icl_dbus_convert_dbus_error(error->code);
+               ret = icl_dbus_convert_dbus_error(error->code);
                g_error_free(error);
                free(types);
                free(resource);
-               return error_code;
+               return ret;
        }
        free(types);
 
@@ -207,15 +210,17 @@ API int iotcon_register_resource(const char *uri_path,
        resource->types = icl_resource_types_ref(res_types);
        resource->uri_path = ic_utils_strdup(uri_path);
        resource->ifaces = ifaces;
-       resource->is_observable = properties & IOTCON_OBSERVABLE;
+       resource->properties = properties;
 
-       snprintf(sig_name, sizeof(sig_name), "%s_%u", IC_DBUS_SIGNAL_REQUEST_HANDLER,
+       snprintf(signal_name, sizeof(signal_name), "%s_%llx", IC_DBUS_SIGNAL_REQUEST_HANDLER,
                        signal_number);
 
-       sub_id = icl_dbus_subscribe_signal(sig_name, resource, _icl_resource_conn_cleanup,
+       sub_id = icl_dbus_subscribe_signal(signal_name, resource, _icl_resource_conn_cleanup,
                        _icl_request_handler);
        if (0 == sub_id) {
                ERR("icl_dbus_subscribe_signal() Fail");
+               iotcon_resource_types_destroy(res_types);
+               free(resource->uri_path);
                free(resource);
                return IOTCON_ERROR_DBUS;
        }
@@ -228,48 +233,51 @@ API int iotcon_register_resource(const char *uri_path,
 }
 
 
-API int iotcon_unregister_resource(iotcon_resource_h resource)
+API int iotcon_resource_destroy(iotcon_resource_h resource)
 {
        FN_CALL;
-       int ret, error_code;
+       int ret;
        GError *error = NULL;
 
-       RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
        RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
 
-       if (0 == resource->sub_id) {
+       if (0 == resource->handle) { /* iotcon dbus disconnected */
                WARN("Invalid Resource handle");
                iotcon_resource_types_destroy(resource->types);
+               if (resource->observers)
+                       iotcon_observers_destroy(resource->observers);
                free(resource->uri_path);
                free(resource);
                return IOTCON_ERROR_NONE;
        }
 
-       ic_dbus_call_unregister_resource_sync(icl_dbus_get_object(), resource->handle,
-                       &ret, NULL, &error);
+       if (NULL == icl_dbus_get_object()) {
+               ERR("icl_dbus_get_object() return NULL");
+               return IOTCON_ERROR_DBUS;
+       }
+
+       ic_dbus_call_unregister_resource_sync(icl_dbus_get_object(), resource->handle, NULL,
+                       &error);
        if (error) {
                ERR("ic_dbus_call_unregister_resource_sync() Fail(%s)", error->message);
-               error_code = icl_dbus_convert_dbus_error(error->code);
+               ret = icl_dbus_convert_dbus_error(error->code);
                g_error_free(error);
-               return error_code;
-       }
-
-       if (IOTCON_ERROR_NONE != ret) {
-               ERR("iotcon-daemon Fail(%d)", ret);
-               return icl_dbus_convert_daemon_error(ret);
+               return ret;
        }
        resource->handle = 0;
 
        icl_dbus_unsubscribe_signal(resource->sub_id);
+       resource->sub_id = 0;
 
        return IOTCON_ERROR_NONE;
 }
 
 
-API int iotcon_resource_bind_interface(iotcon_resource_h resource, int iface)
+API int iotcon_resource_bind_interface(iotcon_resource_h resource,
+               iotcon_interface_e iface)
 {
        FN_CALL;
-       int ret, error_code;
+       int ret;
        GError *error = NULL;
 
        RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
@@ -283,9 +291,9 @@ API int iotcon_resource_bind_interface(iotcon_resource_h resource, int iface)
                        iface, &ret, NULL, &error);
        if (error) {
                ERR("ic_dbus_call_bind_interface_sync() Fail(%s)", error->message);
-               error_code = icl_dbus_convert_dbus_error(error->code);
+               ret = icl_dbus_convert_dbus_error(error->code);
                g_error_free(error);
-               return error_code;
+               return ret;
        }
 
        if (IOTCON_ERROR_NONE != ret) {
@@ -300,7 +308,7 @@ API int iotcon_resource_bind_interface(iotcon_resource_h resource, int iface)
 API int iotcon_resource_bind_type(iotcon_resource_h resource, const char *resource_type)
 {
        FN_CALL;
-       int ret, error_code;
+       int ret;
        GError *error = NULL;
 
        RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
@@ -320,9 +328,9 @@ API int iotcon_resource_bind_type(iotcon_resource_h resource, const char *resour
                        &ret, NULL, &error);
        if (error) {
                ERR("ic_dbus_call_bind_type_sync() Fail(%s)", error->message);
-               error_code = icl_dbus_convert_dbus_error(error->code);
+               ret = icl_dbus_convert_dbus_error(error->code);
                g_error_free(error);
-               return error_code;
+               return ret;
        }
 
        if (IOTCON_ERROR_NONE != ret) {
@@ -333,15 +341,15 @@ API int iotcon_resource_bind_type(iotcon_resource_h resource, const char *resour
        return ret;
 }
 
-
-API int iotcon_resource_bind_request_handler(iotcon_resource_h resource,
-               iotcon_request_handler_cb cb)
+API int iotcon_resource_set_request_handler(iotcon_resource_h resource,
+               iotcon_request_handler_cb cb, void *user_data)
 {
        RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
        RETV_IF(NULL == cb, IOTCON_ERROR_INVALID_PARAMETER);
 
-       WARN("Request handler is changed");
+       DBG("Request handler is changed");
        resource->cb = cb;
+       resource->user_data = user_data;
 
        return IOTCON_ERROR_NONE;
 }
@@ -351,7 +359,7 @@ API int iotcon_resource_bind_child_resource(iotcon_resource_h parent,
                iotcon_resource_h child)
 {
        GError *error = NULL;
-       int i, ret, error_code;
+       int i, ret;
 
        RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
        RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
@@ -380,9 +388,9 @@ API int iotcon_resource_bind_child_resource(iotcon_resource_h parent,
                                        child->handle, &ret, NULL, &error);
                        if (error) {
                                ERR("ic_dbus_call_bind_resource_sync() Fail(%s)", error->message);
-                               error_code = icl_dbus_convert_dbus_error(error->code);
+                               ret = icl_dbus_convert_dbus_error(error->code);
                                g_error_free(error);
-                               return error_code;
+                               return ret;
                        }
 
                        if (IOTCON_ERROR_NONE != ret) {
@@ -405,7 +413,7 @@ API int iotcon_resource_unbind_child_resource(iotcon_resource_h parent,
                iotcon_resource_h child)
 {
        GError *error = NULL;
-       int i, ret, error_code;
+       int i, ret;
 
        RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
        RETV_IF(NULL == parent, IOTCON_ERROR_INVALID_PARAMETER);
@@ -424,9 +432,9 @@ API int iotcon_resource_unbind_child_resource(iotcon_resource_h parent,
                        child->handle, &ret, NULL, &error);
        if (error) {
                ERR("ic_dbus_call_unbind_resource_sync() Fail(%s)", error->message);
-               error_code = icl_dbus_convert_dbus_error(error->code);
+               ret = icl_dbus_convert_dbus_error(error->code);
                g_error_free(error);
-               return error_code;
+               return ret;
        }
 
        if (IOTCON_ERROR_NONE != ret) {
@@ -512,83 +520,52 @@ API int iotcon_resource_get_interfaces(iotcon_resource_h resource, int *ifaces)
 }
 
 
-API int iotcon_resource_is_observable(iotcon_resource_h resource, bool *observable)
+API int iotcon_resource_get_properties(iotcon_resource_h resource, int *properties)
 {
        RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
-       RETV_IF(NULL == observable, IOTCON_ERROR_INVALID_PARAMETER);
+       RETV_IF(NULL == properties, IOTCON_ERROR_INVALID_PARAMETER);
 
-       *observable = resource->is_observable;
+       *properties = resource->properties;
 
        return IOTCON_ERROR_NONE;
 }
 
-
-API int iotcon_notimsg_create(iotcon_representation_h repr, int iface,
-               iotcon_notimsg_h *notimsg_handle)
+API int iotcon_resource_notify(iotcon_resource_h resource,
+               iotcon_representation_h repr, iotcon_observers_h observers)
 {
-       iotcon_notimsg_h msg;
-
-       RETV_IF(NULL == repr, IOTCON_ERROR_INVALID_PARAMETER);
-
-       msg = calloc(1, sizeof(struct icl_notify_msg));
-       if (NULL == msg) {
-               ERR("calloc() Fail(%d)", errno);
-               return IOTCON_ERROR_OUT_OF_MEMORY;
-       }
-
-       msg->repr = repr;
-       icl_representation_inc_ref_count(msg->repr);
-       msg->iface = iface;
-       msg->error_code = 200;
-
-       *notimsg_handle = msg;
-
-       return IOTCON_ERROR_NONE;
-}
-
-
-API void iotcon_notimsg_destroy(iotcon_notimsg_h msg)
-{
-       RET_IF(NULL == msg);
-
-       iotcon_representation_destroy(msg->repr);
-       free(msg);
-}
-
-
-API int iotcon_notify_list_of_observers(iotcon_resource_h resource, iotcon_notimsg_h msg,
-               iotcon_observers_h observers)
-{
-       int ret, error_code;
+       int ret;
        GError *error = NULL;
-       GVariant *noti_msg;
        GVariant *obs;
+       GVariant *repr_gvar;
 
        RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
        RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
-       RETV_IF(NULL == observers, IOTCON_ERROR_INVALID_PARAMETER);
 
        if (0 == resource->sub_id) {
                ERR("Invalid Resource handle");
                return IOTCON_ERROR_INVALID_PARAMETER;
        }
 
-       noti_msg = icl_dbus_notimsg_to_gvariant(msg);
-       if (NULL == noti_msg) {
-               ERR("icl_dbus_notimsg_to_gvariant() Fail");
-               return IOTCON_ERROR_REPRESENTATION;
+       repr_gvar = icl_dbus_representation_to_gvariant(repr);
+       if (NULL == repr_gvar) {
+               ERR("icl_representation_to_gvariant() Fail");
+               return IOTCON_ERROR_SYSTEM;
        }
-       obs = icl_dbus_observers_to_gvariant(observers);
 
-       ic_dbus_call_notify_list_of_observers_sync(icl_dbus_get_object(), resource->handle,
-                       noti_msg, obs, &ret, NULL, &error);
+       if (observers)
+               obs = icl_dbus_observers_to_gvariant(observers);
+       else
+               obs = icl_dbus_observers_to_gvariant(resource->observers);
+
+       ic_dbus_call_notify_sync(icl_dbus_get_object(), resource->handle, repr_gvar, obs,
+                       &ret, NULL, &error);
        if (error) {
-               ERR("ic_dbus_call_notify_list_of_observers_sync() Fail(%s)", error->message);
-               error_code = icl_dbus_convert_dbus_error(error->code);
+               ERR("ic_dbus_call_notify_sync() Fail(%s)", error->message);
+               ret = icl_dbus_convert_dbus_error(error->code);
                g_error_free(error);
                g_variant_unref(obs);
-               g_variant_unref(noti_msg);
-               return error_code;
+               g_variant_unref(repr_gvar);
+               return ret;
        }
 
        if (IOTCON_ERROR_NONE != ret) {
@@ -599,32 +576,3 @@ API int iotcon_notify_list_of_observers(iotcon_resource_h resource, iotcon_notim
        return IOTCON_ERROR_NONE;
 }
 
-
-API int iotcon_resource_notify_all(iotcon_resource_h resource)
-{
-       int ret, error_code;
-       GError *error = NULL;
-
-       RETV_IF(NULL == icl_dbus_get_object(), IOTCON_ERROR_DBUS);
-       RETV_IF(NULL == resource, IOTCON_ERROR_INVALID_PARAMETER);
-       if (0 == resource->sub_id) {
-               ERR("Invalid Resource handle");
-               return IOTCON_ERROR_INVALID_PARAMETER;
-       }
-
-       ic_dbus_call_notify_all_sync(icl_dbus_get_object(), resource->handle, &ret, NULL,
-                       &error);
-       if (error) {
-               ERR("ic_dbus_call_notify_all_sync() Fail(%s)", error->message);
-               error_code = icl_dbus_convert_dbus_error(error->code);
-               g_error_free(error);
-               return error_code;
-       }
-
-       if (IOTCON_ERROR_NONE != ret) {
-               ERR("iotcon-daemon Fail(%d)", ret);
-               return icl_dbus_convert_daemon_error(ret);
-       }
-
-       return IOTCON_ERROR_NONE;
-}