+static struct origin *afb_api_dbus_server_origin_get(struct api_dbus *api, const char *sender)
+{
+ struct origin *origin;
+
+ /* searchs for an existing origin */
+ origin = api->server.origins;
+ while (origin != NULL) {
+ if (0 == strcmp(origin->name, sender)) {
+ origin->refcount++;
+ return origin;
+ }
+ origin = origin->next;
+ }
+
+ /* not found, create it */
+ origin = malloc(strlen(sender) + 1 + sizeof *origin);
+ if (origin == NULL)
+ errno = ENOMEM;
+ else {
+ origin->api = api;
+ origin->refcount = 1;
+ strcpy(origin->name, sender);
+ init_origin_creds(origin);
+ origin->next = api->server.origins;
+ api->server.origins = origin;
+ }
+ return origin;
+}
+
+static void afb_api_dbus_server_origin_unref(struct origin *origin)
+{
+ if (!--origin->refcount) {
+ struct origin **prv;
+
+ prv = &origin->api->server.origins;
+ while(*prv != origin)
+ prv = &(*prv)->next;
+ *prv = origin->next;
+ afb_cred_unref(origin->cred);
+ free(origin);
+ }
+}
+
+struct listener
+{
+ /* link to next different origin */
+ struct origin *origin;
+
+ /* the listener of events */
+ struct afb_evt_listener *listener;
+};
+
+static void afb_api_dbus_server_listener_free(struct listener *listener)
+{
+ afb_evt_listener_unref(listener->listener);
+ afb_api_dbus_server_origin_unref(listener->origin);
+ free(listener);
+}
+
+static struct listener *afb_api_dbus_server_listener_get(struct api_dbus *api, const char *sender, struct afb_session *session)
+{
+ int rc;
+ struct listener *listener;
+ struct origin *origin;
+
+ /* get the origin */
+ origin = afb_api_dbus_server_origin_get(api, sender);
+ if (origin == NULL)
+ return NULL;
+
+ /* retrieves the stored listener */
+ listener = afb_session_get_cookie(session, origin);
+ if (listener != NULL) {
+ /* found */
+ afb_api_dbus_server_origin_unref(origin);
+ return listener;
+ }
+
+ /* creates the listener */
+ listener = malloc(sizeof *listener);
+ if (listener == NULL)
+ errno = ENOMEM;
+ else {
+ listener->origin = origin;
+ listener->listener = afb_evt_listener_create(&evt_push_itf, origin);
+ if (listener->listener != NULL) {
+ rc = afb_session_set_cookie(session, origin, listener, (void*)afb_api_dbus_server_listener_free);
+ if (rc == 0)
+ return listener;
+ afb_evt_listener_unref(listener->listener);
+ }
+ free(listener);
+ }
+ afb_api_dbus_server_origin_unref(origin);
+ return NULL;
+}
+
+/******************* dbus request part for server *****************/
+
+/**
+ * Structure for a dbus request
+ */
+struct dbus_req {
+ struct afb_xreq xreq; /**< the xreq of the request */
+ sd_bus_message *message; /**< the incoming request message */
+ const char *request; /**< the readen request as string */
+ struct json_object *json; /**< the readen request as object */
+ struct listener *listener; /**< the listener for events */
+};
+