Improved version of jbus now handling signals
authorJosé Bollo <jose.bollo@iot.bzh>
Mon, 21 Dec 2015 16:03:28 +0000 (17:03 +0100)
committerJosé Bollo <jose.bollo@iot.bzh>
Mon, 21 Dec 2015 16:03:28 +0000 (17:03 +0100)
Change-Id: Ib4786bf8584f0955725a215a6aa6c7ca90bc7115

src/af-run.c
src/af-usrd.c
src/utils-jbus.c
src/utils-jbus.h

index 304eead..6512a11 100644 (file)
@@ -396,11 +396,10 @@ struct json_object *af_run_list()
 {
        struct json_object *result, *obj;
        struct apprun *runner;
 {
        struct json_object *result, *obj;
        struct apprun *runner;
-       char runidstr[20];
        int i;
 
        /* creates the object */
        int i;
 
        /* creates the object */
-       result = json_object_new_object();
+       result = json_object_new_array();
        if (result == NULL) {
                errno = ENOMEM;
                return NULL;            
        if (result == NULL) {
                errno = ENOMEM;
                return NULL;            
@@ -414,9 +413,8 @@ struct json_object *af_run_list()
                                        json_object_put(result);
                                        return NULL;
                                }
                                        json_object_put(result);
                                        return NULL;
                                }
-                               sprintf(runidstr, "%d", runner->runid);
                                /* TODO status ? */
                                /* TODO status ? */
-                               json_object_object_add(result, runidstr, obj);
+                               json_object_array_add(result, obj);
                        }
                }
        }
                        }
                }
        }
index 960b44b..d2df994 100644 (file)
@@ -31,9 +31,9 @@ static struct jbus *jbus;
 static struct af_db *afdb;
 
 const char error_nothing[] = "[]";
 static struct af_db *afdb;
 
 const char error_nothing[] = "[]";
-const char error_bad_request[] = "{\"status\":\"error: bad request\"}";
-const char error_not_found[] = "{\"status\":\"error: not found\"}";
-const char error_cant_start[] = "{\"status\":\"error: can't start\"}";
+const char error_bad_request[] = "bad request";
+const char error_not_found[] = "not found";
+const char error_cant_start[] = "can't start";
 
 static const char *getappid(struct json_object *obj)
 {
 
 static const char *getappid(struct json_object *obj)
 {
@@ -48,15 +48,23 @@ static int getrunid(struct json_object *obj)
 static void reply(struct jreq *jreq, struct json_object *resp, const char *errstr)
 {
        if (resp)
 static void reply(struct jreq *jreq, struct json_object *resp, const char *errstr)
 {
        if (resp)
-               jbus_reply(jreq, resp);
+               jbus_reply_j(jreq, resp);
        else
        else
-               jbus_replyj(jreq, errstr);
+               jbus_reply_error_s(jreq, errstr);
+}
+
+static void reply_status(struct jreq *jreq, int status)
+{
+       if (status)
+               jbus_reply_error_s(jreq, error_not_found);
+       else
+               jbus_reply_s(jreq, "true");
 }
 
 static void on_runnables(struct jreq *jreq, struct json_object *obj)
 {
        struct json_object *resp = af_db_application_list(afdb);
 }
 
 static void on_runnables(struct jreq *jreq, struct json_object *obj)
 {
        struct json_object *resp = af_db_application_list(afdb);
-       jbus_reply(jreq, resp);
+       jbus_reply_j(jreq, resp);
        json_object_put(obj);
 }
 
        json_object_put(obj);
 }
 
@@ -77,19 +85,19 @@ static void on_start(struct jreq *jreq, struct json_object *obj)
 
        appid = getappid(obj);
        if (appid == NULL)
 
        appid = getappid(obj);
        if (appid == NULL)
-               jbus_replyj(jreq, error_bad_request);
+               jbus_reply_error_s(jreq, error_bad_request);
        else {
                appli = af_db_get_application(afdb, appid);
                if (appli == NULL)
        else {
                appli = af_db_get_application(afdb, appid);
                if (appli == NULL)
-                       jbus_replyj(jreq, error_not_found);
+                       jbus_reply_error_s(jreq, error_not_found);
                else {
                        runid = af_run_start(appli);
                        if (runid <= 0)
                else {
                        runid = af_run_start(appli);
                        if (runid <= 0)
-                               jbus_replyj(jreq, error_cant_start);
+                               jbus_reply_error_s(jreq, error_cant_start);
                        else {
                                snprintf(runidstr, sizeof runidstr, "%d", runid);
                                runidstr[sizeof runidstr - 1] = 0;
                        else {
                                snprintf(runidstr, sizeof runidstr, "%d", runid);
                                runidstr[sizeof runidstr - 1] = 0;
-                               jbus_replyj(jreq, runidstr);
+                               jbus_reply_s(jreq, runidstr);
                        }
                }
        }
                        }
                }
        }
@@ -100,7 +108,7 @@ static void on_stop(struct jreq *jreq, struct json_object *obj)
 {
        int runid = getrunid(obj);
        int status = af_run_stop(runid);
 {
        int runid = getrunid(obj);
        int status = af_run_stop(runid);
-       jbus_replyj(jreq, status ? error_not_found : "true");
+       reply_status(jreq, status);
        json_object_put(obj);
 }
 
        json_object_put(obj);
 }
 
@@ -108,7 +116,7 @@ static void on_continue(struct jreq *jreq, struct json_object *obj)
 {
        int runid = getrunid(obj);
        int status = af_run_continue(runid);
 {
        int runid = getrunid(obj);
        int status = af_run_continue(runid);
-       jbus_replyj(jreq, status ? error_not_found : "true");
+       reply_status(jreq, status);
        json_object_put(obj);
 }
 
        json_object_put(obj);
 }
 
@@ -116,14 +124,14 @@ static void on_terminate(struct jreq *jreq, struct json_object *obj)
 {
        int runid = getrunid(obj);
        int status = af_run_terminate(runid);
 {
        int runid = getrunid(obj);
        int status = af_run_terminate(runid);
-       jbus_replyj(jreq, status ? error_not_found : "true");
+       reply_status(jreq, status);
        json_object_put(obj);
 }
 
 static void on_runners(struct jreq *jreq, struct json_object *obj)
 {
        struct json_object *resp = af_run_list();
        json_object_put(obj);
 }
 
 static void on_runners(struct jreq *jreq, struct json_object *obj)
 {
        struct json_object *resp = af_run_list();
-       jbus_reply(jreq, resp);
+       jbus_reply_j(jreq, resp);
        json_object_put(resp);
        json_object_put(obj);
 }
        json_object_put(resp);
        json_object_put(obj);
 }
@@ -181,14 +189,14 @@ int main(int ac, char **av)
                ERROR("create_jbus failed");
                return 1;
        }
                ERROR("create_jbus failed");
                return 1;
        }
