+/* the interface for events pushing */
+static const struct afb_evt_itf evt_push_itf = {
+ .push = afb_api_dbus_server_event_push,
+ .add = afb_api_dbus_server_event_add,
+ .remove = afb_api_dbus_server_event_remove
+};
+
+/******************* origin description part for server *****************************/
+
+struct origin
+{
+ /* link to next different origin */
+ struct origin *next;
+
+ /* the server dbus-api */
+ struct api_dbus *api;
+
+ /* count of references */
+ int refcount;
+
+ /* credentials of the origin */
+ struct afb_cred *cred;
+
+ /* the origin */
+ char name[1];
+};
+
+/* get the credentials for the message */
+static void init_origin_creds(struct origin *origin)
+{
+ int rc;
+ sd_bus_creds *c;
+ uid_t uid;
+ gid_t gid;
+ pid_t pid;
+ const char *context;
+
+ rc = sd_bus_get_name_creds(origin->api->sdbus, origin->name,
+ SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT,
+ &c);
+ if (rc < 0)
+ origin->cred = NULL;
+ else {
+ afb_cred_unref(origin->cred);
+ sd_bus_creds_get_uid(c, &uid);
+ sd_bus_creds_get_gid(c, &gid);
+ sd_bus_creds_get_pid(c, &pid);
+ sd_bus_creds_get_selinux_context(c, &context);
+ origin->cred = afb_cred_create(uid, gid, pid, context);
+ sd_bus_creds_unref(c);
+ }
+}
+
+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) + 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)