(ACR) Add timeout error on asynchronous APIs
authorsung.goo.kim <sung.goo.kim@samsung.com>
Wed, 21 Oct 2015 08:36:21 +0000 (17:36 +0900)
committeryoungman <yman.jung@samsung.com>
Tue, 3 Nov 2015 11:08:20 +0000 (20:08 +0900)
Change-Id: Ie6e75cfb75ff403becfd1a734462df58a6f66f24

lib/icl-dbus.c
lib/icl-dbus.h
lib/icl-device.c
lib/icl-remote-resource-crud.c
lib/icl-remote-resource.c
lib/icl.c
lib/include/iotcon-errors.h
lib/include/iotcon.h
test/crud-test-client.c
test/device-test-client.c
test/repr-test-client.c

index 1a46f89..d0cd5f8 100644 (file)
@@ -226,12 +226,32 @@ inline int icl_dbus_convert_dbus_error(int error)
 
        if (G_DBUS_ERROR_ACCESS_DENIED == error)
                ret = IOTCON_ERROR_PERMISSION_DENIED;
+       else if (G_DBUS_ERROR_TIMEOUT == error)
+               ret = IOTCON_ERROR_TIMEOUT;
        else
                ret = IOTCON_ERROR_DBUS;
 
        return ret;
 }
 
+int icl_dbus_set_timeout(int timeout_seconds)
+{
+       RETV_IF(NULL == icl_dbus_object, IOTCON_ERROR_DBUS);
+
+       g_dbus_proxy_set_default_timeout(G_DBUS_PROXY(icl_dbus_object), timeout_seconds * 1000);
+
+       return IOTCON_ERROR_NONE;
+}
+
+int icl_dbus_get_timeout()
+{
+       gint timeout = g_dbus_proxy_get_default_timeout(G_DBUS_PROXY(icl_dbus_object));
+       if (timeout <= 0) {
+               ERR("Invalid timeout (%d)", timeout);
+               return ICL_DBUS_TIMEOUT_DEFAULT;
+       }
+       return timeout/1000;
+}
 
 int icl_dbus_start()
 {
@@ -262,6 +282,9 @@ int icl_dbus_start()
                return IOTCON_ERROR_DBUS;
        }
 
+       g_dbus_proxy_set_default_timeout(G_DBUS_PROXY(icl_dbus_object),
+                       ICL_DBUS_TIMEOUT_DEFAULT * 1000);
+
        icl_dbus_count++;
        return IOTCON_ERROR_NONE;
 }
index c381943..f46f32e 100644 (file)
 
 #include "ic-dbus.h"
 
+#define ICL_DBUS_TIMEOUT_DEFAULT 10 /* 10 sec */
+#define ICL_DBUS_TIMEOUT_MAX 60 /* 60 sec */
+
+
 icDbus* icl_dbus_get_object();
 unsigned int icl_dbus_generate_signal_number();
 