-       if(jbus_add_service(jbus, "runnables", on_runnables)
-       || jbus_add_service(jbus, "detail", on_detail)
-       || jbus_add_service(jbus, "start", on_start)
-       || jbus_add_service(jbus, "terminate", on_terminate)
-       || jbus_add_service(jbus, "stop", on_stop)
-       || jbus_add_service(jbus, "continue", on_continue)
-       || jbus_add_service(jbus, "runners", on_runners)
-       || jbus_add_service(jbus, "state", on_state)) {
+       if(jbus_add_service_j(jbus, "runnables", on_runnables)
+       || jbus_add_service_j(jbus, "detail", on_detail)
+       || jbus_add_service_j(jbus, "start", on_start)
+       || jbus_add_service_j(jbus, "terminate", on_terminate)
+       || jbus_add_service_j(jbus, "stop", on_stop)
+       || jbus_add_service_j(jbus, "continue", on_continue)
+       || jbus_add_service_j(jbus, "runners", on_runners)
+       || jbus_add_service_j(jbus, "state", on_state)) {
                ERROR("adding services failed");
                return 1;
        }
                ERROR("adding services failed");
                return 1;
        }
index ef87227..7e65723 100644 (file)
@@ -31,38 +31,217 @@ struct jreq;
 struct jservice;
 struct jbus;
 
 struct jservice;
 struct jbus;
 
+/* structure for handled requests */
 struct jreq {
        DBusConnection *connection;
 struct jreq {
        DBusConnection *connection;
-       DBusMessage *reply;
+       DBusMessage *request;
 };
 
 };
 
+/* structure for recorded services */
 struct jservice {
        struct jservice *next;
        char *method;
 struct jservice {
        struct jservice *next;
        char *method;
-       void (*oncall)(struct jreq *, struct json_object *);
+       void (*oncall_s)(struct jreq *, const char *);
+       void (*oncall_j)(struct jreq *, struct json_object *);
 };
 
 };
 
+/* structure for signal handlers */
+struct jsignal {
+       struct jsignal *next;
+       char *name;
+       void (*onsignal_s)(const char *);
+       void (*onsignal_j)(struct json_object *);
+};
+
+/* structure for recording asynchronous requests */
 struct jrespw {
        struct jrespw *next;
        dbus_uint32_t serial;
        void *data;
 struct jrespw {
        struct jrespw *next;
        dbus_uint32_t serial;
        void *data;
-       void (*onresp)(int status, struct json_object *response, void *data);
+       void (*onresp_s)(int, const char*, void *);
+       void (*onresp_j)(int, struct json_object*, void *);
+};
+
+/* structure for synchronous requests */
+struct respsync {
+       int replied;
+       char *value;
 };
 
 };
 
