+/*********************** 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;
+}