- struct jreq *jreq;
- const char *str;
- const char *method;
- struct json_object *query;
-
- /* search for the service */
- if (!matchitf(message))
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- method = dbus_message_get_member(message);
- if (method == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
- srv = jbus->services;
- while(srv != NULL && strcmp(method, srv->method))
- srv = srv->next;
- if (srv == NULL)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- /* handle the message */
- 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;
+
+ /* connection of the service */
+ if (jbus->sservice == NULL) {
+ rc = sd_bus_add_object(jbus->sdbus, &jbus->sservice, jbus->path, (void*)on_service_call, jbus);
+ if (rc < 0) {
+ errno = -rc;
+ goto error;
+ }
+ }
+
+ /* 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->data = data;
+ srv->next = jbus->services;
+ jbus->services = srv;
+
+ return 0;
+
+ error2:
+ free(srv);
+ error:
+ return -1;
+}
+
+static int on_signal_event(struct sd_bus_message *smsg, struct jbus *jbus, sd_bus_error *error)
+{
+ struct jsignal *signal;
+ const char *member, *content;
+ struct json_object *obj;
+
+ /* check the type */
+ if (!sd_bus_message_has_signature(smsg, "s")
+ || sd_bus_message_read_basic(smsg, 's', &content) < 0)
+ return 0;
+
+ /* dispatch */
+ member = sd_bus_message_get_member(smsg);
+ signal = jbus->signals;
+ while (signal != NULL) {
+ if (!strcmp(signal->name, member)) {
+ if (signal->onsignal_s)
+ signal->onsignal_s(content, signal->data);
+ else if (signal->onsignal_j) {
+ if (!jparse(jbus, content, &obj))
+ obj = json_object_new_string(content);
+ signal->onsignal_j(obj, signal->data);
+ json_object_put(obj);
+ }
+ }
+ signal = signal->next;
+ }
+ return 0;
+}
+
+/*
+ * Adds to 'jbus' a handler for the signal of 'name' emmited by
+ * the sender and the interface that 'jbus' is linked to.
+ * The signal is handled by one of the callback 'onsignal_s'
+ * (for string) or 'onsignal_j' (for json) that will receive
+ * parameters associated with the signal and the closure
+ * parameter 'data'.
+ *
+ * returns 0 in case of success or -1 in case of error (ENOMEM).
+ */
+static int add_signal(
+ struct jbus *jbus,
+ const char *name,
+ void (*onsignal_s) (const char *, void *),
+ void (*onsignal_j) (struct json_object *, void *),
+ void *data)
+{
+ int rc;
+ struct jsignal *sig;
+ char *match;
+
+ /* connection of the signal */
+ if (jbus->ssignal == NULL) {
+ rc = asprintf(&match, "type='signal',path='%s',interface='%s'", jbus->path, jbus->name);
+ if (rc < 0) {
+ errno = ENOMEM;
+ goto error;
+ }
+ rc = sd_bus_add_match(jbus->sdbus, &jbus->ssignal, match, (void*)on_signal_event, jbus);
+ free(match);
+ if (rc < 0) {
+ errno = -rc;
+ goto error;
+ }