+/* structure for handling either client or server jbus on dbus */
 struct jbus {
        int refcount;
        struct jservice *services;
        DBusConnection *connection;
 struct jbus {
        int refcount;
        struct jservice *services;
        DBusConnection *connection;
+       struct jsignal *signals;
        struct jrespw *waiters;
        char *path;
        char *name;
 };
 
        struct jrespw *waiters;
        char *path;
        char *name;
 };
 
-static const char reply_out_of_memory[] = "{\"status\":\"out of memory\"}";
-static const char reply_invalid[] = "{\"status\":\"invalid request\"}";
-static const char interface_jbus[] = "org.jbus";
+/*********************** STATIC COMMON METHODS *****************/
+
+static inline void free_jreq(struct jreq *jreq)
+{
+       dbus_message_unref(jreq->request);
+       dbus_connection_unref(jreq->connection);
+       free(jreq);
+}
+
+static inline int reply_out_of_memory(struct jreq *jreq)
+{
+       static const char out_of_memory[] = "out of memory";
+       jbus_reply_error_s(jreq, out_of_memory);
+       errno = ENOMEM;
+       return -1;
+}
+
+static inline int reply_invalid_request(struct jreq *jreq)
+{
+       static const char invalid_request[] = "invalid request";
+       jbus_reply_error_s(jreq, invalid_request);
+       return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static int matchitf(struct jbus *jbus, DBusMessage *message)
+{
+       const char *itf = dbus_message_get_interface(message);
+       return itf != NULL && !strcmp(itf, jbus->name);
+}
+
+static int add_service(
+               struct jbus *jbus,
+               const char *method,
+               void (*oncall_s)(struct jreq*, const char*),
+               void (*oncall_j)(struct jreq*, struct json_object*)
+)
+{
+       struct jservice *srv;
+
+       /* allocation */
+       srv = malloc(sizeof * srv);
+       if (srv == NULL) {
+               errno = ENOMEM;
+               goto error;
+       }
+       srv->method = strdup(method);
+       if (!srv->method) {
+               errno = ENOMEM;
+               goto error2;
+       }
+
+       /* record the service */
+       srv->oncall_s = oncall_s;
+       srv->oncall_j = oncall_j;
+       srv->next = jbus->services;
+       jbus->services = srv;
+
+       return 0;
+
+error2:
+       free(srv);
+error:
+       return -1;
+}
+
+static int add_signal(
+       struct jbus *jbus,
+       const char *name,
+       void (*onsignal_s)(const char*),
+       void (*onsignal_j)(struct json_object*)
+)
+{
+       char *rule;
+       struct jsignal *sig;
+
+       /* record the signal */
+       if (jbus->signals == NULL) {
+               if (0 >= asprintf(&rule, "type='signal',sender='%s',interface='%s',path='%s'", jbus->name, jbus->name, jbus->path))
+                       return -1;
+               dbus_bus_add_match(jbus->connection, rule, NULL);
+               free(rule);
+       }
+
+       /* allocation */
+       sig = malloc(sizeof * sig);
+       if (sig == NULL)
+               goto error;
+       sig->name = strdup(name);
+       if (!sig->name)
+               goto error2;
+
+       /* record the signal */
+       sig->onsignal_s = onsignal_s;
+       sig->onsignal_j = onsignal_j;
+       sig->next = jbus->signals;
+       jbus->signals = sig;
+
+       return 0;
+
+error2:
+       free(sig);
+error:
+       errno = ENOMEM;
+       return -1;
+}
+
+static int call(
+       struct jbus *jbus,
+       const char *method,
+       const char *query,
+       void (*onresp_s)(int status, const char *response, void *data),
+       void (*onresp_j)(int status, struct json_object *response, void *data),
+       void *data
+)
+{
+       DBusMessage *msg;
+       struct jrespw *resp;
+
+       resp = malloc(sizeof * resp);
+       if (resp == NULL) {
+               errno = ENOMEM;
+               goto error;
+       }
+
+       msg = dbus_message_new_method_call(jbus->name, jbus->path, jbus->name, method);
+       if (msg == NULL) {
+               errno = ENOMEM;
+               goto error2;
+       }
+
+       if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &query, DBUS_TYPE_INVALID)) {
+               errno = ENOMEM;
+               goto error3;
+       }
+
+       if (!dbus_connection_send(jbus->connection, msg, &resp->serial)) {
+               goto error3;
+       }
+
+       dbus_message_unref(msg);
+       resp->data = data;
+       resp->onresp_s = onresp_s;
+       resp->onresp_j = onresp_j;
+       resp->next = jbus->waiters;
+       jbus->waiters = resp;
+       return 0;
+
+error3:
+       dbus_message_unref(msg);
+error2:
+       free(resp);
+error:
+       return -1;
+}
+
+static void sync_of_replies(int status, const char *value, void *data)
+{
+       struct respsync *s = data;
+       s->value = status ? NULL : strdup(value ? value : "");
+       s->replied = 1;
+}
 
 
-static DBusHandlerResult incoming_resp(DBusConnection *connection, DBusMessage *message, struct jbus *jbus)
+static DBusHandlerResult incoming_resp(DBusConnection *connection, DBusMessage *message, struct jbus *jbus, int iserror)
 {
        int status;
        const char *str;
 {
        int status;
        const char *str;
@@ -79,27 +258,26 @@ static DBusHandlerResult incoming_resp(DBusConnection *connection, DBusMessage *
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        *prv = jrw->next;
 
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        *prv = jrw->next;
 
-       /* retrieve the json value */
+       /* retrieve the string value */
        if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID)) {
                status = -1;
        if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID)) {
                status = -1;
+               str = NULL;
                reply = NULL;
                reply = NULL;
-       } else {
+       }
+
+       /* treat it */
+       if (jrw->onresp_s)
+               jrw->onresp_s(iserror ? -1 : status, str, jrw->data);
+       else {
                reply = json_tokener_parse(str);
                status = reply ? 0 : -1;
                reply = json_tokener_parse(str);
                status = reply ? 0 : -1;
+               jrw->onresp_j(iserror ? -1 : status, reply, jrw->data);
        }
 
        }
 
