return get_creds_by_name(bus, name, mask, _creds, error);
}
+static int driver_activation(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
+ _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+ ProxyActivation *activation = userdata;
+
+ /*
+ * The org.freedesktop.DBus.Peer.Ping() call returned. We don't care
+ * whether this succeeded, failed, was not implemented or timed out. We
+ * cannot assume that the target reacts to this properly. Hence, just
+ * send the reply to the activation request and be done.
+ */
+
+ m = activation->request; /* claim reference */
+
+ --activation->proxy->n_activations;
+ LIST_REMOVE(activations_by_proxy, activation->proxy->activations, activation);
+ sd_bus_slot_unref(activation->slot);
+ free(activation);
+
+ return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
+}
+
int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names) {
int r;
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
_cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
+ ProxyActivation *activation;
const char *name;
uint32_t flags;
if (r != -ESRCH)
return synthetic_reply_method_errno(m, r, NULL);
- r = sd_bus_message_new_method_call(
- a,
- &msg,
- name,
- "/",
- "org.freedesktop.DBus.Peer",
- "Ping");
- if (r < 0)
- return synthetic_reply_method_errno(m, r, NULL);
+ if (p->n_activations >= PROXY_ACTIVATIONS_MAX)
+ return synthetic_reply_method_errno(m, -EMFILE, NULL);
- r = sd_bus_send(a, msg, NULL);
- if (r < 0)
+ activation = new0(ProxyActivation, 1);
+ if (!activation)
+ return synthetic_reply_method_errno(m, -ENOMEM, NULL);
+
+ r = sd_bus_call_method_async(a,
+ &activation->slot,
+ name,
+ "/",
+ "org.freedesktop.DBus.Peer",
+ "Ping",
+ driver_activation,
+ activation,
+ NULL);
+ if (r < 0) {
+ free(activation);
return synthetic_reply_method_errno(m, r, NULL);
+ }
- return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
+ activation->proxy = p;
+ activation->request = sd_bus_message_ref(m);
+ LIST_PREPEND(activations_by_proxy, p->activations, activation);
+ ++p->n_activations;
+ return 1;
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
_cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
#include "bus-xml-policy.h"
typedef struct Proxy Proxy;
+typedef struct ProxyActivation ProxyActivation;
+
+#define PROXY_ACTIVATIONS_MAX (16) /* max parallel activation requests */
struct Proxy {
sd_bus *local_bus;
Set *owned_names;
SharedPolicy *policy;
+ LIST_HEAD(ProxyActivation, activations);
+ size_t n_activations;
+
bool got_hello : 1;
bool queue_overflow : 1;
bool message_matched : 1;
bool synthetic_matched : 1;
};
+struct ProxyActivation {
+ LIST_FIELDS(ProxyActivation, activations_by_proxy);
+ Proxy *proxy;
+ sd_bus_message *request;
+ sd_bus_slot *slot;
+};
+
int proxy_new(Proxy **out, int in_fd, int out_fd, const char *dest);
Proxy *proxy_free(Proxy *p);