@@ -32,6 +36,9 @@ int icl_dbus_remove_connection_changed_cb(iotcon_connection_changed_cb cb,
 int icl_dbus_convert_daemon_error(int error);
 int icl_dbus_convert_dbus_error(int error);
 
+int icl_dbus_set_timeout(int timeout_seconds);
+int icl_dbus_get_timeout();
+
 int icl_dbus_start();
 void icl_dbus_stop();
 
index 62c05bb..c5fc238 100644 (file)
@@ -46,12 +46,14 @@ typedef struct {
        iotcon_device_info_cb cb;
        void *user_data;
        unsigned int id;
+       int timeout_id;
 } icl_device_info_s;
 
 typedef struct {
        iotcon_platform_info_cb cb;
        void *user_data;
        unsigned int id;
+       int timeout_id;
 } icl_platform_info_s;
 
 typedef struct {
@@ -100,15 +102,38 @@ static void _icl_device_info_cb(GDBusConnection *connection,
        icl_device_info_s *cb_container = user_data;
        iotcon_device_info_cb cb = cb_container->cb;
 
+       if (cb_container->timeout_id) {
+               g_source_remove(cb_container->timeout_id);
+               cb_container->timeout_id = 0;
+       }
+
        g_variant_get(parameters, "(&s&s&s&s&s)", &uri_path, &info.device_name,
                        &info.spec_ver, &info.device_id, &info.data_model_ver);
 
        /* From iotivity, we can get uri_path. But, the value is always "/oic/d". */
 
        if (cb)
-               cb(&info, cb_container->user_data);
+               cb(&info, IOTCON_ERROR_NONE, cb_container->user_data);
 }
 
+static gboolean _icl_timeout_get_device_info(gpointer p)
+{
+       FN_CALL;
+       icl_device_info_s *cb_container = p;
+       struct icl_device_info info = {0};
+
+       if (NULL == cb_container) {
+               ERR("cb_container is NULL");
+               return G_SOURCE_REMOVE;
+       }
+
+       if (cb_container->cb)
+               cb_container->cb(&info, IOTCON_ERROR_TIMEOUT, cb_container->user_data);
+
+       icl_dbus_unsubscribe_signal(cb_container->id);
+
+       return G_SOURCE_REMOVE;
+}
 
 API int iotcon_get_device_info(const char *host_address, iotcon_device_info_cb cb,
                void *user_data)
@@ -161,6 +186,9 @@ API int iotcon_get_device_info(const char *host_address, iotcon_device_info_cb c
 
        cb_container->id = sub_id;
 
+       cb_container->timeout_id = g_timeout_add_seconds(icl_dbus_get_timeout(),
+                       _icl_timeout_get_device_info, cb_container);
+
        return ret;
 }
 
@@ -226,6 +254,11 @@ static void _icl_platform_info_cb(GDBusConnection *connection,
        icl_platform_info_s *cb_container = user_data;
        iotcon_platform_info_cb cb = cb_container->cb;
 
+       if (cb_container->timeout_id) {
+               g_source_remove(cb_container->timeout_id);
+               cb_container->timeout_id = 0;
+       }
+
        g_variant_get(parameters, "(&s&s&s&s&s&s&s&s&s&s&s&s)",
                        &uri_path,
                        &info.platform_id,
@@ -243,9 +276,27 @@ static void _icl_platform_info_cb(GDBusConnection *connection,
        /* From iotivity, we can get uri_path. But, the value is always "/oic/p". */
 
        if (cb)
-               cb(&info, cb_container->user_data);
+               cb(&info, IOTCON_ERROR_NONE, cb_container->user_data);
 }
 
+static gboolean _icl_timeout_get_platform_info(gpointer p)
+{
+       FN_CALL;
+       icl_platform_info_s *cb_container = p;
+       struct icl_platform_info info = {0};
+
+       if (NULL == cb_container) {
+               ERR("cb_container is NULL");
+               return G_SOURCE_REMOVE;
+       }
+
+       if (cb_container->cb)
+               cb_container->cb(&info, IOTCON_ERROR_TIMEOUT, cb_container->user_data);
+
+       icl_dbus_unsubscribe_signal(cb_container->id);
+
+       return G_SOURCE_REMOVE;
+}
 
 API int iotcon_get_platform_info(const char *host_address, iotcon_platform_info_cb cb,
                void *user_data)
@@ -297,6 +348,8 @@ API int iotcon_get_platform_info(const char *host_address, iotcon_platform_info_
        }
 
        cb_container->id = sub_id;
+       cb_container->timeout_id = g_timeout_add_seconds(icl_dbus_get_timeout(),
+                       _icl_timeout_get_platform_info, cb_container);
 
        return ret;
 }
@@ -317,8 +370,11 @@ static void _icl_tizen_info_cb(GObject *object, GAsyncResult *g_async_res,
        ic_dbus_call_get_tizen_info_finish(IC_DBUS(object), &result, g_async_res, &error);
        if (error) {
                ERR("ic_dbus_call_get_tizen_info_finish() Fail(%s)", error->message);
+               if (cb) {
+                       int ret = icl_dbus_convert_dbus_error(error->code);
+                       cb(&info, ret, cb_container->user_data);
+               }
                g_error_free(error);
-               cb(&info, IOTCON_ERROR_DBUS, cb_container->user_data);
                /* TODO contain time out error */
                free(cb_container);
                return;
index 6daaab8..4399607 100644 (file)
@@ -138,6 +138,11 @@ static void _icl_on_get_cb(GObject *object, GAsyncResult *g_async_res,
        ic_dbus_call_get_finish(IC_DBUS(object), &result, g_async_res, &error);
        if (error) {
                ERR("ic_dbus_call_get_finish() Fail(%s)", error->message);
+               if (cb_container->cb) {
+                       int ret = icl_dbus_convert_dbus_error(error->code);
+                       cb_container->cb(cb_container->resource, NULL, NULL, ret,
+                                       cb_container->user_data);
+               }
                g_error_free(error);
                free(cb_container);
                return;
@@ -157,6 +162,11 @@ static void _icl_on_put_cb(GObject *object, GAsyncResult *g_async_res,
        ic_dbus_call_put_finish(IC_DBUS(object), &result, g_async_res, &error);
        if (error) {
                ERR("ic_dbus_call_put_finish() Fail(%s)", error->message);
+               if (cb_container->cb) {
+                       int ret = icl_dbus_convert_dbus_error(error->code);
+                       cb_container->cb(cb_container->resource, NULL, NULL, ret,
+                                       cb_container->user_data);
+               }
                g_error_free(error);
                free(cb_container);
                return;
@@ -176,6 +186,11 @@ static void _icl_on_post_cb(GObject *object, GAsyncResult *g_async_res,
        ic_dbus_call_post_finish(IC_DBUS(object), &result, g_async_res, &error);
        if (error) {
                ERR("ic_dbus_call_post_finish() Fail(%s)", error->message);
+               if (cb_container->cb) {
+                       int ret = icl_dbus_convert_dbus_error(error->code);
+                       cb_container->cb(cb_container->resource, NULL, NULL, ret,
+                                       cb_container->user_data);
+               }
                g_error_free(error);
                free(cb_container);
                return;
@@ -327,6 +342,10 @@ static void _icl_on_delete_cb(GObject *object, GAsyncResult *g_async_res,
        ic_dbus_call_delete_finish(IC_DBUS(object), &result, g_async_res, &error);
        if (error) {
                ERR("ic_dbus_call_delete_finish() Fail(%s)", error->message);
+               if (cb_container->cb) {
+                       ret = icl_dbus_convert_dbus_error(error->code);
+                       cb_container->cb(cb_container->resource, NULL, ret, cb_container->user_data);
+               }
                g_error_free(error);
                free(cb_container);
                return;
index 4b7c68e..6f17a76 100644 (file)
@@ -34,6 +34,7 @@ typedef struct {
        iotcon_found_resource_cb cb;
        void *user_data;
        unsigned int id;
+       int timeout_id;
 } icl_found_resource_s;
 
 static iotcon_remote_resource_h _icl_remote_resource_from_gvariant(GVariant *payload,
@@ -55,6 +56,11 @@ static void _icl_found_resource_cb(GDBusConnection *connection,
        icl_found_resource_s *cb_container = user_data;
        iotcon_found_resource_cb cb = cb_container->cb;
 
+       if (cb_container->timeout_id) {
+               g_source_remove(cb_container->timeout_id);
+               cb_container->timeout_id = 0;
+       }
+
        g_variant_get(parameters, "(vi)", &payload, &conn_type);
 
        resource = _icl_remote_resource_from_gvariant(payload, conn_type);
@@ -64,7 +70,7 @@ static void _icl_found_resource_cb(GDBusConnection *connection,
        }
 
        if (cb)
-               cb(resource, cb_container->user_data);
+               cb(resource, IOTCON_ERROR_NONE, cb_container->user_data);
 
        iotcon_remote_resource_destroy(resource);
 
@@ -73,6 +79,23 @@ static void _icl_found_resource_cb(GDBusConnection *connection,
         */
 }
 
+static gboolean _icl_timeout_find_resource(gpointer p)
+{
+       icl_found_resource_s *cb_container = p;
+
+       if (NULL == cb_container) {
+               ERR("cb_container is NULL");
+               return G_SOURCE_REMOVE;
+       }
+
+       if (cb_container->cb)
+               cb_container->cb(NULL, IOTCON_ERROR_TIMEOUT, cb_container->user_data);
+
+       icl_dbus_unsubscribe_signal(cb_container->id);
+
+       return G_SOURCE_REMOVE;
+}
+
 
 /* The length of resource_type should be less than or equal to 61.
  * If resource_type is NULL, then All resources in host are discovered. */
@@ -130,6 +153,9 @@ API int iotcon_find_resource(const char *host_address, const char *resource_type
 
        cb_container->id = sub_id;
 
+       cb_container->timeout_id = g_timeout_add_seconds(icl_dbus_get_timeout(),
+                       _icl_timeout_find_resource, cb_container);
+
        return ret;
 }
 
index 3d9f835..61618e9 100644 (file)
--- a/lib/icl.c
+++ b/lib/icl.c
@@ -39,3 +39,19 @@ API void iotcon_close(void)
 {
        icl_dbus_stop();
 }
+
+API int iotcon_set_timeout(int timeout_seconds)
+{
+       int ret;
+
+       if (ICL_DBUS_TIMEOUT_MAX < timeout_seconds || timeout_seconds <= 0) {
+               ERR("Invalid seconds (%d)", timeout_seconds);
+               return IOTCON_ERROR_INVALID_PARAMETER;
+       }
+
+       ret = icl_dbus_set_timeout(timeout_seconds);
+       if (IOTCON_ERROR_NONE != ret)
+               ERR("icl_dbus_set_timeout() Fail(%d)", ret);
+
+       return ret;
+}
index dcafea4..d91e24a 100644 (file)
@@ -36,6 +36,7 @@ typedef enum
        IOTCON_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */
        IOTCON_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
        IOTCON_ERROR_NO_DATA = TIZEN_ERROR_NO_DATA, /**< No data available */
+       IOTCON_ERROR_TIMEOUT = TIZEN_ERROR_TIMED_OUT, /**< Time out */
        IOTCON_ERROR_IOTIVITY = TIZEN_ERROR_IOTCON | 0x01, /**< Iotivity errors */
        IOTCON_ERROR_REPRESENTATION = TIZEN_ERROR_IOTCON | 0x02, /**< Representation errors */
        IOTCON_ERROR_INVALID_TYPE = TIZEN_ERROR_IOTCON | 0x03, /**< Invalid type */
index 637ea88..49f7f93 100644 (file)
@@ -69,6 +69,33 @@ int iotcon_open(void);
  */
 void iotcon_close(void);
 
+
+/**
+ * @brief Set timeout of asynchronize APIs.
+ * @details Default timeout is 10 seconds.
+ * Maximum timeout is 60 seconds.
+ *
+ * @since_tizen 3.0
+ *
+ * @param[in] timeout_secods Seconds for timeout
+ *
+ * @return  0 on success, otherwise a negative error value.
+ * @retval  #IOTCON_ERROR_NONE Successful
+ * @retval  #IOTCON_ERROR_DBUS Dbus error
+ *
+ * @pre iotcon_open() should be called to open a connection to the iotcon.
+ *
+ * @see iotcon_get_device_info()
+ * @see iotcon_get_platform_info()
+ * @see iotcon_get_tizen_info()
+ * @see iotcon_find_resource()
+ * @see iotcon_remote_resource_get()
+ * @see iotcon_remote_resource_put()
+ * @see iotcon_remote_resource_post()
+ * @see iotcon_remote_resource_delete()
+ */
+int iotcon_set_timeout(int timeout_seconds);
+
 /**
  * @brief Specifies the type of function passed to iotcon_add_connection_changed_cb() and
  * iotcon_remove_connection_changed_cb().
@@ -378,6 +405,7 @@ int iotcon_resource_unbind_child_resource(iotcon_resource_h parent,
  * @since_tizen 3.0
  *
  * @param[in] device_info the device information from remote server.
+ * @param[in] result The result code (0 on success, other wise a negative error value)
  * @param[in] user_data The user data to pass to the function
  *
  * @pre iotcon_get_device_info() will invoke this callback function.
@@ -385,7 +413,8 @@ int iotcon_resource_unbind_child_resource(iotcon_resource_h parent,
  * @see iotcon_get_device_info()
  * @see iotcon_device_info_get_property()
  */
-typedef void (*iotcon_device_info_cb)(iotcon_device_info_h device_info, void *user_data);
+typedef void (*iotcon_device_info_cb)(iotcon_device_info_h device_info, int result,
+               void *user_data);
 
 /**
  * @brief Calls a function for device information of remote server.
@@ -422,6 +451,7 @@ int iotcon_get_device_info(const char *host_address, iotcon_device_info_cb cb,
  * @since_tizen 3.0
  *
  * @param[in] platform_info The platform information from remote server.
+ * @param[in] result The result code (0 on success, other wise a negative error value)
  * @param[in] user_data The user data to pass to the function
  *
  * @pre iotcon_get_platform_info() will invoke this callback function.
@@ -429,7 +459,7 @@ int iotcon_get_device_info(const char *host_address, iotcon_device_info_cb cb,
  * @see iotcon_get_platform_info()
  * @see iotcon_platform_info_get_property()
  */
-typedef void (*iotcon_platform_info_cb)(iotcon_platform_info_h platform_info,
+typedef void (*iotcon_platform_info_cb)(iotcon_platform_info_h platform_info, int result,
                void *user_data);
 
 /**
@@ -469,7 +499,7 @@ int iotcon_get_platform_info(const char *host_address, iotcon_platform_info_cb c
  * @since_tizen 3.0
  *
  * @param[in] tizen_info The information of tizen device from remote server.
- * @param[in] response_result The response result code
+ * @param[in] response_result The response result code (Lesser than 0 on fail, otherwise a response result value)
  * @param[in] user_data The user data to pass to the function
  *
  * @pre iotcon_get_tizen_info() will invoke this callback function.
@@ -592,13 +622,14 @@ int iotcon_unsubscribe_presence(iotcon_presence_h presence_handle);
  * @since_tizen 3.0
  *
  * @param[in] resource The handle of resource which is found
+ * @param[in] result The result code (Lesser than 0 on fail, otherwise a response result value)
  * @param[in] user_data The user data to pass to the function
  *
  * @pre The callback must be registered using iotcon_find_resource()
  *
  * @see iotcon_find_resource()
  */
-typedef void (*iotcon_found_resource_cb)(iotcon_remote_resource_h resource, void *user_data);
+typedef void (*iotcon_found_resource_cb)(iotcon_remote_resource_h resource, int result, void *user_data);
 
 /**
  * @brief Finds resources.
@@ -875,7 +906,7 @@ int iotcon_resource_notify(iotcon_resource_h resource, iotcon_notimsg_h msg,
  * @param[in] resource The handle of the resource
  * @param[in] repr The handle of the representation
  * @param[in] options The handle of the header options
- * @param[in] response_result The response result code
+ * @param[in] response_result The response result code (Lesser than 0 on fail, otherwise a response result value)
  * @param[in] user_data The user data to pass to the function
  *
  * @pre The callback must be registered using iotcon_remote_resource_get(), iotcon_remote_resource_put(), iotcon_remote_resource_post()
index d3ad77c..fa9b02c 100644 (file)
@@ -274,7 +274,7 @@ static void _get_tizen_info(iotcon_tizen_info_h info, int response_result,
        INFO("- Tizen Device ID : %s", tizen_device_id);
 }
 
-static void _found_resource(iotcon_remote_resource_h resource, void *user_data)
+static void _found_resource(iotcon_remote_resource_h resource, int result, void *user_data)
 {
        GList *node;
        char *resource_host;
@@ -285,6 +285,8 @@ static void _found_resource(iotcon_remote_resource_h resource, void *user_data)
        iotcon_resource_types_h resource_types;
        iotcon_remote_resource_h resource_clone = NULL;
 
+       RETM_IF(IOTCON_ERROR_NONE != result, "Invalid result(%d)", result);
+
        if (NULL == resource)
                return;
 
index 2a358ca..88d3fc8 100644 (file)
@@ -18,7 +18,7 @@
 #include <iotcon.h>
 #include "test.h"
 
-static void _get_device_info(iotcon_device_info_h info, void *user_data)
+static void _get_device_info(iotcon_device_info_h info, int result, void *user_data)
 {
        int ret;
        char *device_name = NULL;
@@ -26,6 +26,8 @@ static void _get_device_info(iotcon_device_info_h info, void *user_data)
        char *device_id = NULL;
        char *data_model_ver = NULL;
 
+       RETM_IF(IOTCON_ERROR_NONE != result, "Invalid result (%d)", result);
+
        ret = iotcon_device_info_get_property(info, IOTCON_DEVICE_INFO_NAME, &device_name);
        if (IOTCON_ERROR_NONE != ret) {
                ERR("iotcon_device_info_get_property() Fail(%d)", ret);
@@ -58,7 +60,7 @@ static void _get_device_info(iotcon_device_info_h info, void *user_data)
        INFO("data_model_version : %s", data_model_ver);
 }
 
-static void _get_platform_info(iotcon_platform_info_h info, void *user_data)
+static void _get_platform_info(iotcon_platform_info_h info, int result, void *user_data)
 {
        int ret;
        char *platform_id = NULL;
@@ -73,6 +75,8 @@ static void _get_platform_info(iotcon_platform_info_h info, void *user_data)
        char *support_url = NULL;
        char *system_time = NULL;
 
+       RETM_IF(IOTCON_ERROR_NONE != result, "Invalid result (%d)", result);
+
        ret = iotcon_platform_info_get_property(info, IOTCON_PLATFORM_INFO_ID, &platform_id);
        if (IOTCON_ERROR_NONE != ret) {
                ERR("iotcon_platform_info_get_property() Fail(%d)", ret);
index 4616a7a..01dced5 100644 (file)
@@ -215,7 +215,7 @@ static int _device_id_compare(const void *a, const void *b)
        return strcmp(a, b);
 }
 
-static void _found_resource(iotcon_remote_resource_h resource, void *user_data)
+static void _found_resource(iotcon_remote_resource_h resource, int result, void *user_data)
 {
        GList *node;
        char *resource_host;
@@ -224,6 +224,8 @@ static void _found_resource(iotcon_remote_resource_h resource, void *user_data)
        int ret, resource_interfaces;
        iotcon_resource_types_h resource_types;
 
+       RETM_IF(IOTCON_ERROR_NONE != result, "Invalid result(%d)", result);
+
        if (NULL == resource)
                return;