-       /* treat it */
-       jrw->onresp(status, reply, jrw->data);
        free(jrw);
        return DBUS_HANDLER_RESULT_HANDLED;
 }
 
        free(jrw);
        return DBUS_HANDLER_RESULT_HANDLED;
 }
 
-static int matchitf(DBusMessage *message)
-{
-       const char *itf = dbus_message_get_interface(message);
-       return itf != NULL && !strcmp(itf, interface_jbus);
-}
-
 static DBusHandlerResult incoming_call(DBusConnection *connection, DBusMessage *message, struct jbus *jbus)
 {
        struct jservice *srv;
 static DBusHandlerResult incoming_call(DBusConnection *connection, DBusMessage *message, struct jbus *jbus)
 {
        struct jservice *srv;
@@ -109,7 +287,7 @@ static DBusHandlerResult incoming_call(DBusConnection *connection, DBusMessage *
        struct json_object *query;
 
        /* search for the service */
        struct json_object *query;
 
        /* search for the service */
-       if (!matchitf(message))
+       if (!matchitf(jbus, message))
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        method = dbus_message_get_member(message);
        if (method == NULL)
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        method = dbus_message_get_member(message);
        if (method == NULL)
@@ -124,26 +302,58 @@ static DBusHandlerResult incoming_call(DBusConnection *connection, DBusMessage *
        jreq = malloc(sizeof * jreq);
        if (jreq == NULL)
                return DBUS_HANDLER_RESULT_NEED_MEMORY;
        jreq = malloc(sizeof * jreq);
        if (jreq == NULL)
                return DBUS_HANDLER_RESULT_NEED_MEMORY;
-       jreq->reply = dbus_message_new_method_return(message);
-       if (jreq->reply == NULL) {
-               free(jreq);
-               return DBUS_HANDLER_RESULT_NEED_MEMORY;
-       }
+       jreq->request = dbus_message_ref(message);
        jreq->connection = dbus_connection_ref(jbus->connection);
        
        jreq->connection = dbus_connection_ref(jbus->connection);
        
-       /* retrieve the json value */
-       if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID)) {
-               jbus_replyj(jreq, reply_invalid);
-               return DBUS_HANDLER_RESULT_HANDLED;
+       /* retrieve the string value */
+       if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID))
+               return reply_invalid_request(jreq);
+       if (srv->oncall_s) {
+               /* handling strings only */
+               srv->oncall_s(jreq, str);
        }
        }
-       query = json_tokener_parse(str);
-       if (query == NULL) {
-               jbus_replyj(jreq, reply_invalid);
-               return DBUS_HANDLER_RESULT_HANDLED;
+       else {
+               /* handling json only */
+               query = json_tokener_parse(str);
+               if (query == NULL)
+                       return reply_invalid_request(jreq);
+               srv->oncall_j(jreq, query);
        }
        }
