4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
28 #include <dbus/dbus.h>
30 #include "utils-jbus.h"
33 * max depth of json messages
35 #define MAX_JSON_DEPTH 10
38 * errors messages generated by jbus
40 #if defined(NO_JSON_ERROR_STRING)
41 static const char invalid_request_string[] = "invalid request";
42 static const char out_of_memory_string[] = "out of memory";
44 static const char invalid_request_string[] = "\"invalid request\"";
45 static const char out_of_memory_string[] = "\"out of memory\"";
49 * structure for handled requests
52 DBusConnection *connection; /* connection of the request */
53 DBusMessage *request; /* message of the request */
57 * structure for services
60 struct jservice *next; /* link to the next service */
61 char *method; /* method name for the service */
62 void (*oncall_s) (struct jreq *, const char *, void *);
64 void (*oncall_j) (struct jreq *, struct json_object *, void *);
66 void *data; /* closure data for the callbacks */
70 * structure for signals
73 struct jsignal *next; /* link to the next signal */
74 char *name; /* name of the expected signal */
75 void (*onsignal_s) (const char *, void *);
77 void (*onsignal_j) (struct json_object *, void *);
79 void *data; /* closure data for the callbacks */
83 * structure for asynchronous requests (resp-onse w-aiter)
86 struct jrespw *next; /* next asynchronous */
87 dbus_uint32_t serial; /* serial dbus number */
88 void *data; /* closure data for the callbacks */
89 void (*onresp_s) (int, const char *, void *);
91 void (*onresp_j) (int, struct json_object *, void *);
96 * structure for synchronous requests
99 int replied; /* boolean flag indicating reply */
100 char *value; /* copy of the returned value */
104 * structure for handling either client or server jbus on dbus
107 int refcount; /* referenced how many time */
108 DBusConnection *connection; /* connection to DBU */
109 struct json_tokener *tokener; /* string to json tokenizer */
110 struct jservice *services; /* first service */
111 struct jsignal *signals; /* first signal */
112 struct jrespw *waiters; /* first response waiter */
113 char *path; /* dbus path */
114 char *name; /* dbus name */
115 int watchnr; /* counter of watching need */
116 int watchfd; /* file to watch */
117 short watchflags; /* watched flags */
120 /*********************** STATIC COMMON METHODS *****************/
123 * Frees the ressources attached to a request
125 static inline void free_jreq(struct jreq *jreq)
127 dbus_message_unref(jreq->request);
128 dbus_connection_unref(jreq->connection);
133 * Replies the error "out of memory".
134 * This function is intended to be used in services when an
135 * allocation fails. Thus, it set errno to ENOMEM and
138 static inline int reply_out_of_memory(struct jreq *jreq)
140 jbus_reply_error_s(jreq, out_of_memory_string);
146 * Checks if the incoming 'message' matches the interface
149 * Returns 1 if it matches or 0 wether it does not matches.
151 static int matchitf(struct jbus *jbus, DBusMessage * message)
153 const char *itf = dbus_message_get_interface(message);
154 return itf != NULL && !strcmp(itf, jbus->name);
158 * Adds to 'jbus' a service of name 'method'. The service is
159 * performed by one of the callback 'oncall_s' (for string) or
160 * 'oncall_j' (for json) that will receive the request and the
161 * closure parameter 'data'.
163 * returns 0 in case of success or -1 in case of error (ENOMEM).
165 static int add_service(
168 void (*oncall_s) (struct jreq *, const char *, void *),
169 void (*oncall_j) (struct jreq *, struct json_object *, void *),
172 struct jservice *srv;
175 srv = malloc(sizeof *srv);
180 srv->method = strdup(method);
186 /* record the service */
187 srv->oncall_s = oncall_s;
188 srv->oncall_j = oncall_j;
190 srv->next = jbus->services;
191 jbus->services = srv;
202 * Adds to 'jbus' a handler for the signal of 'name' emmited by
203 * the sender and the interface that 'jbus' is linked to.
204 * The signal is handled by one of the callback 'onsignal_s'
205 * (for string) or 'onsignal_j' (for json) that will receive
206 * parameters associated with the signal and the closure
209 * returns 0 in case of success or -1 in case of error (ENOMEM).
211 static int add_signal(
214 void (*onsignal_s) (const char *, void *),
215 void (*onsignal_j) (struct json_object *, void *),
221 /* record the signal */
222 if (jbus->signals == NULL) {
223 if (0 >= asprintf(&rule,
224 "type='signal',sender='%s',interface='%s',path='%s'",
225 jbus->name, jbus->name, jbus->path))
227 dbus_bus_add_match(jbus->connection, rule, NULL);
232 sig = malloc(sizeof *sig);
235 sig->name = strdup(name);
239 /* record the signal */
240 sig->onsignal_s = onsignal_s;
241 sig->onsignal_j = onsignal_j;
243 sig->next = jbus->signals;
256 * Creates a message for 'method' with one string parameter being 'query'
257 * and sends it to the destination, object and interface linked to 'jbus'.
259 * Adds to 'jbus' the response handler defined by the callbacks 'onresp_s'
260 * (for string) and 'onresp_j' (for json) and the closure parameter 'data'.
262 * Returns 0 in case of success or -1 in case of error.
268 void (*onresp_s) (int, const char *, void *),
269 void (*onresp_j) (int, struct json_object *, void *),
275 /* allocates the response structure */
276 resp = malloc(sizeof *resp);
282 /* creates the message */
283 msg = dbus_message_new_method_call(jbus->name, jbus->path, jbus->name,
291 if (!dbus_message_append_args
292 (msg, DBUS_TYPE_STRING, &query, DBUS_TYPE_INVALID)) {
298 if (!dbus_connection_send(jbus->connection, msg, &resp->serial)) {
299 /* TODO: which error? */
303 /* release the message that is not more used */
304 dbus_message_unref(msg);
306 /* fulfill the response structure */
308 resp->onresp_s = onresp_s;
309 resp->onresp_j = onresp_j;
311 /* links the response to list of reponse waiters */
312 resp->next = jbus->waiters;
313 jbus->waiters = resp;
317 dbus_message_unref(msg);
325 * Callback function for synchronous calls.
326 * This function fills the respsync structure pointed by 'data'
327 * with the copy of the answer.
329 static void sync_of_replies(int status, const char *value, void *data)
331 struct respsync *s = data;
332 s->value = status ? NULL : strdup(value ? value : "");
337 * Parses the json-string 'msg' to create a json object stored
338 * in 'obj'. It uses the tokener of 'jbus'. This is a small
339 * improvement to avoid recreation of tokeners.
341 * Returns 1 in case of success and put the result in *'obj'.
342 * Returns 0 in case of error and put NULL in *'obj'.
344 static int jparse(struct jbus *jbus, const char *msg, struct json_object **obj)
346 json_tokener_reset(jbus->tokener);
347 *obj = json_tokener_parse_ex(jbus->tokener, msg, -1);
348 if (json_tokener_get_error(jbus->tokener) == json_tokener_success)
350 json_object_put(*obj);
355 /*********************** STATIC DBUS MESSAGE HANDLING *****************/
358 * Handles incomming responses 'message' on 'jbus'. Response are
359 * either expected if 'iserror' == 0 or errors if 'iserror' != 0.
361 * Returns DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLED
362 * as defined by the dbus function 'dbus_connection_add_filter'.
364 static DBusHandlerResult incoming_resp(
366 DBusMessage * message,
371 struct jrespw *jrw, **prv;
372 struct json_object *reply;
373 dbus_uint32_t serial;
375 /* search for the waiter */
376 serial = dbus_message_get_reply_serial(message);
377 prv = &jbus->waiters;
378 while ((jrw = *prv) != NULL && jrw->serial != serial)
381 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
384 /* retrieve the string value */
385 if (dbus_message_get_args
386 (message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID))
396 jrw->onresp_s(iserror ? -1 : status, str, jrw->data);
398 status = jparse(jbus, str, &reply) - 1;
399 jrw->onresp_j(iserror ? -1 : status, reply, jrw->data);
400 json_object_put(reply);
404 return DBUS_HANDLER_RESULT_HANDLED;
408 * Handles incomming on 'jbus' method calls for 'message'.
410 * Returns DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLED
411 * as defined by the dbus function 'dbus_connection_add_filter'.
413 static DBusHandlerResult incoming_call(
415 DBusMessage * message)
417 struct jservice *srv;
421 struct json_object *query;
423 /* search for the service */
424 if (!matchitf(jbus, message))
425 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
426 method = dbus_message_get_member(message);
428 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
429 srv = jbus->services;
430 while (srv != NULL && strcmp(method, srv->method))
433 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
435 /* creates and init the jreq structure */
436 jreq = malloc(sizeof *jreq);
438 return DBUS_HANDLER_RESULT_NEED_MEMORY;
439 jreq->request = dbus_message_ref(message);
440 jreq->connection = dbus_connection_ref(jbus->connection);
442 /* retrieve the string parameter of the message */
443 if (!dbus_message_get_args
444 (message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID))
445 goto invalid_request;
447 /* send the message to the callback */
449 /* handling strings only */
450 srv->oncall_s(jreq, str, srv->data);
452 /* handling json only */
453 if (!jparse(jbus, str, &query))
454 goto invalid_request;
455 srv->oncall_j(jreq, query, srv->data);
456 json_object_put(query);
458 return DBUS_HANDLER_RESULT_HANDLED;
461 jbus_reply_error_s(jreq, invalid_request_string);
462 return DBUS_HANDLER_RESULT_HANDLED;
466 * Handles incomming on 'jbus' signal propagated with 'message'.
468 * This is a design choice to ignore invalid signals.
470 * Returns DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLED
471 * as defined by the dbus function 'dbus_connection_add_filter'.
473 static DBusHandlerResult incoming_signal(
475 DBusMessage * message)
480 struct json_object *obj;
482 /* search for the signal name */
483 if (!matchitf(jbus, message))
484 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
485 name = dbus_message_get_member(message);
487 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
489 while (sig != NULL && strcmp(name, sig->name))
492 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
494 /* retrieve the string value */
495 if (dbus_message_get_args
496 (message, NULL, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID)) {
497 if (sig->onsignal_s) {
498 /* handling strings only */
499 sig->onsignal_s(str, sig->data);
501 /* handling json only (if valid) */
502 if (jparse(jbus, str, &obj)) {
503 sig->onsignal_j(obj, sig->data);
504 json_object_put(obj);
508 return DBUS_HANDLER_RESULT_HANDLED;
512 * Filters incomming messages as defined by the dbus function
513 * 'dbus_connection_add_filter'.
514 * Returns DBUS_HANDLER_RESULT_HANDLED or DBUS_HANDLER_RESULT_NOT_YET_HANDLED.
516 static DBusHandlerResult incoming(
517 DBusConnection * connection,
518 DBusMessage * message,
521 struct jbus *jbus = data;
522 switch (dbus_message_get_type(message)) {
523 case DBUS_MESSAGE_TYPE_METHOD_CALL:
524 return incoming_call(jbus, message);
525 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
526 return incoming_resp(jbus, message, 0);
527 case DBUS_MESSAGE_TYPE_ERROR:
528 return incoming_resp(jbus, message, 1);
529 case DBUS_MESSAGE_TYPE_SIGNAL:
530 return incoming_signal(jbus, message);
532 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
535 /*********************** STATIC DBUS WATCH/POLLING INTERFACE **********/
538 * Set the watched flags of 'jbus' following what DBUS expects by 'watch'
540 static void watchset(DBusWatch * watch, struct jbus *jbus)
545 flags = dbus_watch_get_flags(watch);
546 wf = jbus->watchflags;
547 if (dbus_watch_get_enabled(watch)) {
548 if (flags & DBUS_WATCH_READABLE)
550 if (flags & DBUS_WATCH_WRITABLE)
553 if (flags & DBUS_WATCH_READABLE)
555 if (flags & DBUS_WATCH_WRITABLE)
558 jbus->watchflags = wf;
562 * DBUS Callback for removing a 'watch'.
563 * See function 'dbus_connection_set_watch_functions'
565 static void watchdel(DBusWatch * watch, void *data)
567 struct jbus *jbus = data;
569 assert(jbus->watchnr > 0);
570 assert(jbus->watchfd == dbus_watch_get_unix_fd(watch));
575 * DBUS Callback for changing a 'watch'.
576 * See function 'dbus_connection_set_watch_functions'
578 static void watchtoggle(DBusWatch * watch, void *data)
580 struct jbus *jbus = data;
582 assert(jbus->watchnr > 0);
583 assert(jbus->watchfd == dbus_watch_get_unix_fd(watch));
584 watchset(watch, jbus);
588 * DBUS Callback for adding a 'watch'.
589 * See function 'dbus_connection_set_watch_functions'
591 static dbus_bool_t watchadd(DBusWatch * watch, void *data)
593 struct jbus *jbus = data;
594 if (jbus->watchnr == 0) {
595 jbus->watchfd = dbus_watch_get_unix_fd(watch);
596 jbus->watchflags = 0;
597 } else if (jbus->watchfd != dbus_watch_get_unix_fd(watch))
600 watchset(watch, jbus);
604 /********************* MAIN FUNCTIONS *****************************************/
607 * Creates a 'jbus' bound to DBUS system using 'path' and returns it.
610 struct jbus *create_jbus_system(const char *path)
612 return create_jbus(path, 0);
616 * Creates a 'jbus' bound to DBUS session using 'path' and returns it.
619 struct jbus *create_jbus_session(const char *path)
621 return create_jbus(path, 1);
625 * Creates a 'jbus' bound the 'path' and it derived names and linked
626 * either to the DBUS SYSTEM when 'session' is nul or to the DBUS SESSION
627 * if 'session' is not nul.
629 * The parameter 'path' is intended to be the path of a DBUS single object.
630 * Single means that it exists only one instance of the object on the
631 * given bus. That path implies 2 derived DBUS names:
632 * 1. the destination name of the program that handles the object
633 * 2. the interface name of the object
634 * These names are derived by removing the heading slash (/) and
635 * by replacing all occurences of slashes by dots.
636 * For example, passing path = /a/b/c means that the object /a/b/c is
637 * handled by the destination a.b.c and replies to the interface a.b.c
639 * Returns the created jbus or NULL in case of error.
641 struct jbus *create_jbus(const char *path, int session)
646 /* create the jbus object */
647 jbus = calloc(1, sizeof *jbus);
654 /* create the tokener */
655 jbus->tokener = json_tokener_new_ex(MAX_JSON_DEPTH);
656 if (jbus->tokener == NULL) {
661 /* records the path */
662 jbus->path = strdup(path);
663 if (jbus->path == NULL) {
668 /* makes the name from the path */
671 jbus->name = name = strdup(path);
682 while (name >= jbus->name && *name == '.')
689 /* connect and init */
690 jbus->connection = dbus_bus_get(session ? DBUS_BUS_SESSION
691 : DBUS_BUS_SYSTEM, NULL);
692 if (jbus->connection == NULL
693 || !dbus_connection_add_filter(jbus->connection, incoming, jbus,
695 || !dbus_connection_set_watch_functions(jbus->connection, watchadd,
696 watchdel, watchtoggle, jbus, NULL))
708 * Adds one reference to 'jbus'.
710 void jbus_addref(struct jbus *jbus)
716 * Removes one reference to 'jbus'. Destroys 'jbus' and it related
717 * data if the count of references decrease to zero.
719 void jbus_unref(struct jbus *jbus)
721 struct jservice *srv;
722 if (!--jbus->refcount) {
723 if (jbus->connection != NULL)
724 dbus_connection_unref(jbus->connection);
725 while ((srv = jbus->services) != NULL) {
726 jbus->services = srv->next;
730 if (jbus->tokener != NULL)
731 json_tokener_free(jbus->tokener);
739 * Replies an error of string 'error' to the request handled by 'jreq'.
740 * Also destroys the request 'jreq' that must not be used later.
742 * Returns 0 in case of success or -1 in case of error.
744 int jbus_reply_error_s(struct jreq *jreq, const char *error)
747 DBusMessage *message;
749 message = dbus_message_new_error(jreq->request, DBUS_ERROR_FAILED,
754 if (dbus_connection_send(jreq->connection, message, NULL))
756 dbus_message_unref(message);
763 * Replies an error of json 'reply' to the request handled by 'jreq'.
764 * Also destroys the request 'jreq' that must not be used later.
766 * Returns 0 in case of success or -1 in case of error.
768 int jbus_reply_error_j(struct jreq *jreq, struct json_object *reply)
770 const char *str = json_object_to_json_string(reply);
771 return str ? jbus_reply_error_s(jreq, str) : reply_out_of_memory(jreq);
775 * Replies normally the string 'reply' to the request handled by 'jreq'.
776 * Also destroys the request 'jreq' that must not be used later.
778 * Returns 0 in case of success or -1 in case of error.
780 int jbus_reply_s(struct jreq *jreq, const char *reply)
783 DBusMessage *message;
785 message = dbus_message_new_method_return(jreq->request);
787 return reply_out_of_memory(jreq);
789 if (!dbus_message_append_args
790 (message, DBUS_TYPE_STRING, &reply, DBUS_TYPE_INVALID)) {
791 dbus_message_unref(message);
792 return reply_out_of_memory(jreq);
795 if (dbus_connection_send(jreq->connection, message, NULL))
797 dbus_message_unref(message);
803 * Replies normally the json 'reply' to the request handled by 'jreq'.
804 * Also destroys the request 'jreq' that must not be used later.
806 * Returns 0 in case of success or -1 in case of error.
808 int jbus_reply_j(struct jreq *jreq, struct json_object *reply)
810 const char *str = json_object_to_json_string(reply);
811 return str ? jbus_reply_s(jreq, str) : reply_out_of_memory(jreq);
815 * Sends from 'jbus' the signal of 'name' handling the string 'content'.
817 * Returns 0 in case of success or -1 in case of error.
819 int jbus_send_signal_s(struct jbus *jbus, const char *name, const char *content)
822 DBusMessage *message;
824 message = dbus_message_new_signal(jbus->path, jbus->name, name);
828 if (!dbus_message_set_sender(message, jbus->name)
829 || !dbus_message_append_args(message, DBUS_TYPE_STRING, &content,
830 DBUS_TYPE_INVALID)) {
831 dbus_message_unref(message);
835 if (dbus_connection_send(jbus->connection, message, NULL))
837 dbus_message_unref(message);
846 * Sends from 'jbus' the signal of 'name' handling the json 'content'.
848 * Returns 0 in case of success or -1 in case of error.
850 int jbus_send_signal_j(struct jbus *jbus, const char *name,
851 struct json_object *content)
853 const char *str = json_object_to_json_string(content);
858 return jbus_send_signal_s(jbus, name, str);
862 * Adds to 'jbus' a service handling calls to the 'method' using
863 * the "string" callback 'oncall' and the closure value 'data'.
865 * The callback 'oncall' is invoked for handling incoming method
866 * calls. It receives 3 parameters:
867 * 1. struct jreq *: a handler to data to be used for replying
868 * 2. const char *: the received string
869 * 3. void *: the closure 'data' set by this function
871 * Returns 0 in case of success or -1 in case of error.
873 int jbus_add_service_s(
876 void (*oncall) (struct jreq *, const char *, void *),
879 return add_service(jbus, method, oncall, NULL, data);
883 * Adds to 'jbus' a service handling calls to the 'method' using
884 * the "json" callback 'oncall' and the closure value 'data'.
886 * The callback 'oncall' is invoked for handling incoming method
887 * calls. It receives 3 parameters:
888 * 1. struct jreq *: a handler to data to be used for replying
889 * 2. struct json_object *: the received json
890 * 3. void *: the closure 'data' set by this function
892 * Returns 0 in case of success or -1 in case of error.
894 int jbus_add_service_j(
897 void (*oncall) (struct jreq *, struct json_object *, void *),
900 return add_service(jbus, method, NULL, oncall, data);
904 * Start to serve: activate services declared for 'jbus'.
905 * This function, in fact, declares 'jbus' as the receiver
906 * for calls to the destination derived from the path set at
908 * It also allows 'jbus' to emit signals of that origin.
910 * Returns 0 in case of success or -1 in case of error.
912 int jbus_start_serving(struct jbus *jbus)
914 int status = dbus_bus_request_name(jbus->connection, jbus->name,
915 DBUS_NAME_FLAG_DO_NOT_QUEUE, NULL);
917 case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
918 case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
920 case DBUS_REQUEST_NAME_REPLY_EXISTS:
921 case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
929 * Fills the at least 'njbuses' structures of array 'fds' with data needed
930 * to poll the 'njbuses' buses pointed by 'jbuses'.
932 * Returns the count of 'fds' structures filled.
934 int jbus_fill_pollfds(struct jbus **jbuses, int njbuses, struct pollfd *fds)
938 for (r = i = 0; i < njbuses; i++) {
939 if (jbuses[i]->watchnr) {
940 fds[r].fd = jbuses[i]->watchfd;
941 fds[r].events = jbuses[i]->watchflags;
949 * Dispatchs a maximum of 'maxcount' events received by poll in 'fds' for the
950 * 'njbuses' jbuses of the array 'jbuses'.
952 * Returns the count of event dispatched.
954 int jbus_dispatch_pollfds(
955 struct jbus **jbuses,
961 DBusDispatchStatus sts;
963 for (r = n = i = 0; i < njbuses && n < maxcount; i++) {
964 if (jbuses[i]->watchnr && fds[r].fd == jbuses[i]->watchfd) {
965 if (fds[r].revents) {
966 dbus_connection_read_write(
967 jbuses[i]->connection, 0);
968 sts = dbus_connection_get_dispatch_status(
969 jbuses[i]->connection);
970 while (sts == DBUS_DISPATCH_DATA_REMAINS
972 sts = dbus_connection_dispatch(
973 jbuses[i]->connection);
984 * Dispatches 'maxcount' of buffered data from the 'njbuses' jbuses of the
987 * Returns the count of event dispatched.
989 int jbus_dispatch_multiple(struct jbus **jbuses, int njbuses, int maxcount)
992 DBusDispatchStatus sts;
994 for (i = r = 0; i < njbuses && r < maxcount; i++) {
995 dbus_connection_read_write(jbuses[i]->connection, 0);
996 sts = dbus_connection_get_dispatch_status(
997 jbuses[i]->connection);
998 while (sts == DBUS_DISPATCH_DATA_REMAINS && r < maxcount) {
999 sts = dbus_connection_dispatch(jbuses[i]->connection);
1007 * Polls during at most 'toms' milliseconds and dispatches 'maxcount'
1008 * of events from the 'njbuses' jbuses of the array 'jbuses'.
1010 * Returns the count of event dispatched or -1 in case of error.
1012 int jbus_read_write_dispatch_multiple(
1013 struct jbus **jbuses,
1021 if (njbuses < 0 || njbuses > 100) {
1025 fds = alloca((unsigned)njbuses * sizeof *fds);
1026 assert(fds != NULL);
1028 r = jbus_dispatch_multiple(jbuses, njbuses, maxcount);
1031 n = jbus_fill_pollfds(jbuses, njbuses, fds);
1033 s = poll(fds, (nfds_t) n, toms);
1040 n = jbus_dispatch_pollfds(jbuses, njbuses, fds, maxcount - r);
1041 return n >= 0 ? r + n : r ? r : n;
1045 * Polls during at most 'toms' milliseconds and dispatches
1046 * the events from 'jbus'.
1048 * Returns the count of event dispatched or -1 in case of error.
1050 int jbus_read_write_dispatch(struct jbus *jbus, int toms)
1052 int r = jbus_read_write_dispatch_multiple(&jbus, 1, toms, 1000);
1053 return r < 0 ? r : 0;
1057 * Asynchronous call to 'method' of 'jbus' passing the string 'query'.
1058 * On response, the function 'onresp' is called with the returned string
1059 * value and the closure 'data'.
1060 * The function 'onresp' is invoked with 3 parameters:
1061 * 1. int: 0 if no error or -1 if error.
1062 * 2. const char *: the returned string (might be NULL if error)
1063 * 3. void *: the closure 'data'
1065 * Returns 0 in case of success or -1 in case of error.
1071 void (*onresp) (int, const char *, void *),
1074 return call(jbus, method, query, onresp, NULL, data);
1078 * Asynchronous call to 'method' of 'jbus' passing the string 'query'.
1079 * On response, the function 'onresp' is called with the returned json
1080 * value and the closure 'data'.
1081 * The function 'onresp' is invoked with 3 parameters:
1082 * 1. int: 0 if no error or -1 if error.
1083 * 2. const char *: the returned json (might be NULL if error)
1084 * 3. void *: the closure 'data'
1086 * Returns 0 in case of success or -1 in case of error.
1092 void (*onresp) (int, struct json_object *, void *),
1095 return call(jbus, method, query, NULL, onresp, data);
1099 * Asynchronous call to 'method' of 'jbus' passing the json 'query'.
1100 * On response, the function 'onresp' is called with the returned string
1101 * value and the closure 'data'.
1102 * The function 'onresp' is invoked with 3 parameters:
1103 * 1. int: 0 if no error or -1 if error.
1104 * 2. const char *: the returned string (might be NULL if error)
1105 * 3. void *: the closure 'data'
1107 * Returns 0 in case of success or -1 in case of error.
1112 struct json_object *query,
1113 void (*onresp) (int, const char *, void *),
1116 const char *str = json_object_to_json_string(query);
1121 return call(jbus, method, str, onresp, NULL, data);
1125 * Asynchronous call to 'method' of 'jbus' passing the json 'query'.
1126 * On response, the function 'onresp' is called with the returned json
1127 * value and the closure 'data'.
1128 * The function 'onresp' is invoked with 3 parameters:
1129 * 1. int: 0 if no error or -1 if error.
1130 * 2. const char *: the returned json (might be NULL if error)
1131 * 3. void *: the closure 'data'
1133 * Returns 0 in case of success or -1 in case of error.
1138 struct json_object *query,
1139 void (*onresp) (int, struct json_object *, void *),
1142 const char *str = json_object_to_json_string(query);
1147 return call(jbus, method, str, NULL, onresp, data);
1151 * Synchronous call to 'method' of 'jbus' passing the string 'query'.
1152 * The returned string response is returned.
1154 * Returns the string response or NULL in case of error.
1156 char *jbus_call_ss_sync(
1161 struct respsync synchro;
1162 synchro.value = NULL;
1164 jbus_call_ss(jbus, method, query, sync_of_replies, &synchro);
1165 while (!synchro.replied && !jbus_read_write_dispatch(jbus, -1)) ;
1166 return synchro.value;
1170 * Synchronous call to 'method' of 'jbus' passing the string 'query'.
1171 * The returned json response is returned.
1173 * Returns the json response or NULL in case of error.
1175 struct json_object *jbus_call_sj_sync(
1180 struct json_object *obj;
1181 char *str = jbus_call_ss_sync(jbus, method, query);
1185 jparse(jbus, str, &obj);
1192 * Synchronous call to 'method' of 'jbus' passing the json 'query'.
1193 * The returned string response is returned.
1195 * Returns the string response or NULL in case of error.
1197 char *jbus_call_js_sync(
1200 struct json_object *query)
1202 const char *str = json_object_to_json_string(query);
1207 return jbus_call_ss_sync(jbus, method, str);
1211 * Synchronous call to 'method' of 'jbus' passing the json 'query'.
1212 * The returned json response is returned.
1214 * Returns the json response or NULL in case of error.
1216 struct json_object *jbus_call_jj_sync(
1219 struct json_object *query)
1221 const char *str = json_object_to_json_string(query);
1226 return jbus_call_sj_sync(jbus, method, str);
1230 * Records for 'jbus' the string signal handler 'onsig' with closure 'data'
1231 * for the signal of 'name'.
1232 * The callback handler is called with 2 arguments:
1233 * 1. char *: the string parameter associated to the signal
1234 * 2. void *: the closure data.
1236 * Returns 0 in case of success or -1 otherwise.
1238 int jbus_on_signal_s(
1241 void (*onsig) (const char *, void *),
1244 return add_signal(jbus, name, onsig, NULL, data);
1248 * Records for 'jbus' the json signal handler 'onsig' with closure 'data'
1249 * for the signal of 'name'.
1250 * The callback handler is called with 2 arguments:
1251 * 1. struct json_object *: the json parameter associated to the signal
1252 * 2. void *: the closure data.
1254 * Returns 0 in case of success or -1 otherwise.
1256 int jbus_on_signal_j(
1259 void (*onsig) (struct json_object *, void *),
1262 return add_signal(jbus, name, NULL, onsig, data);
1265 /****************** FEW LITTLE TESTS *****************************************/
1271 void ping(struct jreq *jreq, struct json_object *request, void *unused)
1273 printf("ping(%s) -> %s\n", json_object_to_json_string(request),
1274 json_object_to_json_string(request));
1275 jbus_reply_j(jreq, request);
1276 json_object_put(request);
1279 void incr(struct jreq *jreq, struct json_object *request, void *unused)
1281 static int counter = 0;
1282 struct json_object *res = json_object_new_int(++counter);
1283 printf("incr(%s) -> %s\n", json_object_to_json_string(request),
1284 json_object_to_json_string(res));
1285 jbus_reply_j(jreq, res);
1286 jbus_send_signal_j(jbus, "incremented", res);
1287 json_object_put(res);
1288 json_object_put(request);
1294 jbus = create_jbus(1, "/bzh/iot/jdbus");
1295 s1 = jbus_add_service_j(jbus, "ping", ping, NULL);
1296 s2 = jbus_add_service_j(jbus, "incr", incr, NULL);
1297 s3 = jbus_start_serving(jbus);
1298 printf("started %d %d %d\n", s1, s2, s3);
1299 while (!jbus_read_write_dispatch(jbus, -1)) ;
1306 void onresp(int status, struct json_object *response, void *data)
1308 printf("resp: %d, %s, %s\n", status, (char *)data,
1309 json_object_to_json_string(response));
1310 json_object_put(response);
1313 void signaled(const char *data)
1315 printf("signaled with {%s}\n", data);
1321 jbus = create_jbus(1, "/bzh/iot/jdbus");
1322 jbus_on_signal_s(jbus, "incremented", signaled);
1324 jbus_call_sj(jbus, "ping", "{\"toto\":[1,2,3,4,true,\"toto\"]}",
1326 jbus_call_sj(jbus, "incr", "{\"doit\":\"for-me\"}", onresp,
1328 jbus_read_write_dispatch(jbus, 1);
1330 printf("[[[%s]]]\n",
1331 jbus_call_ss_sync(jbus, "ping", "\"formidable!\""));
1332 while (!jbus_read_write_dispatch(jbus, -1)) ;