massive refactor to stop passing around client index in server.c
This commit is contained in:
parent
2755669b05
commit
2fb13032ab
4 changed files with 137 additions and 144 deletions
15
match.c
15
match.c
|
@ -178,17 +178,16 @@ fail:
|
|||
} \
|
||||
} while(0)
|
||||
|
||||
int match_check_sender(Bus *s, int sender_index, MatchRule *rule)
|
||||
int match_check_sender(Bus *s, BusClient *sender_client, MatchRule *rule)
|
||||
{
|
||||
BusClient *sender_client = &s->clients[sender_index];
|
||||
if (rule->sender) {
|
||||
if (sender_client->unique_name_index >= 0) {
|
||||
if (strcmp(rule->sender, s->names[sender_client->unique_name_index].name) == 0) {
|
||||
if (sender_client->unique_name) {
|
||||
if (strcmp(rule->sender, sender_client->unique_name->name) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < BUS_NAMES_PER_CLIENT; i++) {
|
||||
if (sender_client->owned_names[i] >= 0 && strcmp(rule->sender, s->names[sender_client->owned_names[i]].name) == 0) {
|
||||
if (sender_client->owned_names[i] && strcmp(rule->sender, sender_client->owned_names[i]->name) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -197,19 +196,19 @@ int match_check_sender(Bus *s, int sender_index, MatchRule *rule)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int match_rule_check(Bus *s, int sender_index, MatchRule *rule, WireMsg *msg, WireCtx *ctx)
|
||||
int match_rule_check(Bus *s, BusClient *sender_client, MatchRule *rule, WireMsg *msg, WireCtx *ctx)
|
||||
{
|
||||
if (rule->type && msg->type != rule->type) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sender_index < 0) {
|
||||
if (!sender_client) {
|
||||
// if the sender is negative, we assume the message is coming from the message bus
|
||||
if (rule->sender && strcmp(rule->sender, "org.freedesktop.DBus") != 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (match_check_sender(s, sender_index, rule) < 0) {
|
||||
if (match_check_sender(s, sender_client, rule) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
2
match.h
2
match.h
|
@ -8,6 +8,6 @@
|
|||
|
||||
void match_rule_free(MatchRule *rule);
|
||||
MatchRule *match_rule_from_string(char *d);
|
||||
int match_rule_check(Bus *s, int sender_index, MatchRule *rule, WireMsg *msg, WireCtx *ctx);
|
||||
int match_rule_check(Bus *s, BusClient *sender_client, MatchRule *rule, WireMsg *msg, WireCtx *ctx);
|
||||
|
||||
#endif // _JITTERBUG__MATCH_H
|
||||
|
|
243
server.c
243
server.c
|
@ -37,7 +37,7 @@ void bus_free(Bus *s)
|
|||
if (s->urandom_fd >= 0) close(s->urandom_fd);
|
||||
// freeing all clients will also free all matches and names
|
||||
for (int i = 0; i < BUS_MAX_CLIENTS; i++) {
|
||||
bus_client_remove(s, i);
|
||||
bus_client_remove(s, &s->clients[i]);
|
||||
}
|
||||
free(s);
|
||||
}
|
||||
|
@ -86,9 +86,10 @@ Bus *bus_create(const char *socket_path)
|
|||
|
||||
for (int i = 0; i < BUS_MAX_CLIENTS; i++) {
|
||||
s->clients[i].fd = -1;
|
||||
s->clients[i].unique_name_index = -1;
|
||||
s->clients[i].unique_name = NULL;
|
||||
s->clients[i].state = BUS_CLIENT_STATE_NONE;
|
||||
s->clients[i].match_count = 0;
|
||||
s->clients[i].fd_index = i;
|
||||
s->fds[i].fd = -1;
|
||||
s->fds[i].events = 0;
|
||||
s->fds[i].revents = 0;
|
||||
|
@ -96,12 +97,12 @@ Bus *bus_create(const char *socket_path)
|
|||
s->clients[i].matches[j] = NULL;
|
||||
}
|
||||
for (int j = 0; j < BUS_NAMES_PER_CLIENT; j++) {
|
||||
s->clients[i].owned_names[j] = -1;
|
||||
s->clients[i].owned_names[j] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < BUS_MAX_NAMES; i++) {
|
||||
s->names[i].client_index = -1;
|
||||
s->names[i].client = NULL;
|
||||
s->names[i].name = NULL;
|
||||
}
|
||||
s->names_count = 0;
|
||||
|
@ -126,7 +127,7 @@ int bus_client_add(Bus *s, int fd)
|
|||
for (int i = 0; i < BUS_MAX_CLIENTS; i++) {
|
||||
if (s->clients[i].fd < 0) {
|
||||
s->clients[i].fd = fd;
|
||||
s->clients[i].unique_name_index = -1;
|
||||
s->clients[i].unique_name = NULL;
|
||||
s->clients[i].state = BUS_CLIENT_STATE_WAIT_AUTH;
|
||||
s->fds[i].fd = fd;
|
||||
s->fds[i].events = POLLIN;
|
||||
|
@ -157,48 +158,46 @@ BusClient *bus_name_find_client(Bus *s, char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (s->names[name_index].client_index < 0) {
|
||||
if (!s->names[name_index].client) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (s->clients[s->names[name_index].client_index].state != BUS_CLIENT_STATE_READY) {
|
||||
if (s->names[name_index].client->state != BUS_CLIENT_STATE_READY) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &s->clients[s->names[name_index].client_index];
|
||||
return s->names[name_index].client;
|
||||
}
|
||||
|
||||
int bus_name_add(Bus *s, char *name, int client_index)
|
||||
BusName *bus_name_add(Bus *s, char *name, BusClient *client)
|
||||
{
|
||||
if (bus_name_find(s, name) >= 0) {
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int bucket = hashmap_hash(name, strlen(name), BUS_MAX_NAMES);
|
||||
|
||||
for (int i = bucket; i < bucket + 12 && i < BUS_MAX_NAMES; i++) {
|
||||
if (s->names[i].client_index == -1) {
|
||||
if (!s->names[i].client) {
|
||||
for (int j = 0; j < BUS_NAMES_PER_CLIENT; j++) {
|
||||
if (s->clients[client_index].owned_names[j] < 0) {
|
||||
s->clients[client_index].owned_names[j] = i;
|
||||
s->names[i].client_index = client_index;
|
||||
if (!client->owned_names[j]) {
|
||||
client->owned_names[j] = &s->names[i];
|
||||
s->names[i].client = client;
|
||||
s->names[i].name = name;
|
||||
s->names_count++;
|
||||
return i;
|
||||
return &s->names[i];
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int bus_client_match_add(Bus *s, int client_index, char *match)
|
||||
int bus_client_match_add(Bus *s, BusClient *c, char *match)
|
||||
{
|
||||
BusClient *c = &s->clients[client_index];
|
||||
|
||||
for (int i = 0; i < BUS_MAX_MATCH; i++) {
|
||||
if (!c->matches[i]) {
|
||||
c->matches[i] = match_rule_from_string(match);
|
||||
|
@ -210,65 +209,66 @@ int bus_client_match_add(Bus *s, int client_index, char *match)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int bus_client_assign_unique_name(Bus *s, int i)
|
||||
BusName *bus_client_assign_unique_name(Bus *s, BusClient *client)
|
||||
{
|
||||
BusClient *c = &s->clients[i];
|
||||
if (c->unique_name_index != -1) {
|
||||
return -1;
|
||||
if (client->unique_name) {
|
||||
return NULL;
|
||||
}
|
||||
uint32_t id = 0;
|
||||
|
||||
if (read(s->urandom_fd, &id, sizeof(uint32_t)) != sizeof(uint32_t)) {
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *name = malloc(sizeof(char) * 16);
|
||||
char *name_str = malloc(sizeof(char) * 16);
|
||||
if (!name_str) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (snprintf(name_str, 16, ":1.%"PRIu32, id) < 0) {
|
||||
free(name_str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BusName *name = bus_name_add(s, name_str, client);
|
||||
if (!name) {
|
||||
return -1;
|
||||
free(name_str);
|
||||
return NULL;
|
||||
}
|
||||
client->unique_name = name;
|
||||
|
||||
if (snprintf(name, 16, ":1.%"PRIu32, id) < 0) {
|
||||
free(name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int name_index = bus_name_add(s, name, i);
|
||||
if (name_index < 0) {
|
||||
free(name);
|
||||
return -1;
|
||||
}
|
||||
c->unique_name_index = name_index;
|
||||
|
||||
return name_index;
|
||||
return name;
|
||||
}
|
||||
|
||||
int bus_client_assign_own_name(Bus *s, int i, char *name)
|
||||
int bus_client_assign_own_name(Bus *s, BusClient *client, char *name)
|
||||
{
|
||||
if (!name || *name == ':' || *name == '\0') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
TRYST(bus_name_add(s, name, i));
|
||||
TRYPTR(bus_name_add(s, name, client));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bus_name_remove(Bus *s, int i)
|
||||
void bus_name_remove(Bus *s, BusName *name)
|
||||
{
|
||||
if (i >= 0) {
|
||||
if (s->names[i].name) {
|
||||
free(s->names[i].name);
|
||||
s->names[i].name = NULL;
|
||||
}
|
||||
s->names[i].client_index = -1;
|
||||
s->names_count--;
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (name->name) {
|
||||
free(name->name);
|
||||
name->name = NULL;
|
||||
}
|
||||
|
||||
name->client = NULL;
|
||||
|
||||
s->names_count--;
|
||||
}
|
||||
|
||||
void bus_client_remove(Bus *s, int i)
|
||||
void bus_client_remove(Bus *s, BusClient *c)
|
||||
{
|
||||
BusClient *c = &s->clients[i];
|
||||
|
||||
if (c->fd >= 0) {
|
||||
close(c->fd);
|
||||
}
|
||||
|
@ -279,38 +279,34 @@ void bus_client_remove(Bus *s, int i)
|
|||
}
|
||||
}
|
||||
for (int j = 0; j < BUS_NAMES_PER_CLIENT; j++) {
|
||||
if (c->owned_names[j] >= 0) {
|
||||
bus_name_remove(s, c->owned_names[j]);
|
||||
c->owned_names[j] = -1;
|
||||
}
|
||||
bus_name_remove(s, c->owned_names[j]);
|
||||
c->owned_names[j] = NULL;
|
||||
}
|
||||
|
||||
c->unique_name_index = -1;
|
||||
c->unique_name = NULL;
|
||||
c->match_count = 0;
|
||||
c->fd = -1;
|
||||
c->state = BUS_CLIENT_STATE_NONE;
|
||||
s->fds[i].fd = -1;
|
||||
s->fds[i].events = 0;
|
||||
s->fds[i].revents = 0;
|
||||
s->fds[c->fd_index].fd = -1;
|
||||
s->fds[c->fd_index].events = 0;
|
||||
s->fds[c->fd_index].revents = 0;
|
||||
s->clients_count--;
|
||||
}
|
||||
|
||||
void bus_client_error(Bus *s, int i, const char *msg)
|
||||
void bus_client_error(Bus *s, BusClient *client, const char *msg)
|
||||
{
|
||||
WARN("removing client %d due to error: %s\n", i, msg);
|
||||
send(s->clients[i].fd, msg, strlen(msg), 0);
|
||||
bus_client_remove(s, i);
|
||||
WARN("removing client %d due to error: %s\n", client->fd_index, msg);
|
||||
send(client->fd, msg, strlen(msg), 0);
|
||||
bus_client_remove(s, client);
|
||||
}
|
||||
|
||||
int bus_broadcast_message(Bus *s, int sender_index, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx)
|
||||
int bus_broadcast_message(Bus *s, BusClient *sender_client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx)
|
||||
{
|
||||
uint32_t body_end = ctx->byte_cursor + msg->body_length;
|
||||
if (body_end >= ctx->data_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
BusClient *sender_client = &s->clients[sender_index];
|
||||
|
||||
int left = s->clients_count;
|
||||
for (int i = 0; i < BUS_MAX_CLIENTS && left > 0; i++) {
|
||||
if (s->clients[i].state != BUS_CLIENT_STATE_READY) {
|
||||
|
@ -329,8 +325,8 @@ int bus_broadcast_message(Bus *s, int sender_index, WireMsg *msg, WireCtx *ctx,
|
|||
match_left--;
|
||||
|
||||
uint32_t previous_cursor = ctx->byte_cursor;
|
||||
if (match_rule_check(s, sender_index, c->matches[j], msg, ctx) >= 0) {
|
||||
TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, s->names[sender_client->unique_name_index].name));
|
||||
if (match_rule_check(s, sender_client, c->matches[j], msg, ctx) >= 0) {
|
||||
TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, sender_client->unique_name->name));
|
||||
TRYST(send(c->fd, reply_ctx->data, reply_ctx->byte_cursor, 0));
|
||||
// TODO?
|
||||
memset(reply_ctx->data, 0, reply_ctx->data_len);
|
||||
|
@ -346,7 +342,7 @@ int bus_broadcast_message(Bus *s, int sender_index, WireMsg *msg, WireCtx *ctx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int bus_broadcast_signal(Bus *s, int sender_index, WireCtx *ctx, WireMsg *msg)
|
||||
int bus_broadcast_signal(Bus *s, BusClient *client, WireCtx *ctx, WireMsg *msg)
|
||||
{
|
||||
int left = s->clients_count;
|
||||
for (int i = 0; i < BUS_MAX_CLIENTS && left > 0; i++) {
|
||||
|
@ -364,7 +360,7 @@ int bus_broadcast_signal(Bus *s, int sender_index, WireCtx *ctx, WireMsg *msg)
|
|||
}
|
||||
|
||||
match_left--;
|
||||
if (match_rule_check(s, sender_index, c->matches[j], msg, ctx) >= 0) {
|
||||
if (match_rule_check(s, client, c->matches[j], msg, ctx) >= 0) {
|
||||
uint32_t previous_cursor = ctx->byte_cursor;
|
||||
TRYST(send(c->fd, ctx->data, ctx->byte_cursor, 0));
|
||||
ctx->byte_cursor = previous_cursor;
|
||||
|
@ -399,7 +395,7 @@ int bus_unicast_message(Bus *s, WireMsg *msg, WireCtx *ctx, char *target_name, c
|
|||
|
||||
#define _signal_end() \
|
||||
*signal_body_length = signal_reply_ctx.byte_cursor - signal_body_start; \
|
||||
TRYST(bus_broadcast_signal(s, -1, &signal_reply_ctx, &signal_reply_msg)); \
|
||||
TRYST(bus_broadcast_signal(s, NULL, &signal_reply_ctx, &signal_reply_msg)); \
|
||||
|
||||
|
||||
#define _reply_begin(M_sig) \
|
||||
|
@ -411,7 +407,7 @@ int bus_unicast_message(Bus *s, WireMsg *msg, WireCtx *ctx, char *target_name, c
|
|||
|
||||
#define _reply_end() \
|
||||
*body_length = reply_ctx->byte_cursor - body_start; \
|
||||
if (send(s->fds[i].fd, reply_ctx->data, reply_ctx->byte_cursor, 0) != reply_ctx->byte_cursor) { \
|
||||
if (send(client->fd, reply_ctx->data, reply_ctx->byte_cursor, 0) != reply_ctx->byte_cursor) { \
|
||||
return -1; \
|
||||
} \
|
||||
VERBOSE("sent response of %d byte(s)\n", reply_ctx->byte_cursor); \
|
||||
|
@ -421,36 +417,36 @@ int bus_unicast_message(Bus *s, WireMsg *msg, WireCtx *ctx, char *target_name, c
|
|||
do { \
|
||||
if (!(msg->flags & DBUS_FLAG_NO_REPLY_EXPECTED)) { \
|
||||
TRYST(wire_compose_error(reply_ctx, msg, (message))); \
|
||||
if (send(s->fds[i].fd, reply_ctx->data, reply_ctx->byte_cursor, 0) != reply_ctx->byte_cursor) { \
|
||||
if (send(client->fd, reply_ctx->data, reply_ctx->byte_cursor, 0) != reply_ctx->byte_cursor) { \
|
||||
return -1; \
|
||||
} \
|
||||
} \
|
||||
} while(0) \
|
||||
|
||||
int handle_hello(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
int handle_hello(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
(void)ctx;
|
||||
|
||||
int unique_name_index = TRYST(bus_client_assign_unique_name(s, i));
|
||||
BusName *name_entry = TRYPTR(bus_client_assign_unique_name(s, client));
|
||||
|
||||
_reply_begin("s") {
|
||||
TRYPTR(wire_set_string(reply_ctx, s->names[unique_name_index].name));
|
||||
TRYPTR(wire_set_string(reply_ctx, name_entry->name));
|
||||
} _reply_end()
|
||||
|
||||
_signal_begin("sss", "NameOwnerChanged") {
|
||||
/* Name with a new owner */
|
||||
TRYPTR(wire_set_string(&signal_reply_ctx, s->names[unique_name_index].name));
|
||||
TRYPTR(wire_set_string(&signal_reply_ctx, name_entry->name));
|
||||
/* Old owner or empty string if none */
|
||||
TRYPTR(wire_set_string(&signal_reply_ctx, ""));
|
||||
/* New owner or empty string if none */
|
||||
TRYPTR(wire_set_string(&signal_reply_ctx, ""));
|
||||
} _signal_end();
|
||||
|
||||
VERBOSE("assigned unique name '%s' to connection %d\n", s->names[unique_name_index].name, i);
|
||||
VERBOSE("assigned unique name '%s' to connection %d\n", name_entry->name, client->fd_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_request_name(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
if (s->clients[i].unique_name_index < 0) {
|
||||
int handle_request_name(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
if (!client->unique_name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -461,11 +457,11 @@ int handle_request_name(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *repl
|
|||
|
||||
int status_code = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
|
||||
|
||||
if (bus_client_assign_own_name(s, i, name_str) < 0) {
|
||||
if (bus_client_assign_own_name(s, client, name_str) < 0) {
|
||||
// TODO: report the actual error
|
||||
status_code = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
|
||||
|
||||
WARN("client '%s' (index=%d) couldn't acquire name '%s'\n", s->names[s->clients[i].unique_name_index].name, i, name_str);
|
||||
WARN("client '%s' (index=%d) couldn't acquire name '%s'\n", client->unique_name->name, client->fd_index, name_str);
|
||||
|
||||
free(name_str);
|
||||
}
|
||||
|
@ -481,30 +477,30 @@ int handle_request_name(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *repl
|
|||
/* Old owner or empty string if none */
|
||||
TRYPTR(wire_set_string(&signal_reply_ctx, ""));
|
||||
/* New owner or empty string if none */
|
||||
TRYPTR(wire_set_string(&signal_reply_ctx, s->names[s->clients[i].unique_name_index].name));
|
||||
TRYPTR(wire_set_string(&signal_reply_ctx, client->unique_name->name));
|
||||
} _signal_end();
|
||||
|
||||
VERBOSE("client '%s' (index=%d) now owns name '%s'\n", s->names[s->clients[i].unique_name_index].name, i, name_str);
|
||||
VERBOSE("client '%s' (index=%d) now owns name '%s'\n", client->unique_name->name, client->fd_index, name_str);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_get_name_owner(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
int handle_get_name_owner(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
char *name = TRYPTR(wire_get_name_string(ctx));
|
||||
|
||||
BusClient *target = bus_name_find_client(s, name);
|
||||
if (!target || target->unique_name_index < 0) {
|
||||
if (!target || !target->unique_name) {
|
||||
_reply_error("org.freedesktop.DBus.Error.NameHasNoOwner");
|
||||
return 0;
|
||||
}
|
||||
|
||||
_reply_begin("s") {
|
||||
TRYPTR(wire_set_string(reply_ctx, s->names[target->unique_name_index].name));
|
||||
TRYPTR(wire_set_string(reply_ctx, target->unique_name->name));
|
||||
} _reply_end()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_name_has_owner(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
int handle_name_has_owner(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
char *name = TRYPTR(wire_get_name_string(ctx));
|
||||
|
||||
BusClient *target = bus_name_find_client(s, name);
|
||||
|
@ -515,7 +511,7 @@ int handle_name_has_owner(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *re
|
|||
return 0;
|
||||
}
|
||||
|
||||
int handle_list_names(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
int handle_list_names(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
(void)ctx;
|
||||
|
||||
_reply_begin("as") {
|
||||
|
@ -530,7 +526,7 @@ int handle_list_names(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_
|
|||
|
||||
int left = s->names_count;
|
||||
for (int j = 0; j < BUS_MAX_NAMES && left > 0; j++) {
|
||||
if (s->names[j].name && s->names[j].client_index >= 0) {
|
||||
if (s->names[j].name && s->names[j].client) {
|
||||
left--;
|
||||
TRYPTR(wire_set_string(reply_ctx, s->names[j].name));
|
||||
}
|
||||
|
@ -541,7 +537,7 @@ int handle_list_names(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_
|
|||
return 0;
|
||||
}
|
||||
|
||||
int handle_list_activatable_names(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
int handle_list_activatable_names(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
(void)ctx;
|
||||
|
||||
STUB("handle_list_activatable_names", "always returns empty array");
|
||||
|
@ -554,7 +550,7 @@ int handle_list_activatable_names(Bus *s, int i, WireMsg *msg, WireCtx *ctx, Wir
|
|||
return 0;
|
||||
}
|
||||
|
||||
int handle_start_service_by_name(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
int handle_start_service_by_name(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
TRYPTR(wire_get_name_string(ctx));
|
||||
|
||||
/* unused flags value */
|
||||
|
@ -568,21 +564,20 @@ int handle_start_service_by_name(Bus *s, int i, WireMsg *msg, WireCtx *ctx, Wire
|
|||
return 0;
|
||||
}
|
||||
|
||||
int handle_add_match(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
int handle_add_match(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
char *match = TRYPTR(wire_get_string_check(ctx, 1, MATCH_RULE_MAX));
|
||||
|
||||
VERBOSE("client index %d adding match rule: '%s'\n", i, match);
|
||||
VERBOSE("client index %d adding match rule: '%s'\n", client->fd_index, match);
|
||||
|
||||
TRYST(bus_client_match_add(s, i, match));
|
||||
TRYST(bus_client_match_add(s, client, match));
|
||||
|
||||
_reply_begin("") {} _reply_end()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_remove_match(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
int handle_remove_match(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
char *match = TRYPTR(wire_get_string_check(ctx, 1, MATCH_RULE_MAX));
|
||||
|
||||
BusClient *client = &s->clients[i];
|
||||
int left = client->match_count;
|
||||
for (int j = 0; j < BUS_MAX_MATCH && left > 0; j++) {
|
||||
left--;
|
||||
|
@ -599,7 +594,7 @@ int handle_remove_match(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *repl
|
|||
return 0;
|
||||
}
|
||||
|
||||
int handle_get_connection_stats(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
int handle_get_connection_stats(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
(void)ctx;
|
||||
|
||||
TRYPTR(wire_get_name_string(ctx));
|
||||
|
@ -614,13 +609,13 @@ int handle_get_connection_stats(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireC
|
|||
return 0;
|
||||
}
|
||||
|
||||
int handle_get_connection_unix_process_id(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
int handle_get_connection_unix_process_id(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
(void)ctx;
|
||||
|
||||
char *name = TRYPTR(wire_get_name_string(ctx));
|
||||
|
||||
BusClient *target = bus_name_find_client(s, name);
|
||||
if (!target || target->unique_name_index < 0 || target->fd < 0) {
|
||||
if (!target || !target->unique_name || target->fd < 0) {
|
||||
_reply_error("org.freedesktop.DBus.Error.NameHasNoOwner");
|
||||
return 0;
|
||||
}
|
||||
|
@ -639,7 +634,7 @@ int handle_get_connection_unix_process_id(Bus *s, int i, WireMsg *msg, WireCtx *
|
|||
return 0;
|
||||
}
|
||||
|
||||
int handle_get_all_match_rules(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
int handle_get_all_match_rules(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
||||
(void)ctx;
|
||||
_reply_begin("a{sas}") {
|
||||
uint32_t *outer_array_len = TRYPTR(wire_set_u32(reply_ctx, 0));
|
||||
|
@ -649,14 +644,14 @@ int handle_get_all_match_rules(Bus *s, int i, WireMsg *msg, WireCtx *ctx, WireCt
|
|||
int left = s->names_count;
|
||||
for (int j = 0; j < BUS_MAX_NAMES && left > 0; j++) {
|
||||
BusName *n = &s->names[j];
|
||||
if (!n->name || n->client_index < 0 || *n->name != ':') {
|
||||
if (!n->name || !n->client || *n->name != ':') {
|
||||
continue;
|
||||
}
|
||||
left--;
|
||||
|
||||
TRYPTR(wire_write_align(reply_ctx, 8)); /* structs always aligned to 8 */
|
||||
|
||||
BusClient *c = &s->clients[s->names[j].client_index];
|
||||
BusClient *c = s->names[j].client;
|
||||
|
||||
TRYPTR(wire_set_string(reply_ctx, s->names[j].name)); /* unique name */
|
||||
|
||||
|
@ -703,16 +698,14 @@ static const int bus_method_handlers_count = sizeof(bus_method_handlers) / sizeo
|
|||
do { \
|
||||
if (!(msg.flags & DBUS_FLAG_NO_REPLY_EXPECTED)) { \
|
||||
TRYST(wire_compose_error(&reply_ctx, &msg, (message))); \
|
||||
if (send(s->fds[i].fd, reply_ctx.data, reply_ctx.byte_cursor, 0) != reply_ctx.byte_cursor) { \
|
||||
if (send(client->fd, reply_ctx.data, reply_ctx.byte_cursor, 0) != reply_ctx.byte_cursor) { \
|
||||
return -1; \
|
||||
} \
|
||||
} \
|
||||
} while(0) \
|
||||
|
||||
int bus_client_process_message(Bus *s, int i, WireCtx *ctx)
|
||||
int bus_client_process_message(Bus *s, BusClient *client, WireCtx *ctx)
|
||||
{
|
||||
BusClient *client = &s->clients[i];
|
||||
|
||||
WireMsg msg = {0};
|
||||
|
||||
TRYST(wire_parse_message(ctx, &msg));
|
||||
|
@ -737,7 +730,7 @@ int bus_client_process_message(Bus *s, int i, WireCtx *ctx)
|
|||
for (int j = 0; j < bus_method_handlers_count; j++) {
|
||||
const BusMethodHandler *handler = &bus_method_handlers[j];
|
||||
if (strcmp(handler->name, member_field->t.str) == 0) {
|
||||
TRYST(handler->handler(s, i, &msg, ctx, &reply_ctx));
|
||||
TRYST(handler->handler(s, client, &msg, ctx, &reply_ctx));
|
||||
goto end_nonfatal;
|
||||
}
|
||||
}
|
||||
|
@ -749,17 +742,17 @@ int bus_client_process_message(Bus *s, int i, WireCtx *ctx)
|
|||
// message needs to be routed
|
||||
// TODO: perform checks here like making sure all method calls have the 'member' field, etc.
|
||||
|
||||
if (client->unique_name_index < 0) {
|
||||
if (!client->unique_name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (destination_field->present) {
|
||||
if (bus_unicast_message(s, &msg, ctx, destination_field->t.str, s->names[client->unique_name_index].name, &reply_ctx) < 0) {
|
||||
if (bus_unicast_message(s, &msg, ctx, destination_field->t.str, client->unique_name->name, &reply_ctx) < 0) {
|
||||
_process_message_reply_error("xyz.hippoz.jitterbug.UnicastFailed");
|
||||
goto end_nonfatal;
|
||||
}
|
||||
} else {
|
||||
if (bus_broadcast_message(s, i, &msg, ctx, &reply_ctx) < 0) {
|
||||
if (bus_broadcast_message(s, client, &msg, ctx, &reply_ctx) < 0) {
|
||||
_process_message_reply_error("xyz.hippoz.jitterbug.BroadcastFailed");
|
||||
goto end_nonfatal;
|
||||
}
|
||||
|
@ -785,7 +778,7 @@ end_nonfatal:
|
|||
return 0;
|
||||
}
|
||||
|
||||
int bus_client_drain_messages(Bus *s, int ci, uint8_t *data, uint32_t data_len)
|
||||
int bus_client_drain_messages(Bus *s, BusClient *client, uint8_t *data, uint32_t data_len)
|
||||
{
|
||||
WireCtx ctx = {
|
||||
.byte_cursor = 0,
|
||||
|
@ -793,7 +786,7 @@ int bus_client_drain_messages(Bus *s, int ci, uint8_t *data, uint32_t data_len)
|
|||
.data_len = data_len
|
||||
};
|
||||
|
||||
TRYST(bus_client_process_message(s, ci, &ctx));
|
||||
TRYST(bus_client_process_message(s, client, &ctx));
|
||||
|
||||
int i = 0;
|
||||
for (; i < 10; i++) {
|
||||
|
@ -804,7 +797,7 @@ int bus_client_drain_messages(Bus *s, int ci, uint8_t *data, uint32_t data_len)
|
|||
ctx.data = ctx.data + ctx.byte_cursor;
|
||||
ctx.data_len = ctx.data_len - ctx.byte_cursor;
|
||||
ctx.byte_cursor = 0;
|
||||
TRYST(bus_client_process_message(s, ci, &ctx));
|
||||
TRYST(bus_client_process_message(s, client, &ctx));
|
||||
}
|
||||
|
||||
VERBOSE("processed %d messages - cursor:%d; data_len:%ld\n", i + 1, ctx.byte_cursor, ctx.data_len);
|
||||
|
@ -812,7 +805,7 @@ int bus_client_drain_messages(Bus *s, int ci, uint8_t *data, uint32_t data_len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define _client_die(m) do { bus_client_error(s,i,m); goto done; } while(0)
|
||||
#define _client_die(m) do { bus_client_error(s, &s->clients[i], m); goto done; } while(0)
|
||||
int bus_turn(Bus *s)
|
||||
{
|
||||
static const char agree_unix_fd[] = "ERROR\r\n";
|
||||
|
@ -836,23 +829,23 @@ int bus_turn(Bus *s)
|
|||
for (int i = 0; i < s->fd_num; i++) {
|
||||
int fd = s->fds[i].fd;
|
||||
if (s->fds[i].revents & POLLNVAL) {
|
||||
ERROR("Busurn: error: got POLLNVAL for fds[%d]. This is considered a bug in the server implementation.\n", i);
|
||||
ERROR("bus_turn: error: got POLLNVAL for fds[%d]. This is considered a bug in the server implementation.\n", i);
|
||||
return -1;
|
||||
}
|
||||
if (s->fds[i].revents & POLLERR) {
|
||||
if (fd == s->sock_fd) {
|
||||
ERROR("Busurn: error: got POLLERR for sock_fd\n");
|
||||
ERROR("bus_turn: error: got POLLERR for sock_fd\n");
|
||||
return -1;
|
||||
}
|
||||
bus_client_remove(s, i);
|
||||
bus_client_remove(s, &s->clients[i]);
|
||||
continue;
|
||||
}
|
||||
if (s->fds[i].revents & POLLHUP) {
|
||||
if (fd == s->sock_fd) {
|
||||
ERROR("Busurn: error: got POLLHUP for sock_fd\n");
|
||||
ERROR("bus_turn: error: got POLLHUP for sock_fd\n");
|
||||
return -1;
|
||||
}
|
||||
bus_client_remove(s, i);
|
||||
bus_client_remove(s, &s->clients[i]);
|
||||
continue;
|
||||
}
|
||||
if (s->fds[i].revents & POLLIN) {
|
||||
|
@ -876,7 +869,7 @@ int bus_turn(Bus *s)
|
|||
if (bytes <= 0) {
|
||||
// error during recv() OR client disconnected, disconnect the client
|
||||
// TODO: should we actually do this?
|
||||
bus_client_remove(s, i);
|
||||
bus_client_remove(s, &s->clients[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -917,7 +910,7 @@ int bus_turn(Bus *s)
|
|||
char *first_message_begin = data + 7; /* 7 = length of "BEGIN\r\n" */
|
||||
if (*first_message_begin == 'l' || *first_message_begin == 'B') {
|
||||
// This looks like a D-Bus message. Let's process it!
|
||||
if (bus_client_drain_messages(s, i, (uint8_t *)first_message_begin, data_buffer_len - 7) < 0) {
|
||||
if (bus_client_drain_messages(s, &s->clients[i], (uint8_t *)first_message_begin, data_buffer_len - 7) < 0) {
|
||||
_client_die("failed to process message");
|
||||
}
|
||||
}
|
||||
|
@ -930,7 +923,7 @@ int bus_turn(Bus *s)
|
|||
} break;
|
||||
|
||||
case BUS_CLIENT_STATE_READY: {
|
||||
if (bus_client_drain_messages(s, i, (uint8_t*)data, data_buffer_len) < 0) {
|
||||
if (bus_client_drain_messages(s, &s->clients[i], (uint8_t*)data, data_buffer_len) < 0) {
|
||||
_client_die("failed to process message");
|
||||
}
|
||||
} break;
|
||||
|
|
21
server.h
21
server.h
|
@ -30,20 +30,21 @@ enum {
|
|||
BUS_CLIENT_STATE_READY
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
typedef struct bus_name {
|
||||
char *name;
|
||||
struct bus_client *client;
|
||||
} BusName;
|
||||
|
||||
typedef struct bus_client {
|
||||
int fd;
|
||||
int16_t unique_name_index;
|
||||
BusName *unique_name;
|
||||
int16_t fd_index;
|
||||
uint8_t state;
|
||||
int8_t match_count;
|
||||
MatchRule *matches[BUS_MAX_MATCH];
|
||||
int16_t owned_names[BUS_NAMES_PER_CLIENT];
|
||||
BusName *owned_names[BUS_NAMES_PER_CLIENT];
|
||||
} BusClient;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int32_t client_index;
|
||||
} BusName;
|
||||
|
||||
typedef struct {
|
||||
int sock_fd;
|
||||
int fd_num;
|
||||
|
@ -57,12 +58,12 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int (*handler)(Bus *bus, int client_index, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx);
|
||||
int (*handler)(Bus *bus, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx);
|
||||
} BusMethodHandler;
|
||||
|
||||
|
||||
int bus_client_add(Bus *s, int fd);
|
||||
void bus_client_remove(Bus *s, int i);
|
||||
void bus_client_remove(Bus *s, BusClient *client);
|
||||
void bus_free(Bus *s);
|
||||
Bus *bus_create(const char *socket_path);
|
||||
int bus_turn(Bus *s);
|
||||
|
|
Loading…
Reference in a new issue