+       return DBUS_HANDLER_RESULT_HANDLED;
+}
 
 
-       /* treat it */
-       srv->oncall(jreq, query);
+static DBusHandlerResult incoming_signal(DBusConnection *connection, DBusMessage *message, struct jbus *jbus)
+{
+       struct jsignal *sig;
+       const char *str;
+       const char *name;
+       struct json_object *obj;
+
+       /* search for the service */
+       if (!matchitf(jbus, message))
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       name = dbus_message_get_member(message);
+       if (name == NULL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       sig = jbus->signals;
+       while(sig != NULL && strcmp(name, sig->name))
+               sig = sig->next;
+       if (sig == NULL)
+               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+       /* retrieve the string value */
+       if (dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID)) {
+               if (sig->onsignal_s) {
+                       /* handling strings only */
+                       sig->onsignal_s(str);
+               }
+               else {
+                       /* handling json only */
+                       obj = json_tokener_parse(str);
+                       if (obj != NULL)
+                               sig->onsignal_j(obj);
+               }
+       }
        return DBUS_HANDLER_RESULT_HANDLED;
 }
 
        return DBUS_HANDLER_RESULT_HANDLED;
 }
 
@@ -152,12 +362,17 @@ static DBusHandlerResult incoming(DBusConnection *connection, DBusMessage *messa
        switch(dbus_message_get_type(message)) {
        case DBUS_MESSAGE_TYPE_METHOD_CALL:
                return incoming_call(connection, message, (struct jbus*)data);
        switch(dbus_message_get_type(message)) {
        case DBUS_MESSAGE_TYPE_METHOD_CALL:
                return incoming_call(connection, message, (struct jbus*)data);
-       case  DBUS_MESSAGE_TYPE_METHOD_RETURN:
-               return incoming_resp(connection, message, (struct jbus*)data);
+       case DBUS_MESSAGE_TYPE_METHOD_RETURN:
+               return incoming_resp(connection, message, (struct jbus*)data, 0);
+       case DBUS_MESSAGE_TYPE_ERROR:
+               return incoming_resp(connection, message, (struct jbus*)data, 1);
+       case DBUS_MESSAGE_TYPE_SIGNAL:
+               return incoming_signal(connection, message, (struct jbus*)data);
        }
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
        }
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
+/************************** MAIN FUNCTIONS *****************************************/
 
 struct jbus *create_jbus(int session, const char *path)
 {
 
 struct jbus *create_jbus(int session, const char *path)
 {
@@ -234,54 +449,100 @@ void jbus_unref(struct jbus *jbus)
        }
 }
 
        }
 }
 
-int jbus_replyj(struct jreq *jreq, const char *reply)
+int jbus_reply_error_s(struct jreq *jreq, const char *error)
 {
        int rc = -1;
 {
        int rc = -1;
-       if (dbus_message_append_args(jreq->reply, DBUS_TYPE_STRING, &reply, DBUS_TYPE_INVALID)) {
-               if (dbus_connection_send(jreq->connection, jreq->reply, NULL))
+       DBusMessage *message;
+
+       message = dbus_message_new_error(jreq->request, DBUS_ERROR_FAILED, error);
+       if (message == NULL)
+               errno = ENOMEM;
+       else {
+               if (dbus_connection_send(jreq->connection, message, NULL))
                        rc = 0;
                        rc = 0;
+               dbus_message_unref(message);
        }
        }
-       dbus_message_unref(jreq->reply);
-       dbus_connection_unref(jreq->connection);
-       free(jreq);
+       free_jreq(jreq);
        return rc;
 }
 
        return rc;
 }
 
-int jbus_reply(struct jreq *jreq, struct json_object *reply)
+int jbus_reply_error_j(struct jreq *jreq, struct json_object *reply)
 {
        const char *str = json_object_to_json_string(reply);
 {
        const char *str = json_object_to_json_string(reply);
-       return jbus_replyj(jreq, str ? str : reply_out_of_memory);
+       return str ? jbus_reply_error_s(jreq, str) : reply_out_of_memory(jreq);
 }
 
 }
 
-int jbus_add_service(struct jbus *jbus, const char *method, void (*oncall)(struct jreq *jreq, struct json_object *request))
+int jbus_reply_s(struct jreq *jreq, const char *reply)
 {
 {
-       struct jservice *srv;
+       int rc = -1;
+       DBusMessage *message;
 
 
-       /* allocation */
-       srv = malloc(sizeof * srv);
-       if (srv == NULL) {
-               errno = ENOMEM;
-               goto error;
-       }
-       srv->method = strdup(method);
-       if (!srv->method) {
-               errno = ENOMEM;
-               goto error2;
+       message = dbus_message_new_method_return(jreq->request);
+       if (message == NULL)
+               return reply_out_of_memory(jreq);
+
+       if (!dbus_message_append_args(message, DBUS_TYPE_STRING, &reply, DBUS_TYPE_INVALID)) {
+               dbus_message_unref(message);
+               return reply_out_of_memory(jreq);
        }
 
        }
 
-       /* record the service */
-       srv->oncall = oncall;
-       srv->next = jbus->services;
-       jbus->services = srv;
+       if (dbus_connection_send(jreq->connection, message, NULL))
+               rc = 0;
+       dbus_message_unref(message);
+       free_jreq(jreq);
+       return rc;
+}
 
 
-       return 0;
+int jbus_reply_j(struct jreq *jreq, struct json_object *reply)
+{
+       const char *str = json_object_to_json_string(reply);
+       return str ? jbus_reply_s(jreq, str) : reply_out_of_memory(jreq);
+}
+
+int jbus_send_signal_s(struct jbus *jbus, const char *name, const char *content)
+{
+       int rc = -1;
+       DBusMessage *message;
+
+       message = dbus_message_new_signal(jbus->path, jbus->name, name);
+       if (message == NULL)
+               goto error;
+
+       if (!dbus_message_append_args(message, DBUS_TYPE_STRING, &content, DBUS_TYPE_INVALID)) {
+               dbus_message_unref(message);
+               goto error;
+       }
+
+       if (dbus_connection_send(jbus->connection, message, NULL))
+               rc = 0;
+       dbus_message_unref(message);
+       return rc;
 
 
-error2:
-       free(srv);
 error:
 error:
+       errno = ENOMEM;
        return -1;
 }
 
        return -1;
 }
 
