Revise whole event callback management code
authorSung-jae Park <nicesj.park@samsung.com>
Wed, 1 Aug 2012 07:55:43 +0000 (16:55 +0900)
committerSung-jae Park <nicesj.park@samsung.com>
Wed, 1 Aug 2012 12:09:51 +0000 (21:09 +0900)
Change-Id: Ib21f68650297a5e959b061708f386482116eecb2

debian/changelog
include/livebox.h
include/livebox_internal.h
packaging/liblivebox-viewer.spec
src/client.c
src/fb.c
src/livebox.c

index edb8ccf..6be5eda 100644 (file)
@@ -1,3 +1,10 @@
+livebox-viewer (0.3.10) unstable; urgency=low
+
+  * Git: slp/pkgs/l/livebox-viewer
+  * Tag: livebox-viewer_0.3.10
+
+ -- Sung-jae Park <nicesj.park@samsung.com>  Wed, 01 Aug 2012 20:55:55 +0900
+
 livebox-viewer (0.3.9) unstable; urgency=low
 
   * Git: slp/pkgs/l/livebox-viewer
index 59f97cb..c5384a7 100644 (file)
@@ -117,9 +117,14 @@ extern int livebox_del(struct livebox *handler, ret_cb_t cb, void *data);
  * \note event list
  *     "lb,updated" - Contents of the given livebox is updated.
  *     "pd,updated" - Contents of the given pd is updated.
+ *
  *     "lb,created" - A new livebox is created
  *     "lb,deleted" - Given livebox is deleted
+ *
+ *     "group,changed" - Group(cluster/sub-cluster) information is changed
  *     "pinup,changed" - Pinup status is changed
+ *     "period,changed" - Update period is changed
+ *
  * \brief Set a livebox events callback
  * \param[in] cb
  * \param[in] data
index c896866..27bb8e3 100644 (file)
@@ -24,7 +24,7 @@ extern int lb_text_pd(struct livebox *handler);
 extern void lb_set_period(struct livebox *handler, double period);
 extern struct livebox *lb_ref(struct livebox *handler);
 extern struct livebox *lb_unref(struct livebox *handler);