+int jbus_send_signal_j(struct jbus *jbus, const char *name, struct json_object *content)
+{
+       const char *str = json_object_to_json_string(content);
+       if (str == NULL) {
+               errno = ENOMEM;
+               return -1;
+       }
+       return jbus_send_signal_s(jbus, name, str);
+}
+
+int jbus_add_service_s(struct jbus *jbus, const char *method, void (*oncall)(struct jreq *, const char *))
+{
+       return add_service(jbus, method, oncall, NULL);
+}
+
+int jbus_add_service_j(struct jbus *jbus, const char *method, void (*oncall)(struct jreq *, struct json_object *))
+{
+       return add_service(jbus, method, NULL, oncall);
+}
+
 int jbus_start_serving(struct jbus *jbus)
 {
        int status = dbus_bus_request_name(jbus->connection, jbus->name, DBUS_NAME_FLAG_DO_NOT_QUEUE, NULL);
 int jbus_start_serving(struct jbus *jbus)
 {
        int status = dbus_bus_request_name(jbus->connection, jbus->name, DBUS_NAME_FLAG_DO_NOT_QUEUE, NULL);
@@ -305,82 +566,111 @@ int jbus_read_write_dispatch(struct jbus *jbus, int toms)
        return -1;
 }
 
        return -1;
 }
 
-int jbus_callj(struct jbus *jbus, const char *method, const char *query, void (*onresp)(int status, struct json_object *response, void *data), void *data)
+int jbus_call_ss(struct jbus *jbus, const char *method, const char *query, void (*onresp)(int, const char*, void*), void *data)
 {
 {
-       DBusMessage *msg;
-       struct jrespw *resp;
+       return call(jbus, method, query, onresp, NULL, data);
+}
 
 
-       resp = malloc(sizeof * resp);
-       if (resp == NULL) {
-               errno = ENOMEM;
-               goto error;
-       }
+int jbus_call_sj(struct jbus *jbus, const char *method, const char *query, void (*onresp)(int, struct json_object*, void*), void *data)
+{
+       return call(jbus, method, query, NULL, onresp, data);
+}
 
 
-       msg = dbus_message_new_method_call(jbus->name, jbus->path, interface_jbus, method);
-       if (msg == NULL) {
+int jbus_call_js(struct jbus *jbus, const char *method, struct json_object *query, void (*onresp)(int, const char*, void*), void *data)
+{
+       const char *str = json_object_to_json_string(query);
+       if (str == NULL) {
                errno = ENOMEM;
                errno = ENOMEM;
-               goto error2;
+               return -1;
        }
        }
+       return call(jbus, method, str, onresp, NULL, data);
+}
 
 
-       if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &query, DBUS_TYPE_INVALID)) {
+int jbus_call_jj(struct jbus *jbus, const char *method, struct json_object *query, void (*onresp)(int, struct json_object*, void*), void *data)
+{
+       const char *str = json_object_to_json_string(query);
+       if (str == NULL) {
                errno = ENOMEM;
                errno = ENOMEM;
-               goto error3;
-       }
-
-       if (!dbus_connection_send(jbus->connection, msg, &resp->serial)) {
-               goto error3;
+               return -1;
        }
        }
+       return call(jbus, method, str, NULL, onresp, data);
+}
 
 
-       dbus_message_unref(msg);
-       resp->data = data;
-       resp->onresp = onresp;
-       resp->next = jbus->waiters;
-       jbus->waiters = resp;
-       return 0;
+char *jbus_call_ss_sync(struct jbus *jbus, const char *method, const char *query)
+{
+       struct respsync synchro;
+       synchro.value = NULL;
+       synchro.replied = jbus_call_ss(jbus, method, query, sync_of_replies, &synchro);
+       while (!synchro.replied && !jbus_read_write_dispatch(jbus, -1));
+       return synchro.value;
+}
 
 
-error3:
-       dbus_message_unref(msg);
-error2:
-       free(resp);
-error:
-       return -1;
+struct json_object *jbus_call_sj_sync(struct jbus *jbus, const char *method, const char *query)
+{
+       const char *str = jbus_call_ss_sync(jbus, method, query);
+       return str ? json_tokener_parse(str) : NULL;
 }
 
 
 }
 
 
-int jbus_call(struct jbus *jbus, const char *method, struct json_object *query, void (*onresp)(int status, struct json_object *response, void *data), void *data)
+char *jbus_call_js_sync(struct jbus *jbus, const char *method, struct json_object *query)
 {
        const char *str = json_object_to_json_string(query);
        if (str == NULL) {
                errno = ENOMEM;
 {
        const char *str = json_object_to_json_string(query);
        if (str == NULL) {
                errno = ENOMEM;
-               return -1;
+               return NULL;
+       }
+       return jbus_call_ss_sync(jbus, method, str);
+}
+
+struct json_object *jbus_call_jj_sync(struct jbus *jbus, const char *method, struct json_object *query)
+{
+       const char *str = json_object_to_json_string(query);
+       if (str == NULL) {
+               errno = ENOMEM;
+               return NULL;
        }
        }
-       return jbus_callj(jbus, method, str, onresp, data);
+       return jbus_call_sj_sync(jbus, method, str);
 }
 
 }
 
+int jbus_on_signal_s(struct jbus *jbus, const char *name, void (*onsig)(const char *))
+{
+       return add_signal(jbus, name, onsig, NULL);
+}
+
+int jbus_on_signal_j(struct jbus *jbus, const char *name, void (*onsig)(struct json_object *))
+{
+       return add_signal(jbus, name, NULL, onsig);
+}
+
+/************************** FEW LITTLE TESTS *****************************************/
+
 #ifdef SERVER
 #include <stdio.h>
 #include <unistd.h>
 #ifdef SERVER
 #include <stdio.h>
 #include <unistd.h>