-extern int lb_send_delete(struct livebox *handler);
+extern int lb_send_delete(struct livebox *handler, ret_cb_t cb, void *data);
 extern int lb_delete_all(void);
 
 enum lb_type { /*!< Must have to be sync with data-provider-master */
@@ -47,6 +47,7 @@ struct livebox {
        enum {
                CREATE = 0xBEEFbeef,
                DELETE = 0xDEADdead, /* Delete only for this client */
+               DESTROYED = 0x00DEAD00,
        } state;
 
        char *cluster;
@@ -97,13 +98,18 @@ struct livebox {
 
        ret_cb_t created_cb;
        void *created_cbdata;
-       int is_created;
 
        ret_cb_t deleted_cb;
        void *deleted_cbdata;
 
        ret_cb_t pinup_cb;
        void *pinup_cbdata;
+
+       ret_cb_t group_changed_cb;
+       void *group_cbdata;
+
+       ret_cb_t period_changed_cb;
+       void *period_cbdata;
 };
 
 /* End of a file */
index 742c754..08f0230 100644 (file)
@@ -1,6 +1,6 @@
 Name: liblivebox-viewer
 Summary: Library for the development of a livebox viewer
-Version: 0.3.9
+Version: 0.3.10
 Release: 1
 Group: main/app
 License: Samsung Proprietary License
index 7d592a6..ed4990f 100644 (file)
@@ -20,6 +20,7 @@
 #include "util.h"
 #include "master_rpc.h"
 #include "conf.h"
+#include "critical_log.h"
 
 static inline void make_connection(void);
 
@@ -80,19 +81,20 @@ static struct packet *master_pinup(pid_t pid, int handle, const struct packet *p
 
        if (ret == 0) {
                new_content = strdup(content);
-               if (!new_content) {
+               if (new_content) {
+                       free(handler->content);
+                       handler->content = new_content;
+                       handler->lb.is_pinned_up = pinup;
+               } else {
                        ret = -ENOMEM;
-                       goto out;
                }
-
-               free(handler->content);
-               handler->content = new_content;
-               handler->lb.is_pinned_up = pinup;
        }
 
        if (handler->pinup_cb) {
                handler->pinup_cb(handler, ret, handler->pinup_cbdata);
+
                handler->pinup_cb = NULL; /*!< Reset pinup cb */
+               handler->pinup_cbdata = NULL;
        } else {
                lb_invoke_event_handler(handler, "lb,pinup");
        }
@@ -102,6 +104,7 @@ out:
        result = packet_create_reply(packet, "i", ret);
        if (!result)
                ErrPrint("Failed to create a reply packet\n");
+
        return result;
 }
 
@@ -131,24 +134,62 @@ static struct packet *master_deleted(pid_t pid, int handle, const struct packet
                goto out;
        }
 
-       DbgPrint("[%p] %s(%s) is deleted\n", handler, pkgname, id);
-       if (!handler->is_created) {
-               if (handler->created_cb)
-                       handler->created_cb(handler, -EFAULT, handler->created_cbdata);
-       } else if (handler->state == CREATE) {
-               lb_invoke_event_handler(handler, "lb,deleted");
+       /*!< Check validity of this "handler" */
+       if (handler->state != CREATE) {
+               if (handler->state != DELETE) {
+                       /*!
+                        * \note
+                        * This is not possible
+                        */
+                       CRITICAL_LOG("Already deleted handler (%s - %s)\n", pkgname, id);
+                       return NULL;
+               }
+       }
+
+       if (!handler->id) {
+               /*!
+                * \note
+                * This is not possible,
+                * master_deleted can only be called after creating an instance.
+                */
+               CRITICAL_LOG("Livebox is not created yet (%s - %s)\n", pkgname, id);
+               return NULL;
+       }
+
+       ret = 0;
+
+       if (handler->created_cb == handler->deleted_cb) {
+               if (handler->created_cbdata != handler->deleted_cbdata)
+                       CRITICAL_LOG("cb is same but cbdata is different (%s - %s)\n", pkgname, id);
+
+               DbgPrint("Call the created cb with -ECANCELED\n");
+               handler->created_cb(handler, -ECANCELED, handler->created_cbdata);
+
+               handler->created_cb = NULL;
+               handler->created_cbdata = NULL;
+               handler->deleted_cb = NULL;
+               handler->deleted_cbdata = NULL;
        } else if (handler->deleted_cb) {
-               handler->deleted_cb(handler, 0, handler->deleted_cbdata);
+               DbgPrint("Call the deleted cb\n");
+               handler->deleted_cb(handler, ret, handler->deleted_cbdata);
+
+               handler->deleted_cb = NULL;
+               handler->deleted_cbdata = NULL;
+       } else {
+               DbgPrint("Call the lb,deleted\n");
+               lb_invoke_event_handler(handler, "lb,deleted");
        }
 
+       DbgPrint("[%p] %s(%s) is deleted\n", handler, pkgname, id);
+
        /* Just try to delete it, if a user didn't remove it from the live box list */
        lb_unref(handler);
-       ret = 0;
 
 out:
        result = packet_create_reply(packet, "i", ret);
        if (!result)
                ErrPrint("Failed to create a reply packet\n");
+
        return result;
 }
 
@@ -286,6 +327,113 @@ out:
        return result;
 }
 
+static struct packet *master_period_changed(pid_t pid, int handle, const struct packet *packet)
+{
+       struct livebox *handler;
+       const char *pkgname;
+       const char *id;
+       int ret;
+       double period;
+       int status;
+       struct packet *result;
+
+       ret = packet_get(packet, "idss", &status, &period, &pkgname, &id);
+       if (ret != 4) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       handler = lb_find_livebox(pkgname, id);
+       if (!handler) {
+               ErrPrint("Livebox(%s - %s) is not found\n", pkgname, id);
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (handler->state != CREATE) {
+               ret = -EPERM;
+               goto out;
+       }
+
+       if (status == 0)
+               lb_set_period(handler, period);
+
+       if (handler->period_changed_cb) {
+               handler->period_changed_cb(handler, status, handler->group_cbdata);
+
+               handler->period_changed_cb = NULL;
+               handler->period_cbdata = NULL;
+       } else {
+               lb_invoke_event_handler(handler, "period,changed");
+       }
+
+       ret = 0;
+
+out:
+       result = packet_create_reply(packet, "i", ret);
+       if (!result)
+               ErrPrint("Failed to create a reply packet\n");
+
+       return result;
+}
+
+static struct packet *master_group_changed(pid_t pid, int handle, const struct packet *packet)
+{
+       struct livebox *handler;
+       const char *pkgname;
+       const char *id;
+       int ret;
+       const char *cluster;
+       const char *category;
+       int status;
+       struct packet *result;
+
+       ret = packet_get(packet, "ssiss", &pkgname, &id, &status, &cluster, &category);
+       if (ret != 5) {
+               ErrPrint("Invalid argument\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       handler = lb_find_livebox(pkgname, id);
+       if (!handler) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (handler->state != CREATE) {
+               /*!
+                * \note
+                * Do no access this handler,
+                * You cannot believe this handler anymore.
+                */
+               ret = -EPERM;
+               goto out;
+       }
+
+       if (status == 0)
+               lb_set_group(handler, cluster, category);
+
+       if (handler->group_changed_cb) {
+               handler->group_changed_cb(handler, status, handler->group_cbdata);
+
+               handler->group_changed_cb = NULL;
+               handler->group_cbdata = NULL;
+       } else {
+               lb_invoke_event_handler(handler, "group,changed");
+       }
+
+       ret = 0;
+
+out:
+       result = packet_create_reply(packet, "i", ret);
+       if (!result)
+               ErrPrint("Failed to create a reply packet\n");
+
+       return result;
+}
+
 static struct packet *master_created(pid_t pid, int handle, const struct packet *packet)
 {
        struct livebox *handler;
@@ -314,6 +462,8 @@ static struct packet *master_created(pid_t pid, int handle, const struct packet
        double period;
        struct packet *result;
 
+       int old_state = DESTROYED;
+
        int ret;
 
        ret = packet_get(packet, "dsssiiiissssidiiiiid",
@@ -348,8 +498,30 @@ static struct packet *master_created(pid_t pid, int handle, const struct packet
                        ret = -EFAULT;
                        goto out;
                }
+
+               old_state = handler->state;
        } else {
-               if (handler->is_created == 1) {
+               if (handler->state != CREATE) {
+                       if (handler->state != DELETE) {
+                               /*!
+                                * \note
+                                * This is not possible!!!
+                                */
+                               ErrPrint("Invalid handler\n");
+                               ret = -EINVAL;
+                               goto out;
+                       }
+
+                       /*!
+                        * \note
+                        * After get the delete states,
+                        * call the create callback with deleted result.
+                        */
+               }
+
+               old_state = handler->state;
+
+               if (handler->id) {
                        ErrPrint("Already created: timestamp[%lf] "
                                "pkgname[%s], id[%s] content[%s] "
                                "cluster[%s] category[%s] lb_fname[%s] pd_fname[%s]\n",
@@ -357,17 +529,11 @@ static struct packet *master_created(pid_t pid, int handle, const struct packet
                                        content, cluster, category,
                                        lb_fname, pd_fname);
 
-                       ret = 0;
+                       ret = -EALREADY;
                        goto out;
                }
 
                lb_set_id(handler, id);
-
-               if (handler->state != CREATE) {
-                       lb_send_delete(handler);
-                       ret = 0;
-                       goto out;
-               }
        }
 
        lb_set_size(handler, lb_w, lb_h);
@@ -426,15 +592,44 @@ static struct packet *master_created(pid_t pid, int handle, const struct packet
 
        lb_set_period(handler, period);
 
-       if (handler->created_cb)
-               handler->created_cb(handler, 0, handler->created_cbdata);
-       else
-               lb_invoke_event_handler(handler, "lb,created");
-
-       handler->is_created = 1;
        ret = 0;
 
+       if (handler->state == CREATE) {
+               /*!
+                * \note
+                * These callback can change the handler->state.
+                * So we have to use the "old_state" which stored state before call these callbacks
+                */
+
+               if (handler->created_cb) {
+                       DbgPrint("Invoke the created_cb\n");
+                       handler->created_cb(handler, ret, handler->created_cbdata);
+
+                       handler->created_cb = NULL;
+                       handler->created_cbdata = NULL;
+               } else {
+                       DbgPrint("Invoke the lb,created\n");
+                       lb_invoke_event_handler(handler, "lb,created");
+               }
+       }
+
 out:
+       if (ret == 0 && old_state == DELETE) {
+               DbgPrint("Send the delete request\n");
+               lb_send_delete(handler, handler->created_cb, handler->created_cbdata);
+
+               /*!
+                * \note
+                * handler->created_cb = NULL;
+                * handler->created_cbdata = NULL;
+                *
+                * Do not clear this to use this from the deleted event callback.
+                * if this value is not cleared when the deleted event callback check it,
+                * it means that the created function is not called yet.
+                * Then the call the deleted event callback with -ECANCELED errno.
+                */
+       }
+
        result = packet_create_reply(packet, "i", ret);
        if (!result)
                ErrPrint("Failed to create a reply packet\n");
@@ -463,6 +658,14 @@ static struct method s_table[] = {
                .handler = master_created,
        },
        {
+               .cmd = "group_changed",
+               .handler = master_group_changed,
+       },
+       {
+               .cmd = "period_changed",
+               .handler = master_period_changed,
+       },
+       {
                .cmd = "pinup",
                .handler = master_pinup,
        },
index 6b80ba7..32a5123 100644 (file)
--- a/src/fb.c
+++ b/src/fb.c
@@ -273,8 +273,10 @@ int fb_release_buffer(void *data)
 {
        struct buffer *buffer;
 
-       if (!data)
+       if (!data) {
+               DbgPrint("Here?\n");
                return 0;
+       }
 
        buffer = container_of(data, struct buffer, data);
 
index 622289d..93ac3f3 100644 (file)
@@ -51,6 +51,31 @@ struct fault_info {
        void *user_data;
 };
 
+static inline void default_create_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default created event handler: %d\n", ret);
+}
+
+static inline void default_delete_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default deleted event handler: %d\n", ret);
+}
+
+static inline void default_pinup_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default pinup event handler: %d\n", ret);
+}
+
+static inline void default_group_changed_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default group changed event handler: %d\n", ret);
+}
+
+static inline void default_period_changed_cb(struct livebox *handler, int ret, void *data)
+{
+       DbgPrint("Default period changed event handler: %d\n", ret);
+}
+
 static inline struct cb_info *create_cb_info(ret_cb_t cb, void *data)
 {
        struct cb_info *info;
@@ -125,6 +150,16 @@ static void resize_cb(struct livebox *handler, const struct packet *result, void
                ret = -EINVAL;
        }
 
+       /*!
+        * \note
+        * In case of resize request,
+        * The livebox handler will not have resized value right after this callback,
+        * It can only get the new size when it makes updates.
+        *
+        * So the user can only get the resized value(result) from the first update event
+        * after this request.
+        */
+
        if (cb)
                cb(handler, ret, cbdata);
 }
@@ -165,15 +200,16 @@ static void text_signal_cb(struct livebox *handler, const struct packet *result,
        return;
 }
 
-static void set_group_cb(struct livebox *handler, const struct packet *result, void *data)
+static void set_group_ret_cb(struct livebox *handler, const struct packet *result, void *data)
 {
        int ret;
        void *cbdata;
-       struct cb_info *info = data;
        ret_cb_t cb;
+       struct cb_info *info = data;
 
        cbdata = info->data;
        cb = info->cb;
+       destroy_cb_info(info);
 
        if (!result) {
                ret = -EFAULT;
@@ -182,15 +218,19 @@ static void set_group_cb(struct livebox *handler, const struct packet *result, v
                ret = -EINVAL;
        }
 
-       if (cb)
+       if (ret == 0) { /*!< Group information is successfully changed */
+               handler->group_changed_cb = cb;
+               handler->group_cbdata = cbdata;
+       } else if (cb) {
                cb(handler, ret, cbdata);
+       }
+
        return;
 }
 
 static void period_ret_cb(struct livebox *handler, const struct packet *result, void *data)
 {
        struct cb_info *info = data;
-       double period;
        int ret;
        ret_cb_t cb;
        void *cbdata;
@@ -201,30 +241,45 @@ static void period_ret_cb(struct livebox *handler, const struct packet *result,
 
        if (!result) {
                ret = -EFAULT;
-       } else if (packet_get(result, "id", &ret, &period) != 2) {
+       } else if (packet_get(result, "i", &ret) != 1) {
                ErrPrint("Invalid argument\n");
                ret = -EINVAL;
        }
 
-       if (ret == 0)
-               lb_set_period(handler, period);
-
-       if (cb)
+       if (ret == 0) {
+               handler->period_changed_cb = cb;
+               handler->period_cbdata = cbdata;
+       } else if (cb) {
                cb(handler, ret, cbdata);
+       }
 }
 
 static void del_ret_cb(struct livebox *handler, const struct packet *result, void *data)
 {
+       struct cb_info *info = data;
        int ret;
+       ret_cb_t cb;
+       void *cbdata;
+
+       cb = info->cb;
+       cbdata = info->data;
+       destroy_cb_info(info);
 
        if (!result) {
+               ErrPrint("Connection lost?\n");
                ret = -EFAULT;
        } else if (packet_get(result, "i", &ret) != 1) {
                ErrPrint("Invalid argument\n");
                ret = -EINVAL;
        }
 
-       DbgPrint("Returns %d (waiting deleted event)\n", ret);
+       if (ret == 0) {
+               DbgPrint("Returns %d (waiting deleted event)\n", ret);
+               handler->deleted_cb = cb;
+               handler->deleted_cbdata = cbdata;
+       } else if (cb) {
+               cb(handler, ret, cbdata);
+       }
 
        /*!
         * \note
@@ -419,9 +474,8 @@ static void delete_category_cb(struct livebox *handler, const struct packet *res
 
        if (!result) {
                ret = -EFAULT;
-       } else {
-               if (packet_get(result, "i", &ret) != 1)
-                       ret = -EINVAL;
+       } else if (packet_get(result, "i", &ret) != 1) {
+               ret = -EINVAL;
        }
 
        DbgPrint("Delete category returns: %d\n", ret);
@@ -443,10 +497,8 @@ static void pinup_done_cb(struct livebox *handler, const struct packet *result,
 
        if (!result) {
                ret = -EFAULT;
-       } else {
-               if (packet_get(result, "i", &ret) != 1) {
-                       ret = -EINVAL;
-               }
+       } else if (packet_get(result, "i", &ret) != 1) {
+               ret = -EINVAL;
        }
 
        if (ret == 0) {
@@ -548,6 +600,9 @@ EAPI struct livebox *livebox_add(const char *pkgname, const char *content, const
                return NULL;
        }
 
+       if (!cb)
+               cb = default_create_cb;
+
        /* Data provider will set this */
        handler->lb.type = _LB_TYPE_FILE;
        handler->pd.type = _PD_TYPE_SCRIPT;
@@ -558,7 +613,6 @@ EAPI struct livebox *livebox_add(const char *pkgname, const char *content, const
 
        handler->timestamp = util_timestamp();
        handler->is_user = 1;
-       handler->is_created = 0;
 
        s_info.livebox_list = dlist_append(s_info.livebox_list, handler);
 
@@ -614,8 +668,13 @@ EAPI int livebox_set_period(struct livebox *handler, double period, ret_cb_t cb,
        }
 
        packet = packet_create("set_period", "ssd", handler->pkgname, handler->id, period);
-       if (!packet)
+       if (!packet) {
+               ErrPrint("Failed to build a packet %s\n", handler->pkgname);
                return -EFAULT;
+       }
+
+       if (!cb)
+               cb = default_period_changed_cb;
 
        return master_rpc_async_request(handler, packet, 0, period_ret_cb, create_cb_info(cb, data));
 }
@@ -633,8 +692,6 @@ EAPI int livebox_del(struct livebox *handler, ret_cb_t cb, void *data)
        }
 
        handler->state = DELETE;
-       handler->deleted_cb = cb;
-       handler->deleted_cbdata = data;
 
        if (!handler->id) {
                /*!
@@ -643,11 +700,18 @@ EAPI int livebox_del(struct livebox *handler, ret_cb_t cb, void *data)
                 * It means a user didn't receive created event yet.
                 * Then just stop to delete procedure from here.
                 * Because the "created" event handler will release this.
+                * By the way, if the user adds any callback for getting return status of this,
+                * call it at here.
                 */
+               if (cb)
+                       cb(handler, 0, data);
                return 0;
        }
 
-       return lb_send_delete(handler);
+       if (!cb)
+               cb = default_delete_cb;
+
+       return lb_send_delete(handler, cb, data);
 }
 
 EAPI int livebox_fault_handler_set(int (*cb)(const char *, const char *, const char *, const char *, void *), void *data)
@@ -1113,13 +1177,21 @@ EAPI int livebox_set_group(struct livebox *handler, const char *cluster, const c
                return -EINVAL;
        }
 
+       if (!strcmp(handler->cluster, cluster) && !strcmp(handler->category, category)) {
+               DbgPrint("No changes\n");
+               return -EALREADY;
+       }
+
        packet = packet_create("change_group", "ssss", handler->pkgname, handler->id, cluster, category);
        if (!packet) {
                ErrPrint("Failed to build a param\n");
                return -EFAULT;
        }
 
-       return master_rpc_async_request(handler, packet, 0, set_group_cb, create_cb_info(cb, data));
+       if (!cb)
+               cb = default_group_changed_cb;
+
+       return master_rpc_async_request(handler, packet, 0, set_group_ret_cb, create_cb_info(cb, data));
 }
 
 EAPI int livebox_get_group(struct livebox *handler, char ** const cluster, char ** const category)
@@ -1328,6 +1400,7 @@ EAPI void *livebox_acquire_fb(struct livebox *handler)
 
 EAPI int livebox_release_fb(void *buffer)
 {
+       DbgPrint("Release buffer: %p\n", buffer);
        return fb_release_buffer(buffer);
 }
 
@@ -1420,8 +1493,10 @@ EAPI int livebox_set_pinup(struct livebox *handler, int flag, ret_cb_t cb, void
                return -EINVAL;
        }
 
-       if (handler->lb.is_pinned_up == flag)
-               return 0;
+       if (handler->lb.is_pinned_up == flag) {
+               DbgPrint("No changes\n");
+               return -EALREADY;
+       }
 
        packet = packet_create("pinup_changed", "ssi", handler->pkgname, handler->id, flag);
        if (!packet) {
@@ -1429,6 +1504,9 @@ EAPI int livebox_set_pinup(struct livebox *handler, int flag, ret_cb_t cb, void
                return -EFAULT;
        }
 
+       if (!cb)
+               cb = default_pinup_cb;
+
        return master_rpc_async_request(handler, packet, 0, pinup_done_cb, create_cb_info(cb, data));
 }
 
@@ -1911,7 +1989,7 @@ struct livebox *lb_unref(struct livebox *handler)
 
        dlist_remove_data(s_info.livebox_list, handler);
 
-       handler->state = DELETE;
+       handler->state = DESTROYED;
        free(handler->cluster);
        free(handler->category);
        free(handler->id);
@@ -1931,19 +2009,33 @@ struct livebox *lb_unref(struct livebox *handler)
        return NULL;
 }
 
-int lb_send_delete(struct livebox *handler)
+int lb_send_delete(struct livebox *handler, ret_cb_t cb, void *data)
 {
        struct packet *packet;
 
+       if (!cb && !!data) {
+               ErrPrint("Invalid argument\n");
+               return -EINVAL;
+       }
+
+       if (handler->deleted_cb) {
+               ErrPrint("Already in-progress\n");
+               return -EINPROGRESS;
+       }
+
        packet = packet_create("delete", "ss", handler->pkgname, handler->id);
        if (!packet) {
                ErrPrint("Failed to build a param\n");
-               if (handler->deleted_cb)
-                       handler->deleted_cb(handler, -EFAULT, handler->deleted_cbdata);
+               if (cb)
+                       cb(handler, -EFAULT, data);
+
                return -EFAULT;
        }
 
-       return master_rpc_async_request(handler, packet, 0, del_ret_cb, NULL);
+       if (!cb)
+               cb = default_delete_cb;
+
+       return master_rpc_async_request(handler, packet, 0, del_ret_cb, create_cb_info(cb, data));
 }
 
 EAPI int livebox_subscribe_group(const char *cluster, const char *category)