+struct jbus *jbus;
 void ping(struct jreq *jreq, struct json_object *request)
 {
 printf("ping(%s) -> %s\n",json_object_to_json_string(request),json_object_to_json_string(request));
 void ping(struct jreq *jreq, struct json_object *request)
 {
 printf("ping(%s) -> %s\n",json_object_to_json_string(request),json_object_to_json_string(request));
-       jbus_reply(jreq, request);
-       json_object_put(request);
+       jbus_reply_j(jreq, request);
+       json_object_put(request);       
 }
 void incr(struct jreq *jreq, struct json_object *request)
 {
        static int counter = 0;
        struct json_object *res = json_object_new_int(++counter);
 printf("incr(%s) -> %s\n",json_object_to_json_string(request),json_object_to_json_string(res));
 }
 void incr(struct jreq *jreq, struct json_object *request)
 {
        static int counter = 0;
        struct json_object *res = json_object_new_int(++counter);
 printf("incr(%s) -> %s\n",json_object_to_json_string(request),json_object_to_json_string(res));
-       jbus_reply(jreq, res);
+       jbus_reply_j(jreq, res);
+jbus_send_signal_j(jbus, "incremented", res);
        json_object_put(res);
        json_object_put(request);
 }
 int main()
 {
        json_object_put(res);
        json_object_put(request);
 }
 int main()
 {
-       struct jbus *jbus = create_jbus(1, "/bzh/iot/jdbus");
-       int s1 = jbus_add_service(jbus, "ping", ping);
-       int s2 = jbus_add_service(jbus, "incr", incr);
-       int s3 = jbus_start_serving(jbus);
+       int s1, s2, s3;
+       jbus = create_jbus(1, "/bzh/iot/jdbus");
+       s1 = jbus_add_service_j(jbus, "ping", ping);
+       s2 = jbus_add_service_j(jbus, "incr", incr);
+       s3 = jbus_start_serving(jbus);
        printf("started %d %d %d\n", s1, s2, s3);
        while (!jbus_read_write_dispatch (jbus, -1))
                ;
        printf("started %d %d %d\n", s1, s2, s3);
        while (!jbus_read_write_dispatch (jbus, -1))
                ;
@@ -389,22 +679,36 @@ int main()
 #ifdef CLIENT
 #include <stdio.h>
 #include <unistd.h>
 #ifdef CLIENT
 #include <stdio.h>
 #include <unistd.h>
+struct jbus *jbus;
 void onresp(int status, struct json_object *response, void *data)
 {
        printf("resp: %d, %s, %s\n",status,(char*)data,json_object_to_json_string(response));
        json_object_put(response);
 }
 void onresp(int status, struct json_object *response, void *data)
 {
        printf("resp: %d, %s, %s\n",status,(char*)data,json_object_to_json_string(response));
        json_object_put(response);
 }
+void signaled(const char *data)
+{
+       printf("signaled with {%s}\n", data);
+}
 int main()
 {
 int main()
 {
-       struct jbus *jbus = create_jbus(1, "/bzh/iot/jdbus");
        int i = 10;
        int i = 10;
+       jbus = create_jbus(1, "/bzh/iot/jdbus");
+       jbus_on_signal_s(jbus, "incremented", signaled);
        while(i--) {
        while(i--) {
-               jbus_callj(jbus, "ping", "{\"toto\":[1,2,3,4,true,\"toto\"]}", onresp, "ping");
-               jbus_callj(jbus, "incr", "{\"doit\":\"for-me\"}", onresp, "incr");
+               jbus_call_sj(jbus, "ping", "{\"toto\":[1,2,3,4,true,\"toto\"]}", onresp, "ping");
+               jbus_call_sj(jbus, "incr", "{\"doit\":\"for-me\"}", onresp, "incr");
                jbus_read_write_dispatch (jbus, 1);
        }
                jbus_read_write_dispatch (jbus, 1);
        }
+       printf("[[[%s]]]\n", jbus_call_ss_sync(jbus, "ping", "\"formidable!\""));
        while (!jbus_read_write_dispatch (jbus, -1))
                ;
 }
 #endif
 
        while (!jbus_read_write_dispatch (jbus, -1))
                ;
 }
 #endif
 
+
+
+
+
+
+
+
index 3d71282..68e9b68 100644 (file)
@@ -24,12 +24,30 @@ extern struct jbus *create_jbus(int session, const char *path);
 extern void jbus_addref(struct jbus *jbus);
 extern void jbus_unref(struct jbus *jbus);
 
 extern void jbus_addref(struct jbus *jbus);
 extern void jbus_unref(struct jbus *jbus);
 
-extern int jbus_replyj(struct jreq *jreq, const char *reply);
-extern int jbus_reply(struct jreq *jreq, struct json_object *reply);
-extern int jbus_add_service(struct jbus *jbus, const char *method, void (*oncall)(struct jreq *, struct json_object *));
-extern int jbus_start_serving(struct jbus *jbus);
 extern int jbus_read_write_dispatch(struct jbus *jbus, int toms);
 
 extern int jbus_read_write_dispatch(struct jbus *jbus, int toms);
 
-extern int jbus_callj(struct jbus *jbus, const char *method, const char *query, void (*onresp)(int, struct json_object *, void *), void *data);
-extern int jbus_call(struct jbus *jbus, const char *method, struct json_object *query, void (*onresp)(int, struct json_object *response, void *), void *data);
+/* verbs for the clients */
+extern int jbus_call_ss(struct jbus *jbus, const char *method, const char *query, void (*onresp)(int, const char *, void *), void *data);
+extern int jbus_call_js(struct jbus *jbus, const char *method, struct json_object *query, void (*onresp)(int, const char *, void *), void *data);
+extern int jbus_call_sj(struct jbus *jbus, const char *method, const char *query, void (*onresp)(int, struct json_object *, void *), void *data);
+extern int jbus_call_jj(struct jbus *jbus, const char *method, struct json_object *query, void (*onresp)(int, struct json_object *, void *), void *data);
+
+extern char *jbus_call_ss_sync(struct jbus *jbus, const char *method, const char *query);
+extern char *jbus_call_js_sync(struct jbus *jbus, const char *method, struct json_object *query);
+extern struct json_object *jbus_call_sj_sync(struct jbus *jbus, const char *method, const char *query);
+extern struct json_object *jbus_call_jj_sync(struct jbus *jbus, const char *method, struct json_object *query);
+
+extern int jbus_on_signal_s(struct jbus *jbus, const char *name, void (*onsignal)(const char *));
+extern int jbus_on_signal_j(struct jbus *jbus, const char *name, void (*onsignal)(struct json_object *));
 
 
+/* verbs for servers */
+extern int jbus_reply_s(struct jreq *jreq, const char *reply);
+extern int jbus_reply_j(struct jreq *jreq, struct json_object *reply);
+extern int jbus_reply_error_s(struct jreq *jreq, const char *reply);
+extern int jbus_reply_error_j(struct jreq *jreq, struct json_object *reply);
+
+extern int jbus_add_service_s(struct jbus *jbus, const char *method, void (*oncall)(struct jreq *, const char *));
+extern int jbus_add_service_j(struct jbus *jbus, const char *method, void (*oncall)(struct jreq *, struct json_object *));
+extern int jbus_start_serving(struct jbus *jbus);
+extern int jbus_send_signal_s(struct jbus *jbus, const char *name, const char *content);
+extern int jbus_send_signal_j(struct jbus *jbus, const char *name, struct json_object *content);