Compare commits
No commits in common. "2fb13032abaa92213e72cc1f5975210a8a5b1097" and "796630d74eeed6cd8ae656faca9e0259662a76e7" have entirely different histories.
2fb13032ab
...
796630d74e
8 changed files with 244 additions and 238 deletions
2
main.c
2
main.c
|
@ -27,7 +27,7 @@ int main(int argc, char *argv[])
|
||||||
/* we handle send() errors directly in the code */
|
/* we handle send() errors directly in the code */
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
Bus *srv = bus_create(socket_path);
|
bus_t *srv = bus_create(socket_path);
|
||||||
if (srv == NULL) {
|
if (srv == NULL) {
|
||||||
fprintf(stderr, "server_create failed\n");
|
fprintf(stderr, "server_create failed\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
25
match.c
25
match.c
|
@ -8,7 +8,7 @@
|
||||||
#include "try.h"
|
#include "try.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
void match_rule_free(MatchRule *rule)
|
void match_rule_free(match_rule_t *rule)
|
||||||
{
|
{
|
||||||
if (rule) {
|
if (rule) {
|
||||||
free(rule->rule_string);
|
free(rule->rule_string);
|
||||||
|
@ -27,18 +27,18 @@ void match_rule_free(MatchRule *rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MatchRule *match_rule_from_string(char *d)
|
match_rule_t *match_rule_from_string(char *d)
|
||||||
{
|
{
|
||||||
char *key = NULL;
|
char *key = NULL;
|
||||||
char acc[MATCH_RULE_MAX];
|
char acc[MATCH_RULE_MAX];
|
||||||
int acci = 0;
|
int acci = 0;
|
||||||
MatchRule *rule;
|
match_rule_t *rule;
|
||||||
|
|
||||||
if (strlen(d) >= MATCH_RULE_MAX) {
|
if (strlen(d) >= MATCH_RULE_MAX) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rule = calloc(sizeof(MatchRule), 1);
|
rule = calloc(sizeof(match_rule_t), 1);
|
||||||
if (!rule) {
|
if (!rule) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -178,16 +178,17 @@ fail:
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
int match_check_sender(Bus *s, BusClient *sender_client, MatchRule *rule)
|
int match_check_sender(bus_t *s, int sender_index, match_rule_t *rule)
|
||||||
{
|
{
|
||||||
|
bus_client_t *sender_client = &s->clients[sender_index];
|
||||||
if (rule->sender) {
|
if (rule->sender) {
|
||||||
if (sender_client->unique_name) {
|
if (sender_client->unique_name_index >= 0) {
|
||||||
if (strcmp(rule->sender, sender_client->unique_name->name) == 0) {
|
if (strcmp(rule->sender, s->names[sender_client->unique_name_index].name) == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i < BUS_NAMES_PER_CLIENT; i++) {
|
for (int i = 0; i < BUS_NAMES_PER_CLIENT; i++) {
|
||||||
if (sender_client->owned_names[i] && strcmp(rule->sender, sender_client->owned_names[i]->name) == 0) {
|
if (sender_client->owned_names[i] >= 0 && strcmp(rule->sender, s->names[sender_client->owned_names[i]].name) == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,19 +197,19 @@ int match_check_sender(Bus *s, BusClient *sender_client, MatchRule *rule)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int match_rule_check(Bus *s, BusClient *sender_client, MatchRule *rule, WireMsg *msg, WireCtx *ctx)
|
int match_rule_check(bus_t *s, int sender_index, match_rule_t *rule, wire_message_t *msg, wire_context_t *ctx)
|
||||||
{
|
{
|
||||||
if (rule->type && msg->type != rule->type) {
|
if (rule->type && msg->type != rule->type) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sender_client) {
|
if (sender_index < 0) {
|
||||||
// if the sender is negative, we assume the message is coming from the message bus
|
// 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) {
|
if (rule->sender && strcmp(rule->sender, "org.freedesktop.DBus") != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (match_check_sender(s, sender_client, rule) < 0) {
|
if (match_check_sender(s, sender_index, rule) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,7 +220,7 @@ int match_rule_check(Bus *s, BusClient *sender_client, MatchRule *rule, WireMsg
|
||||||
/* todo: path_namespace */
|
/* todo: path_namespace */
|
||||||
_check_header_field_str(destination, DBUS_HEADER_FIELD_DESTINATION);
|
_check_header_field_str(destination, DBUS_HEADER_FIELD_DESTINATION);
|
||||||
|
|
||||||
WireMsgBodyString strings[MATCH_RULE_MAX_ARG];
|
wire_message_body_string_t strings[MATCH_RULE_MAX_ARG];
|
||||||
memset(strings, 0, sizeof(strings));
|
memset(strings, 0, sizeof(strings));
|
||||||
/* TODO: handle failure */
|
/* TODO: handle failure */
|
||||||
TRYST(wire_collect_strings(ctx, msg, strings, MATCH_RULE_MAX_ARG));
|
TRYST(wire_collect_strings(ctx, msg, strings, MATCH_RULE_MAX_ARG));
|
||||||
|
|
6
match.h
6
match.h
|
@ -6,8 +6,8 @@
|
||||||
#include "wire.h"
|
#include "wire.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
|
||||||
void match_rule_free(MatchRule *rule);
|
void match_rule_free(match_rule_t *rule);
|
||||||
MatchRule *match_rule_from_string(char *d);
|
match_rule_t *match_rule_from_string(char *d);
|
||||||
int match_rule_check(Bus *s, BusClient *sender_client, MatchRule *rule, WireMsg *msg, WireCtx *ctx);
|
int match_rule_check(bus_t *s, int sender_index, match_rule_t *rule, wire_message_t *msg, wire_context_t *ctx);
|
||||||
|
|
||||||
#endif // _JITTERBUG__MATCH_H
|
#endif // _JITTERBUG__MATCH_H
|
||||||
|
|
286
server.c
286
server.c
|
@ -30,21 +30,21 @@ uint64_t hashmap_hash(const char *bytes, size_t bytes_n, size_t map_len)
|
||||||
return (hash % map_len);
|
return (hash % map_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bus_free(Bus *s)
|
void bus_free(bus_t *s)
|
||||||
{
|
{
|
||||||
if (!s) return;
|
if (!s) return;
|
||||||
if (s->sock_fd >= 0) close(s->sock_fd);
|
if (s->sock_fd >= 0) close(s->sock_fd);
|
||||||
if (s->urandom_fd >= 0) close(s->urandom_fd);
|
if (s->urandom_fd >= 0) close(s->urandom_fd);
|
||||||
// freeing all clients will also free all matches and names
|
// freeing all clients will also free all matches and names
|
||||||
for (int i = 0; i < BUS_MAX_CLIENTS; i++) {
|
for (int i = 0; i < BUS_MAX_CLIENTS; i++) {
|
||||||
bus_client_remove(s, &s->clients[i]);
|
bus_client_remove(s, i);
|
||||||
}
|
}
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bus *bus_create(const char *socket_path)
|
bus_t *bus_create(const char *socket_path)
|
||||||
{
|
{
|
||||||
Bus *s = malloc(sizeof(Bus));
|
bus_t *s = malloc(sizeof(bus_t));
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -86,10 +86,9 @@ Bus *bus_create(const char *socket_path)
|
||||||
|
|
||||||
for (int i = 0; i < BUS_MAX_CLIENTS; i++) {
|
for (int i = 0; i < BUS_MAX_CLIENTS; i++) {
|
||||||
s->clients[i].fd = -1;
|
s->clients[i].fd = -1;
|
||||||
s->clients[i].unique_name = NULL;
|
s->clients[i].unique_name_index = -1;
|
||||||
s->clients[i].state = BUS_CLIENT_STATE_NONE;
|
s->clients[i].state = BUS_CLIENT_STATE_NONE;
|
||||||
s->clients[i].match_count = 0;
|
s->clients[i].match_count = 0;
|
||||||
s->clients[i].fd_index = i;
|
|
||||||
s->fds[i].fd = -1;
|
s->fds[i].fd = -1;
|
||||||
s->fds[i].events = 0;
|
s->fds[i].events = 0;
|
||||||
s->fds[i].revents = 0;
|
s->fds[i].revents = 0;
|
||||||
|
@ -97,12 +96,12 @@ Bus *bus_create(const char *socket_path)
|
||||||
s->clients[i].matches[j] = NULL;
|
s->clients[i].matches[j] = NULL;
|
||||||
}
|
}
|
||||||
for (int j = 0; j < BUS_NAMES_PER_CLIENT; j++) {
|
for (int j = 0; j < BUS_NAMES_PER_CLIENT; j++) {
|
||||||
s->clients[i].owned_names[j] = NULL;
|
s->clients[i].owned_names[j] = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < BUS_MAX_NAMES; i++) {
|
for (int i = 0; i < BUS_MAX_NAMES; i++) {
|
||||||
s->names[i].client = NULL;
|
s->names[i].client_index = -1;
|
||||||
s->names[i].name = NULL;
|
s->names[i].name = NULL;
|
||||||
}
|
}
|
||||||
s->names_count = 0;
|
s->names_count = 0;
|
||||||
|
@ -122,12 +121,12 @@ defer_fail:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bus_client_add(Bus *s, int fd)
|
int bus_client_add(bus_t *s, int fd)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < BUS_MAX_CLIENTS; i++) {
|
for (int i = 0; i < BUS_MAX_CLIENTS; i++) {
|
||||||
if (s->clients[i].fd < 0) {
|
if (s->clients[i].fd < 0) {
|
||||||
s->clients[i].fd = fd;
|
s->clients[i].fd = fd;
|
||||||
s->clients[i].unique_name = NULL;
|
s->clients[i].unique_name_index = -1;
|
||||||
s->clients[i].state = BUS_CLIENT_STATE_WAIT_AUTH;
|
s->clients[i].state = BUS_CLIENT_STATE_WAIT_AUTH;
|
||||||
s->fds[i].fd = fd;
|
s->fds[i].fd = fd;
|
||||||
s->fds[i].events = POLLIN;
|
s->fds[i].events = POLLIN;
|
||||||
|
@ -138,7 +137,7 @@ int bus_client_add(Bus *s, int fd)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bus_name_find(Bus *s, char *name)
|
int bus_name_find(bus_t *s, char *name)
|
||||||
{
|
{
|
||||||
int bucket = hashmap_hash(name, strlen(name), BUS_MAX_NAMES);
|
int bucket = hashmap_hash(name, strlen(name), BUS_MAX_NAMES);
|
||||||
|
|
||||||
|
@ -151,53 +150,55 @@ int bus_name_find(Bus *s, char *name)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BusClient *bus_name_find_client(Bus *s, char *name)
|
bus_client_t *bus_name_find_client(bus_t *s, char *name)
|
||||||
{
|
{
|
||||||
int name_index = bus_name_find(s, name);
|
int name_index = bus_name_find(s, name);
|
||||||
if (name_index < 0) {
|
if (name_index < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!s->names[name_index].client) {
|
if (s->names[name_index].client_index < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->names[name_index].client->state != BUS_CLIENT_STATE_READY) {
|
if (s->clients[s->names[name_index].client_index].state != BUS_CLIENT_STATE_READY) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s->names[name_index].client;
|
return &s->clients[s->names[name_index].client_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
BusName *bus_name_add(Bus *s, char *name, BusClient *client)
|
int bus_name_add(bus_t *s, char *name, int client_index)
|
||||||
{
|
{
|
||||||
if (bus_name_find(s, name) >= 0) {
|
if (bus_name_find(s, name) >= 0) {
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bucket = hashmap_hash(name, strlen(name), BUS_MAX_NAMES);
|
int bucket = hashmap_hash(name, strlen(name), BUS_MAX_NAMES);
|
||||||
|
|
||||||
for (int i = bucket; i < bucket + 12 && i < BUS_MAX_NAMES; i++) {
|
for (int i = bucket; i < bucket + 12 && i < BUS_MAX_NAMES; i++) {
|
||||||
if (!s->names[i].client) {
|
if (s->names[i].client_index == -1) {
|
||||||
for (int j = 0; j < BUS_NAMES_PER_CLIENT; j++) {
|
for (int j = 0; j < BUS_NAMES_PER_CLIENT; j++) {
|
||||||
if (!client->owned_names[j]) {
|
if (s->clients[client_index].owned_names[j] < 0) {
|
||||||
client->owned_names[j] = &s->names[i];
|
s->clients[client_index].owned_names[j] = i;
|
||||||
s->names[i].client = client;
|
s->names[i].client_index = client_index;
|
||||||
s->names[i].name = name;
|
s->names[i].name = name;
|
||||||
s->names_count++;
|
s->names_count++;
|
||||||
return &s->names[i];
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bus_client_match_add(Bus *s, BusClient *c, char *match)
|
int bus_client_match_add(bus_t *s, int client_index, char *match)
|
||||||
{
|
{
|
||||||
|
bus_client_t *c = &s->clients[client_index];
|
||||||
|
|
||||||
for (int i = 0; i < BUS_MAX_MATCH; i++) {
|
for (int i = 0; i < BUS_MAX_MATCH; i++) {
|
||||||
if (!c->matches[i]) {
|
if (!c->matches[i]) {
|
||||||
c->matches[i] = match_rule_from_string(match);
|
c->matches[i] = match_rule_from_string(match);
|
||||||
|
@ -209,66 +210,64 @@ int bus_client_match_add(Bus *s, BusClient *c, char *match)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
BusName *bus_client_assign_unique_name(Bus *s, BusClient *client)
|
int bus_client_assign_unique_name(bus_t *s, int i)
|
||||||
{
|
{
|
||||||
if (client->unique_name) {
|
bus_client_t *c = &s->clients[i];
|
||||||
return NULL;
|
if (c->unique_name_index != -1) {
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
uint32_t id = 0;
|
uint32_t id = 0;
|
||||||
|
|
||||||
if (read(s->urandom_fd, &id, sizeof(uint32_t)) != sizeof(uint32_t)) {
|
if (read(s->urandom_fd, &id, sizeof(uint32_t)) != sizeof(uint32_t)) {
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *name_str = malloc(sizeof(char) * 16);
|
char *name = 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) {
|
if (!name) {
|
||||||
free(name_str);
|
return -1;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
client->unique_name = name;
|
|
||||||
|
|
||||||
return name;
|
if (snprintf(name, 16, ":1.%"PRIu32, id) < 0) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bus_client_assign_own_name(Bus *s, BusClient *client, char *name)
|
int bus_client_assign_own_name(bus_t *s, int i, char *name)
|
||||||
{
|
{
|
||||||
if (!name || *name == ':' || *name == '\0') {
|
if (!name || *name == ':' || *name == '\0') {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRYPTR(bus_name_add(s, name, client));
|
TRYST(bus_name_add(s, name, i));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bus_name_remove(Bus *s, BusName *name)
|
void bus_name_remove(bus_t *s, int i)
|
||||||
{
|
{
|
||||||
if (!name) {
|
if (i >= 0) {
|
||||||
return;
|
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->name) {
|
|
||||||
free(name->name);
|
|
||||||
name->name = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
name->client = NULL;
|
|
||||||
|
|
||||||
s->names_count--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bus_client_remove(Bus *s, BusClient *c)
|
void bus_client_remove(bus_t *s, int i)
|
||||||
{
|
{
|
||||||
|
bus_client_t *c = &s->clients[i];
|
||||||
|
|
||||||
if (c->fd >= 0) {
|
if (c->fd >= 0) {
|
||||||
close(c->fd);
|
close(c->fd);
|
||||||
}
|
}
|
||||||
|
@ -279,34 +278,38 @@ void bus_client_remove(Bus *s, BusClient *c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int j = 0; j < BUS_NAMES_PER_CLIENT; j++) {
|
for (int j = 0; j < BUS_NAMES_PER_CLIENT; j++) {
|
||||||
bus_name_remove(s, c->owned_names[j]);
|
if (c->owned_names[j] >= 0) {
|
||||||
c->owned_names[j] = NULL;
|
bus_name_remove(s, c->owned_names[j]);
|
||||||
|
c->owned_names[j] = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c->unique_name = NULL;
|
c->unique_name_index = -1;
|
||||||
c->match_count = 0;
|
c->match_count = 0;
|
||||||
c->fd = -1;
|
c->fd = -1;
|
||||||
c->state = BUS_CLIENT_STATE_NONE;
|
c->state = BUS_CLIENT_STATE_NONE;
|
||||||
s->fds[c->fd_index].fd = -1;
|
s->fds[i].fd = -1;
|
||||||
s->fds[c->fd_index].events = 0;
|
s->fds[i].events = 0;
|
||||||
s->fds[c->fd_index].revents = 0;
|
s->fds[i].revents = 0;
|
||||||
s->clients_count--;
|
s->clients_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bus_client_error(Bus *s, BusClient *client, const char *msg)
|
void bus_client_error(bus_t *s, int i, const char *msg)
|
||||||
{
|
{
|
||||||
WARN("removing client %d due to error: %s\n", client->fd_index, msg);
|
WARN("removing client %d due to error: %s\n", i, msg);
|
||||||
send(client->fd, msg, strlen(msg), 0);
|
send(s->clients[i].fd, msg, strlen(msg), 0);
|
||||||
bus_client_remove(s, client);
|
bus_client_remove(s, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bus_broadcast_message(Bus *s, BusClient *sender_client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx)
|
int bus_broadcast_message(bus_t *s, int sender_index, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx)
|
||||||
{
|
{
|
||||||
uint32_t body_end = ctx->byte_cursor + msg->body_length;
|
uint32_t body_end = ctx->byte_cursor + msg->body_length;
|
||||||
if (body_end >= ctx->data_len) {
|
if (body_end >= ctx->data_len) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bus_client_t *sender_client = &s->clients[sender_index];
|
||||||
|
|
||||||
int left = s->clients_count;
|
int left = s->clients_count;
|
||||||
for (int i = 0; i < BUS_MAX_CLIENTS && left > 0; i++) {
|
for (int i = 0; i < BUS_MAX_CLIENTS && left > 0; i++) {
|
||||||
if (s->clients[i].state != BUS_CLIENT_STATE_READY) {
|
if (s->clients[i].state != BUS_CLIENT_STATE_READY) {
|
||||||
|
@ -315,7 +318,7 @@ int bus_broadcast_message(Bus *s, BusClient *sender_client, WireMsg *msg, WireCt
|
||||||
|
|
||||||
left--;
|
left--;
|
||||||
|
|
||||||
BusClient *c = &s->clients[i];
|
bus_client_t *c = &s->clients[i];
|
||||||
int match_left = c->match_count;
|
int match_left = c->match_count;
|
||||||
for (int j = 0; j < BUS_MAX_MATCH && match_left > 0; j++) {
|
for (int j = 0; j < BUS_MAX_MATCH && match_left > 0; j++) {
|
||||||
if (!c->matches[j]) {
|
if (!c->matches[j]) {
|
||||||
|
@ -325,8 +328,8 @@ int bus_broadcast_message(Bus *s, BusClient *sender_client, WireMsg *msg, WireCt
|
||||||
match_left--;
|
match_left--;
|
||||||
|
|
||||||
uint32_t previous_cursor = ctx->byte_cursor;
|
uint32_t previous_cursor = ctx->byte_cursor;
|
||||||
if (match_rule_check(s, sender_client, c->matches[j], msg, ctx) >= 0) {
|
if (match_rule_check(s, sender_index, c->matches[j], msg, ctx) >= 0) {
|
||||||
TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, sender_client->unique_name->name));
|
TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, s->names[sender_client->unique_name_index].name));
|
||||||
TRYST(send(c->fd, reply_ctx->data, reply_ctx->byte_cursor, 0));
|
TRYST(send(c->fd, reply_ctx->data, reply_ctx->byte_cursor, 0));
|
||||||
// TODO?
|
// TODO?
|
||||||
memset(reply_ctx->data, 0, reply_ctx->data_len);
|
memset(reply_ctx->data, 0, reply_ctx->data_len);
|
||||||
|
@ -342,7 +345,7 @@ int bus_broadcast_message(Bus *s, BusClient *sender_client, WireMsg *msg, WireCt
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bus_broadcast_signal(Bus *s, BusClient *client, WireCtx *ctx, WireMsg *msg)
|
int bus_broadcast_signal(bus_t *s, int sender_index, wire_context_t *ctx, wire_message_t *msg)
|
||||||
{
|
{
|
||||||
int left = s->clients_count;
|
int left = s->clients_count;
|
||||||
for (int i = 0; i < BUS_MAX_CLIENTS && left > 0; i++) {
|
for (int i = 0; i < BUS_MAX_CLIENTS && left > 0; i++) {
|
||||||
|
@ -352,7 +355,7 @@ int bus_broadcast_signal(Bus *s, BusClient *client, WireCtx *ctx, WireMsg *msg)
|
||||||
|
|
||||||
left--;
|
left--;
|
||||||
|
|
||||||
BusClient *c = &s->clients[i];
|
bus_client_t *c = &s->clients[i];
|
||||||
int match_left = c->match_count;
|
int match_left = c->match_count;
|
||||||
for (int j = 0; j < BUS_MAX_MATCH && match_left > 0; j++) {
|
for (int j = 0; j < BUS_MAX_MATCH && match_left > 0; j++) {
|
||||||
if (!c->matches[j]) {
|
if (!c->matches[j]) {
|
||||||
|
@ -360,7 +363,7 @@ int bus_broadcast_signal(Bus *s, BusClient *client, WireCtx *ctx, WireMsg *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
match_left--;
|
match_left--;
|
||||||
if (match_rule_check(s, client, c->matches[j], msg, ctx) >= 0) {
|
if (match_rule_check(s, sender_index, c->matches[j], msg, ctx) >= 0) {
|
||||||
uint32_t previous_cursor = ctx->byte_cursor;
|
uint32_t previous_cursor = ctx->byte_cursor;
|
||||||
TRYST(send(c->fd, ctx->data, ctx->byte_cursor, 0));
|
TRYST(send(c->fd, ctx->data, ctx->byte_cursor, 0));
|
||||||
ctx->byte_cursor = previous_cursor;
|
ctx->byte_cursor = previous_cursor;
|
||||||
|
@ -371,9 +374,9 @@ int bus_broadcast_signal(Bus *s, BusClient *client, WireCtx *ctx, WireMsg *msg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bus_unicast_message(Bus *s, WireMsg *msg, WireCtx *ctx, char *target_name, char *sender_unique_name, WireCtx *reply_ctx)
|
int bus_unicast_message(bus_t *s, wire_message_t *msg, wire_context_t *ctx, char *target_name, char *sender_unique_name, wire_context_t *reply_ctx)
|
||||||
{
|
{
|
||||||
BusClient *target = TRYPTR(bus_name_find_client(s, target_name));
|
bus_client_t *target = TRYPTR(bus_name_find_client(s, target_name));
|
||||||
TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, sender_unique_name));
|
TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, sender_unique_name));
|
||||||
TRYST(send(target->fd, reply_ctx->data, reply_ctx->byte_cursor, 0));
|
TRYST(send(target->fd, reply_ctx->data, reply_ctx->byte_cursor, 0));
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -384,18 +387,18 @@ int bus_unicast_message(Bus *s, WireMsg *msg, WireCtx *ctx, char *target_name, c
|
||||||
uint32_t signal_body_start = 0; \
|
uint32_t signal_body_start = 0; \
|
||||||
uint8_t signal_reply_data[8192]; \
|
uint8_t signal_reply_data[8192]; \
|
||||||
memset(signal_reply_data, 0, 8192); \
|
memset(signal_reply_data, 0, 8192); \
|
||||||
WireCtx signal_reply_ctx = { \
|
wire_context_t signal_reply_ctx = { \
|
||||||
.byte_cursor = 0, \
|
.byte_cursor = 0, \
|
||||||
.data = signal_reply_data, \
|
.data = signal_reply_data, \
|
||||||
.data_len = 8192, \
|
.data_len = 8192, \
|
||||||
}; \
|
}; \
|
||||||
WireMsg signal_reply_msg = {0}; \
|
wire_message_t signal_reply_msg = {0}; \
|
||||||
TRYST(wire_compose_signal(&signal_reply_ctx, &signal_reply_msg, (M_sig), (M_member), &signal_body_length)); \
|
TRYST(wire_compose_signal(&signal_reply_ctx, &signal_reply_msg, (M_sig), (M_member), &signal_body_length)); \
|
||||||
signal_body_start = signal_reply_ctx.byte_cursor;
|
signal_body_start = signal_reply_ctx.byte_cursor;
|
||||||
|
|
||||||
#define _signal_end() \
|
#define _signal_end() \
|
||||||
*signal_body_length = signal_reply_ctx.byte_cursor - signal_body_start; \
|
*signal_body_length = signal_reply_ctx.byte_cursor - signal_body_start; \
|
||||||
TRYST(bus_broadcast_signal(s, NULL, &signal_reply_ctx, &signal_reply_msg)); \
|
TRYST(bus_broadcast_signal(s, -1, &signal_reply_ctx, &signal_reply_msg)); \
|
||||||
|
|
||||||
|
|
||||||
#define _reply_begin(M_sig) \
|
#define _reply_begin(M_sig) \
|
||||||
|
@ -407,7 +410,7 @@ int bus_unicast_message(Bus *s, WireMsg *msg, WireCtx *ctx, char *target_name, c
|
||||||
|
|
||||||
#define _reply_end() \
|
#define _reply_end() \
|
||||||
*body_length = reply_ctx->byte_cursor - body_start; \
|
*body_length = reply_ctx->byte_cursor - body_start; \
|
||||||
if (send(client->fd, reply_ctx->data, reply_ctx->byte_cursor, 0) != reply_ctx->byte_cursor) { \
|
if (send(s->fds[i].fd, reply_ctx->data, reply_ctx->byte_cursor, 0) != reply_ctx->byte_cursor) { \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
VERBOSE("sent response of %d byte(s)\n", reply_ctx->byte_cursor); \
|
VERBOSE("sent response of %d byte(s)\n", reply_ctx->byte_cursor); \
|
||||||
|
@ -417,36 +420,36 @@ int bus_unicast_message(Bus *s, WireMsg *msg, WireCtx *ctx, char *target_name, c
|
||||||
do { \
|
do { \
|
||||||
if (!(msg->flags & DBUS_FLAG_NO_REPLY_EXPECTED)) { \
|
if (!(msg->flags & DBUS_FLAG_NO_REPLY_EXPECTED)) { \
|
||||||
TRYST(wire_compose_error(reply_ctx, msg, (message))); \
|
TRYST(wire_compose_error(reply_ctx, msg, (message))); \
|
||||||
if (send(client->fd, reply_ctx->data, reply_ctx->byte_cursor, 0) != reply_ctx->byte_cursor) { \
|
if (send(s->fds[i].fd, reply_ctx->data, reply_ctx->byte_cursor, 0) != reply_ctx->byte_cursor) { \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} while(0) \
|
} while(0) \
|
||||||
|
|
||||||
int handle_hello(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_hello(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
|
|
||||||
BusName *name_entry = TRYPTR(bus_client_assign_unique_name(s, client));
|
int unique_name_index = TRYST(bus_client_assign_unique_name(s, i));
|
||||||
|
|
||||||
_reply_begin("s") {
|
_reply_begin("s") {
|
||||||
TRYPTR(wire_set_string(reply_ctx, name_entry->name));
|
TRYPTR(wire_set_string(reply_ctx, s->names[unique_name_index].name));
|
||||||
} _reply_end()
|
} _reply_end()
|
||||||
|
|
||||||
_signal_begin("sss", "NameOwnerChanged") {
|
_signal_begin("sss", "NameOwnerChanged") {
|
||||||
/* Name with a new owner */
|
/* Name with a new owner */
|
||||||
TRYPTR(wire_set_string(&signal_reply_ctx, name_entry->name));
|
TRYPTR(wire_set_string(&signal_reply_ctx, s->names[unique_name_index].name));
|
||||||
/* Old owner or empty string if none */
|
/* Old owner or empty string if none */
|
||||||
TRYPTR(wire_set_string(&signal_reply_ctx, ""));
|
TRYPTR(wire_set_string(&signal_reply_ctx, ""));
|
||||||
/* New owner or empty string if none */
|
/* New owner or empty string if none */
|
||||||
TRYPTR(wire_set_string(&signal_reply_ctx, ""));
|
TRYPTR(wire_set_string(&signal_reply_ctx, ""));
|
||||||
} _signal_end();
|
} _signal_end();
|
||||||
|
|
||||||
VERBOSE("assigned unique name '%s' to connection %d\n", name_entry->name, client->fd_index);
|
VERBOSE("assigned unique name '%s' to connection %d\n", s->names[unique_name_index].name, i);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_request_name(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_request_name(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
if (!client->unique_name) {
|
if (s->clients[i].unique_name_index < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,11 +460,11 @@ int handle_request_name(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, W
|
||||||
|
|
||||||
int status_code = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
|
int status_code = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
|
||||||
|
|
||||||
if (bus_client_assign_own_name(s, client, name_str) < 0) {
|
if (bus_client_assign_own_name(s, i, name_str) < 0) {
|
||||||
// TODO: report the actual error
|
// TODO: report the actual error
|
||||||
status_code = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
|
status_code = DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
|
||||||
|
|
||||||
WARN("client '%s' (index=%d) couldn't acquire name '%s'\n", client->unique_name->name, client->fd_index, name_str);
|
WARN("client '%s' (index=%d) couldn't acquire name '%s'\n", s->names[s->clients[i].unique_name_index].name, i, name_str);
|
||||||
|
|
||||||
free(name_str);
|
free(name_str);
|
||||||
}
|
}
|
||||||
|
@ -477,33 +480,33 @@ int handle_request_name(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, W
|
||||||
/* Old owner or empty string if none */
|
/* Old owner or empty string if none */
|
||||||
TRYPTR(wire_set_string(&signal_reply_ctx, ""));
|
TRYPTR(wire_set_string(&signal_reply_ctx, ""));
|
||||||
/* New owner or empty string if none */
|
/* New owner or empty string if none */
|
||||||
TRYPTR(wire_set_string(&signal_reply_ctx, client->unique_name->name));
|
TRYPTR(wire_set_string(&signal_reply_ctx, s->names[s->clients[i].unique_name_index].name));
|
||||||
} _signal_end();
|
} _signal_end();
|
||||||
|
|
||||||
VERBOSE("client '%s' (index=%d) now owns name '%s'\n", client->unique_name->name, client->fd_index, name_str);
|
VERBOSE("client '%s' (index=%d) now owns name '%s'\n", s->names[s->clients[i].unique_name_index].name, i, name_str);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_get_name_owner(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_get_name_owner(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
char *name = TRYPTR(wire_get_name_string(ctx));
|
char *name = TRYPTR(wire_get_name_string(ctx));
|
||||||
|
|
||||||
BusClient *target = bus_name_find_client(s, name);
|
bus_client_t *target = bus_name_find_client(s, name);
|
||||||
if (!target || !target->unique_name) {
|
if (!target || target->unique_name_index < 0) {
|
||||||
_reply_error("org.freedesktop.DBus.Error.NameHasNoOwner");
|
_reply_error("org.freedesktop.DBus.Error.NameHasNoOwner");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_reply_begin("s") {
|
_reply_begin("s") {
|
||||||
TRYPTR(wire_set_string(reply_ctx, target->unique_name->name));
|
TRYPTR(wire_set_string(reply_ctx, s->names[target->unique_name_index].name));
|
||||||
} _reply_end()
|
} _reply_end()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_name_has_owner(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_name_has_owner(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
char *name = TRYPTR(wire_get_name_string(ctx));
|
char *name = TRYPTR(wire_get_name_string(ctx));
|
||||||
|
|
||||||
BusClient *target = bus_name_find_client(s, name);
|
bus_client_t *target = bus_name_find_client(s, name);
|
||||||
|
|
||||||
_reply_begin("b") {
|
_reply_begin("b") {
|
||||||
TRYPTR(wire_set_u32(reply_ctx, target ? 1 : 0));
|
TRYPTR(wire_set_u32(reply_ctx, target ? 1 : 0));
|
||||||
|
@ -511,7 +514,7 @@ int handle_name_has_owner(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_list_names(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_list_names(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
|
|
||||||
_reply_begin("as") {
|
_reply_begin("as") {
|
||||||
|
@ -526,7 +529,7 @@ int handle_list_names(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, Wir
|
||||||
|
|
||||||
int left = s->names_count;
|
int left = s->names_count;
|
||||||
for (int j = 0; j < BUS_MAX_NAMES && left > 0; j++) {
|
for (int j = 0; j < BUS_MAX_NAMES && left > 0; j++) {
|
||||||
if (s->names[j].name && s->names[j].client) {
|
if (s->names[j].name && s->names[j].client_index >= 0) {
|
||||||
left--;
|
left--;
|
||||||
TRYPTR(wire_set_string(reply_ctx, s->names[j].name));
|
TRYPTR(wire_set_string(reply_ctx, s->names[j].name));
|
||||||
}
|
}
|
||||||
|
@ -537,7 +540,7 @@ int handle_list_names(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, Wir
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_list_activatable_names(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_list_activatable_names(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
|
|
||||||
STUB("handle_list_activatable_names", "always returns empty array");
|
STUB("handle_list_activatable_names", "always returns empty array");
|
||||||
|
@ -550,7 +553,7 @@ int handle_list_activatable_names(Bus *s, BusClient *client, WireMsg *msg, WireC
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_start_service_by_name(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_start_service_by_name(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
TRYPTR(wire_get_name_string(ctx));
|
TRYPTR(wire_get_name_string(ctx));
|
||||||
|
|
||||||
/* unused flags value */
|
/* unused flags value */
|
||||||
|
@ -564,20 +567,21 @@ int handle_start_service_by_name(Bus *s, BusClient *client, WireMsg *msg, WireCt
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_add_match(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_add_match(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
char *match = TRYPTR(wire_get_string_check(ctx, 1, MATCH_RULE_MAX));
|
char *match = TRYPTR(wire_get_string_check(ctx, 1, MATCH_RULE_MAX));
|
||||||
|
|
||||||
VERBOSE("client index %d adding match rule: '%s'\n", client->fd_index, match);
|
VERBOSE("client index %d adding match rule: '%s'\n", i, match);
|
||||||
|
|
||||||
TRYST(bus_client_match_add(s, client, match));
|
TRYST(bus_client_match_add(s, i, match));
|
||||||
|
|
||||||
_reply_begin("") {} _reply_end()
|
_reply_begin("") {} _reply_end()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_remove_match(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_remove_match(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
char *match = TRYPTR(wire_get_string_check(ctx, 1, MATCH_RULE_MAX));
|
char *match = TRYPTR(wire_get_string_check(ctx, 1, MATCH_RULE_MAX));
|
||||||
|
|
||||||
|
bus_client_t *client = &s->clients[i];
|
||||||
int left = client->match_count;
|
int left = client->match_count;
|
||||||
for (int j = 0; j < BUS_MAX_MATCH && left > 0; j++) {
|
for (int j = 0; j < BUS_MAX_MATCH && left > 0; j++) {
|
||||||
left--;
|
left--;
|
||||||
|
@ -594,7 +598,7 @@ int handle_remove_match(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, W
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_get_connection_stats(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_get_connection_stats(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
|
|
||||||
TRYPTR(wire_get_name_string(ctx));
|
TRYPTR(wire_get_name_string(ctx));
|
||||||
|
@ -609,13 +613,13 @@ int handle_get_connection_stats(Bus *s, BusClient *client, WireMsg *msg, WireCtx
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_get_connection_unix_process_id(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_get_connection_unix_process_id(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
|
|
||||||
char *name = TRYPTR(wire_get_name_string(ctx));
|
char *name = TRYPTR(wire_get_name_string(ctx));
|
||||||
|
|
||||||
BusClient *target = bus_name_find_client(s, name);
|
bus_client_t *target = bus_name_find_client(s, name);
|
||||||
if (!target || !target->unique_name || target->fd < 0) {
|
if (!target || target->unique_name_index < 0 || target->fd < 0) {
|
||||||
_reply_error("org.freedesktop.DBus.Error.NameHasNoOwner");
|
_reply_error("org.freedesktop.DBus.Error.NameHasNoOwner");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -634,7 +638,7 @@ int handle_get_connection_unix_process_id(Bus *s, BusClient *client, WireMsg *ms
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_get_all_match_rules(Bus *s, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx) {
|
int handle_get_all_match_rules(bus_t *s, int i, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx) {
|
||||||
(void)ctx;
|
(void)ctx;
|
||||||
_reply_begin("a{sas}") {
|
_reply_begin("a{sas}") {
|
||||||
uint32_t *outer_array_len = TRYPTR(wire_set_u32(reply_ctx, 0));
|
uint32_t *outer_array_len = TRYPTR(wire_set_u32(reply_ctx, 0));
|
||||||
|
@ -643,15 +647,15 @@ int handle_get_all_match_rules(Bus *s, BusClient *client, WireMsg *msg, WireCtx
|
||||||
|
|
||||||
int left = s->names_count;
|
int left = s->names_count;
|
||||||
for (int j = 0; j < BUS_MAX_NAMES && left > 0; j++) {
|
for (int j = 0; j < BUS_MAX_NAMES && left > 0; j++) {
|
||||||
BusName *n = &s->names[j];
|
bus_name_t *n = &s->names[j];
|
||||||
if (!n->name || !n->client || *n->name != ':') {
|
if (!n->name || n->client_index < 0 || *n->name != ':') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
left--;
|
left--;
|
||||||
|
|
||||||
TRYPTR(wire_write_align(reply_ctx, 8)); /* structs always aligned to 8 */
|
TRYPTR(wire_write_align(reply_ctx, 8)); /* structs always aligned to 8 */
|
||||||
|
|
||||||
BusClient *c = s->names[j].client;
|
bus_client_t *c = &s->clients[s->names[j].client_index];
|
||||||
|
|
||||||
TRYPTR(wire_set_string(reply_ctx, s->names[j].name)); /* unique name */
|
TRYPTR(wire_set_string(reply_ctx, s->names[j].name)); /* unique name */
|
||||||
|
|
||||||
|
@ -677,7 +681,7 @@ int handle_get_all_match_rules(Bus *s, BusClient *client, WireMsg *msg, WireCtx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const BusMethodHandler bus_method_handlers[] = {
|
static const bus_method_handler_t bus_method_handlers[] = {
|
||||||
{ "Hello", handle_hello },
|
{ "Hello", handle_hello },
|
||||||
{ "RequestName", handle_request_name },
|
{ "RequestName", handle_request_name },
|
||||||
{ "GetNameOwner", handle_get_name_owner },
|
{ "GetNameOwner", handle_get_name_owner },
|
||||||
|
@ -698,15 +702,17 @@ static const int bus_method_handlers_count = sizeof(bus_method_handlers) / sizeo
|
||||||
do { \
|
do { \
|
||||||
if (!(msg.flags & DBUS_FLAG_NO_REPLY_EXPECTED)) { \
|
if (!(msg.flags & DBUS_FLAG_NO_REPLY_EXPECTED)) { \
|
||||||
TRYST(wire_compose_error(&reply_ctx, &msg, (message))); \
|
TRYST(wire_compose_error(&reply_ctx, &msg, (message))); \
|
||||||
if (send(client->fd, reply_ctx.data, reply_ctx.byte_cursor, 0) != reply_ctx.byte_cursor) { \
|
if (send(s->fds[i].fd, reply_ctx.data, reply_ctx.byte_cursor, 0) != reply_ctx.byte_cursor) { \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
} while(0) \
|
} while(0) \
|
||||||
|
|
||||||
int bus_client_process_message(Bus *s, BusClient *client, WireCtx *ctx)
|
int bus_client_process_message(bus_t *s, int i, wire_context_t *ctx)
|
||||||
{
|
{
|
||||||
WireMsg msg = {0};
|
bus_client_t *client = &s->clients[i];
|
||||||
|
|
||||||
|
wire_message_t msg = {0};
|
||||||
|
|
||||||
TRYST(wire_parse_message(ctx, &msg));
|
TRYST(wire_parse_message(ctx, &msg));
|
||||||
|
|
||||||
|
@ -715,11 +721,11 @@ int bus_client_process_message(Bus *s, BusClient *client, WireCtx *ctx)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
WireMsgField *destination_field = &msg.fields[DBUS_HEADER_FIELD_DESTINATION];
|
wire_message_field_t *destination_field = &msg.fields[DBUS_HEADER_FIELD_DESTINATION];
|
||||||
WireMsgField *member_field = &msg.fields[DBUS_HEADER_FIELD_MEMBER];
|
wire_message_field_t *member_field = &msg.fields[DBUS_HEADER_FIELD_MEMBER];
|
||||||
|
|
||||||
uint8_t reply_data[8192];
|
uint8_t reply_data[8192];
|
||||||
WireCtx reply_ctx = {
|
wire_context_t reply_ctx = {
|
||||||
.byte_cursor = 0,
|
.byte_cursor = 0,
|
||||||
.data = reply_data,
|
.data = reply_data,
|
||||||
.data_len = 8192,
|
.data_len = 8192,
|
||||||
|
@ -728,9 +734,9 @@ int bus_client_process_message(Bus *s, BusClient *client, WireCtx *ctx)
|
||||||
if (msg.type == DBUS_MESSAGE_METHOD_CALL && destination_field->present && member_field->present && strcmp(destination_field->t.str, "org.freedesktop.DBus") == 0) {
|
if (msg.type == DBUS_MESSAGE_METHOD_CALL && destination_field->present && member_field->present && strcmp(destination_field->t.str, "org.freedesktop.DBus") == 0) {
|
||||||
// method call to the bus
|
// method call to the bus
|
||||||
for (int j = 0; j < bus_method_handlers_count; j++) {
|
for (int j = 0; j < bus_method_handlers_count; j++) {
|
||||||
const BusMethodHandler *handler = &bus_method_handlers[j];
|
const bus_method_handler_t *handler = &bus_method_handlers[j];
|
||||||
if (strcmp(handler->name, member_field->t.str) == 0) {
|
if (strcmp(handler->name, member_field->t.str) == 0) {
|
||||||
TRYST(handler->handler(s, client, &msg, ctx, &reply_ctx));
|
TRYST(handler->handler(s, i, &msg, ctx, &reply_ctx));
|
||||||
goto end_nonfatal;
|
goto end_nonfatal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -742,17 +748,17 @@ int bus_client_process_message(Bus *s, BusClient *client, WireCtx *ctx)
|
||||||
// message needs to be routed
|
// message needs to be routed
|
||||||
// TODO: perform checks here like making sure all method calls have the 'member' field, etc.
|
// TODO: perform checks here like making sure all method calls have the 'member' field, etc.
|
||||||
|
|
||||||
if (!client->unique_name) {
|
if (client->unique_name_index < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (destination_field->present) {
|
if (destination_field->present) {
|
||||||
if (bus_unicast_message(s, &msg, ctx, destination_field->t.str, client->unique_name->name, &reply_ctx) < 0) {
|
if (bus_unicast_message(s, &msg, ctx, destination_field->t.str, s->names[client->unique_name_index].name, &reply_ctx) < 0) {
|
||||||
_process_message_reply_error("xyz.hippoz.jitterbug.UnicastFailed");
|
_process_message_reply_error("xyz.hippoz.jitterbug.UnicastFailed");
|
||||||
goto end_nonfatal;
|
goto end_nonfatal;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (bus_broadcast_message(s, client, &msg, ctx, &reply_ctx) < 0) {
|
if (bus_broadcast_message(s, i, &msg, ctx, &reply_ctx) < 0) {
|
||||||
_process_message_reply_error("xyz.hippoz.jitterbug.BroadcastFailed");
|
_process_message_reply_error("xyz.hippoz.jitterbug.BroadcastFailed");
|
||||||
goto end_nonfatal;
|
goto end_nonfatal;
|
||||||
}
|
}
|
||||||
|
@ -778,15 +784,15 @@ end_nonfatal:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bus_client_drain_messages(Bus *s, BusClient *client, uint8_t *data, uint32_t data_len)
|
int bus_client_drain_messages(bus_t *s, int ci, uint8_t *data, uint32_t data_len)
|
||||||
{
|
{
|
||||||
WireCtx ctx = {
|
wire_context_t ctx = {
|
||||||
.byte_cursor = 0,
|
.byte_cursor = 0,
|
||||||
.data = data,
|
.data = data,
|
||||||
.data_len = data_len
|
.data_len = data_len
|
||||||
};
|
};
|
||||||
|
|
||||||
TRYST(bus_client_process_message(s, client, &ctx));
|
TRYST(bus_client_process_message(s, ci, &ctx));
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; i < 10; i++) {
|
for (; i < 10; i++) {
|
||||||
|
@ -797,7 +803,7 @@ int bus_client_drain_messages(Bus *s, BusClient *client, uint8_t *data, uint32_t
|
||||||
ctx.data = ctx.data + ctx.byte_cursor;
|
ctx.data = ctx.data + ctx.byte_cursor;
|
||||||
ctx.data_len = ctx.data_len - ctx.byte_cursor;
|
ctx.data_len = ctx.data_len - ctx.byte_cursor;
|
||||||
ctx.byte_cursor = 0;
|
ctx.byte_cursor = 0;
|
||||||
TRYST(bus_client_process_message(s, client, &ctx));
|
TRYST(bus_client_process_message(s, ci, &ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
VERBOSE("processed %d messages - cursor:%d; data_len:%ld\n", i + 1, ctx.byte_cursor, ctx.data_len);
|
VERBOSE("processed %d messages - cursor:%d; data_len:%ld\n", i + 1, ctx.byte_cursor, ctx.data_len);
|
||||||
|
@ -805,8 +811,8 @@ int bus_client_drain_messages(Bus *s, BusClient *client, uint8_t *data, uint32_t
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _client_die(m) do { bus_client_error(s, &s->clients[i], m); goto done; } while(0)
|
#define _client_die(m) do { bus_client_error(s,i,m); goto done; } while(0)
|
||||||
int bus_turn(Bus *s)
|
int bus_turn(bus_t *s)
|
||||||
{
|
{
|
||||||
static const char agree_unix_fd[] = "ERROR\r\n";
|
static const char agree_unix_fd[] = "ERROR\r\n";
|
||||||
static const char auth_ok[] = "OK aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n";
|
static const char auth_ok[] = "OK aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n";
|
||||||
|
@ -837,7 +843,7 @@ int bus_turn(Bus *s)
|
||||||
ERROR("bus_turn: error: got POLLERR for sock_fd\n");
|
ERROR("bus_turn: error: got POLLERR for sock_fd\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bus_client_remove(s, &s->clients[i]);
|
bus_client_remove(s, i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (s->fds[i].revents & POLLHUP) {
|
if (s->fds[i].revents & POLLHUP) {
|
||||||
|
@ -845,7 +851,7 @@ int bus_turn(Bus *s)
|
||||||
ERROR("bus_turn: error: got POLLHUP for sock_fd\n");
|
ERROR("bus_turn: error: got POLLHUP for sock_fd\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bus_client_remove(s, &s->clients[i]);
|
bus_client_remove(s, i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (s->fds[i].revents & POLLIN) {
|
if (s->fds[i].revents & POLLIN) {
|
||||||
|
@ -869,13 +875,13 @@ int bus_turn(Bus *s)
|
||||||
if (bytes <= 0) {
|
if (bytes <= 0) {
|
||||||
// error during recv() OR client disconnected, disconnect the client
|
// error during recv() OR client disconnected, disconnect the client
|
||||||
// TODO: should we actually do this?
|
// TODO: should we actually do this?
|
||||||
bus_client_remove(s, &s->clients[i]);
|
bus_client_remove(s, i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
VERBOSE("\nrecv: got %zd bytes\n", bytes);
|
VERBOSE("\nrecv: got %zd bytes\n", bytes);
|
||||||
|
|
||||||
BusClient *c = &s->clients[i];
|
bus_client_t *c = &s->clients[i];
|
||||||
switch (c->state) {
|
switch (c->state) {
|
||||||
case BUS_CLIENT_STATE_WAIT_AUTH: {
|
case BUS_CLIENT_STATE_WAIT_AUTH: {
|
||||||
// The D-Bus authentication protocol is a simple plain text protocol.
|
// The D-Bus authentication protocol is a simple plain text protocol.
|
||||||
|
@ -910,7 +916,7 @@ int bus_turn(Bus *s)
|
||||||
char *first_message_begin = data + 7; /* 7 = length of "BEGIN\r\n" */
|
char *first_message_begin = data + 7; /* 7 = length of "BEGIN\r\n" */
|
||||||
if (*first_message_begin == 'l' || *first_message_begin == 'B') {
|
if (*first_message_begin == 'l' || *first_message_begin == 'B') {
|
||||||
// This looks like a D-Bus message. Let's process it!
|
// This looks like a D-Bus message. Let's process it!
|
||||||
if (bus_client_drain_messages(s, &s->clients[i], (uint8_t *)first_message_begin, data_buffer_len - 7) < 0) {
|
if (bus_client_drain_messages(s, i, (uint8_t *)first_message_begin, data_buffer_len - 7) < 0) {
|
||||||
_client_die("failed to process message");
|
_client_die("failed to process message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -923,7 +929,7 @@ int bus_turn(Bus *s)
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BUS_CLIENT_STATE_READY: {
|
case BUS_CLIENT_STATE_READY: {
|
||||||
if (bus_client_drain_messages(s, &s->clients[i], (uint8_t*)data, data_buffer_len) < 0) {
|
if (bus_client_drain_messages(s, i, (uint8_t*)data, data_buffer_len) < 0) {
|
||||||
_client_die("failed to process message");
|
_client_die("failed to process message");
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
47
server.h
47
server.h
|
@ -8,13 +8,13 @@
|
||||||
#define MATCH_RULE_MAX 1024
|
#define MATCH_RULE_MAX 1024
|
||||||
#define MATCH_RULE_MAX_ARG 12
|
#define MATCH_RULE_MAX_ARG 12
|
||||||
|
|
||||||
typedef struct {
|
typedef struct match_rule {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
bool eavesdrop;
|
bool eavesdrop;
|
||||||
char *sender, *interface, *member, *path, *path_namespace, *destination, *arg0namespace, *rule_string;
|
char *sender, *interface, *member, *path, *path_namespace, *destination, *arg0namespace, *rule_string;
|
||||||
char *arg[MATCH_RULE_MAX_ARG]; /* TODO: spec states that indexes 0 to 63 should be supported */
|
char *arg[MATCH_RULE_MAX_ARG]; /* TODO: spec states that indexes 0 to 63 should be supported */
|
||||||
char *arg_path[MATCH_RULE_MAX_ARG]; /* TODO: spec states that indexes 0 to 63 should be supported */
|
char *arg_path[MATCH_RULE_MAX_ARG]; /* TODO: spec states that indexes 0 to 63 should be supported */
|
||||||
} MatchRule;
|
} match_rule_t;
|
||||||
|
|
||||||
// TODO: dynamically size the arrays
|
// TODO: dynamically size the arrays
|
||||||
#define BUS_MAX_CLIENTS 256
|
#define BUS_MAX_CLIENTS 256
|
||||||
|
@ -30,43 +30,42 @@ enum {
|
||||||
BUS_CLIENT_STATE_READY
|
BUS_CLIENT_STATE_READY
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct bus_name {
|
|
||||||
char *name;
|
|
||||||
struct bus_client *client;
|
|
||||||
} BusName;
|
|
||||||
|
|
||||||
typedef struct bus_client {
|
typedef struct bus_client {
|
||||||
int fd;
|
int fd;
|
||||||
BusName *unique_name;
|
int16_t unique_name_index;
|
||||||
int16_t fd_index;
|
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
int8_t match_count;
|
int8_t match_count;
|
||||||
MatchRule *matches[BUS_MAX_MATCH];
|
match_rule_t *matches[BUS_MAX_MATCH];
|
||||||
BusName *owned_names[BUS_NAMES_PER_CLIENT];
|
int16_t owned_names[BUS_NAMES_PER_CLIENT];
|
||||||
} BusClient;
|
} bus_client_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct bus_name {
|
||||||
|
char *name;
|
||||||
|
int32_t client_index;
|
||||||
|
} bus_name_t;
|
||||||
|
|
||||||
|
typedef struct bus {
|
||||||
int sock_fd;
|
int sock_fd;
|
||||||
int fd_num;
|
int fd_num;
|
||||||
int names_count;
|
int names_count;
|
||||||
int clients_count;
|
int clients_count;
|
||||||
int urandom_fd;
|
int urandom_fd;
|
||||||
BusClient clients[BUS_MAX_CLIENTS];
|
bus_client_t clients[BUS_MAX_CLIENTS];
|
||||||
BusName names[BUS_MAX_NAMES];
|
bus_name_t names[BUS_MAX_NAMES];
|
||||||
struct pollfd fds[BUS_MAX_CLIENTS + 1];
|
struct pollfd fds[BUS_MAX_CLIENTS + 1];
|
||||||
} Bus;
|
} bus_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct bus_method_handler {
|
||||||
const char *name;
|
const char *name;
|
||||||
int (*handler)(Bus *bus, BusClient *client, WireMsg *msg, WireCtx *ctx, WireCtx *reply_ctx);
|
int (*handler)(bus_t *bus, int client_index, wire_message_t *msg, wire_context_t *ctx, wire_context_t *reply_ctx);
|
||||||
} BusMethodHandler;
|
} bus_method_handler_t;
|
||||||
|
|
||||||
|
|
||||||
int bus_client_add(Bus *s, int fd);
|
int bus_client_add(bus_t *s, int fd);
|
||||||
void bus_client_remove(Bus *s, BusClient *client);
|
void bus_client_remove(bus_t *s, int i);
|
||||||
void bus_free(Bus *s);
|
void bus_free(bus_t *s);
|
||||||
Bus *bus_create(const char *socket_path);
|
bus_t *bus_create(const char *socket_path);
|
||||||
int bus_turn(Bus *s);
|
int bus_turn(bus_t *s);
|
||||||
|
|
||||||
|
|
||||||
#endif // _JITTERBUG__SERVER_H
|
#endif // _JITTERBUG__SERVER_H
|
10
try.h
10
try.h
|
@ -7,7 +7,7 @@
|
||||||
#ifdef JB_ENABLE_TRY_TRACE
|
#ifdef JB_ENABLE_TRY_TRACE
|
||||||
#define __TRY_TRACE() do { \
|
#define __TRY_TRACE() do { \
|
||||||
printf("trace: %s:%d\n", __FILE__, __LINE__); \
|
printf("trace: %s:%d\n", __FILE__, __LINE__); \
|
||||||
} while(0);
|
} while(0)
|
||||||
#else
|
#else
|
||||||
#define __TRY_TRACE()
|
#define __TRY_TRACE()
|
||||||
#endif // JB_ENABLE_TRY_TRACE
|
#endif // JB_ENABLE_TRY_TRACE
|
||||||
|
@ -16,10 +16,10 @@
|
||||||
// NOTE: The macro(s) below make use of a GCC extension called "Statement Exprs", which is nonstandard.
|
// NOTE: The macro(s) below make use of a GCC extension called "Statement Exprs", which is nonstandard.
|
||||||
// More info: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
|
// More info: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
|
||||||
|
|
||||||
#define TRYPTR_NIL(M_expr) __extension__({ void* _result = (void*)(M_expr); if (unlikely(!_result)) { __TRY_TRACE() return (NULL); } _result; })
|
#define TRYPTR_NIL(M_expr) __extension__({ void* _result = (void*)(M_expr); if (unlikely(!_result)) { __TRY_TRACE(); return (NULL); } _result; })
|
||||||
#define TRYPTR(M_expr) __extension__({ void* _result = (void*)(M_expr); if (unlikely(!_result)) { __TRY_TRACE() return (-1); } _result; })
|
#define TRYPTR(M_expr) __extension__({ void* _result = (void*)(M_expr); if (unlikely(!_result)) { __TRY_TRACE(); return (-1); } _result; })
|
||||||
|
|
||||||
#define TRYST_NIL(M_expr) __extension__({ int _result = (int)(M_expr); if (unlikely(_result < 0)) { __TRY_TRACE() return (NULL); } _result; })
|
#define TRYST_NIL(M_expr) __extension__({ int _result = (int)(M_expr); if (unlikely(_result < 0)) { __TRY_TRACE(); return (NULL); } _result; })
|
||||||
#define TRYST(M_expr) __extension__({ int _result = (int)(M_expr); if (unlikely(_result < 0)) { __TRY_TRACE() return (-1); } _result; })
|
#define TRYST(M_expr) __extension__({ int _result = (int)(M_expr); if (unlikely(_result < 0)) { __TRY_TRACE(); return (-1); } _result; })
|
||||||
|
|
||||||
#endif // __JITTERBUG_TRY_H
|
#endif // __JITTERBUG_TRY_H
|
||||||
|
|
40
wire.c
40
wire.c
|
@ -4,7 +4,7 @@
|
||||||
#include "wire.h"
|
#include "wire.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
bool wire_align(WireCtx *c, uint32_t alignment)
|
bool wire_align(wire_context_t *c, uint32_t alignment)
|
||||||
{
|
{
|
||||||
if ((c->byte_cursor % alignment) == 0) {
|
if ((c->byte_cursor % alignment) == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -17,7 +17,7 @@ bool wire_align(WireCtx *c, uint32_t alignment)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wire_write_align(WireCtx *c, uint32_t alignment)
|
bool wire_write_align(wire_context_t *c, uint32_t alignment)
|
||||||
{
|
{
|
||||||
if ((c->byte_cursor % alignment) == 0) {
|
if ((c->byte_cursor % alignment) == 0) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -41,7 +41,7 @@ _WIRE_DEF_TYPE(i32, int32_t, 4)
|
||||||
_WIRE_DEF_TYPE(u32, uint32_t, 4)
|
_WIRE_DEF_TYPE(u32, uint32_t, 4)
|
||||||
_WIRE_DEF_TYPE(boolean, uint32_t, 4)
|
_WIRE_DEF_TYPE(boolean, uint32_t, 4)
|
||||||
|
|
||||||
char *wire_get_string_impl(WireCtx *c, bool as_signature)
|
char *wire_get_string_impl(wire_context_t *c, bool as_signature)
|
||||||
{
|
{
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
if (as_signature) {
|
if (as_signature) {
|
||||||
|
@ -67,7 +67,7 @@ char *wire_get_string_impl(WireCtx *c, bool as_signature)
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *wire_set_string_impl(WireCtx *c, const char *str, bool as_signature)
|
char *wire_set_string_impl(wire_context_t *c, const char *str, bool as_signature)
|
||||||
{
|
{
|
||||||
uint32_t len = strlen(str);
|
uint32_t len = strlen(str);
|
||||||
if (as_signature) {
|
if (as_signature) {
|
||||||
|
@ -90,14 +90,14 @@ char *wire_set_string_impl(WireCtx *c, const char *str, bool as_signature)
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *wire_get_string_check(WireCtx *c, int min_length, int max_length) {
|
char *wire_get_string_check(wire_context_t *c, int min_length, int max_length) {
|
||||||
char *str = TRYPTR_NIL(wire_get_string_impl(c, false));
|
char *str = TRYPTR_NIL(wire_get_string_impl(c, false));
|
||||||
int length = strlen(str);
|
int length = strlen(str);
|
||||||
if (unlikely(length < min_length || length > max_length)) return NULL;
|
if (unlikely(length < min_length || length > max_length)) return NULL;
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wire_parse_message(WireCtx *c, WireMsg *msg)
|
int wire_parse_message(wire_context_t *c, wire_message_t *msg)
|
||||||
{
|
{
|
||||||
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
|
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
|
||||||
msg->endianness = *(uint8_t*)TRYPTR(wire_get_u8(c));
|
msg->endianness = *(uint8_t*)TRYPTR(wire_get_u8(c));
|
||||||
|
@ -165,7 +165,7 @@ int wire_parse_message(WireCtx *c, WireMsg *msg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wire_compose_signal(WireCtx *c, WireMsg *out_msg, const char *signature, const char *member, uint32_t **out_body_length)
|
int wire_compose_signal(wire_context_t *c, wire_message_t *out_msg, const char *signature, const char *member, uint32_t **out_body_length)
|
||||||
{
|
{
|
||||||
out_msg->endianness = 'l';
|
out_msg->endianness = 'l';
|
||||||
TRYPTR(wire_set_u8(c, 'l')); /* endianness */
|
TRYPTR(wire_set_u8(c, 'l')); /* endianness */
|
||||||
|
@ -278,7 +278,7 @@ int wire_compose_signal(WireCtx *c, WireMsg *out_msg, const char *signature, con
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wire_compose_reply(WireCtx *c, WireMsg *msg, const char *signature, uint32_t **out_body_length)
|
int wire_compose_reply(wire_context_t *c, wire_message_t *msg, const char *signature, uint32_t **out_body_length)
|
||||||
{
|
{
|
||||||
|
|
||||||
TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */
|
TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */
|
||||||
|
@ -345,7 +345,7 @@ int wire_compose_reply(WireCtx *c, WireMsg *msg, const char *signature, uint32_t
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wire_compose_error(WireCtx *c, WireMsg *msg, const char *error_name)
|
int wire_compose_error(wire_context_t *c, wire_message_t *msg, const char *error_name)
|
||||||
{
|
{
|
||||||
|
|
||||||
TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */
|
TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */
|
||||||
|
@ -394,7 +394,7 @@ int wire_compose_error(WireCtx *c, WireMsg *msg, const char *error_name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *sender_unique_name)
|
int wire_compose_unicast_reply(wire_context_t *c, wire_context_t *msg_c, wire_message_t *msg, char *sender_unique_name)
|
||||||
{
|
{
|
||||||
TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */
|
TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */
|
||||||
TRYPTR(wire_set_u8(c, msg->type)); /* type */
|
TRYPTR(wire_set_u8(c, msg->type)); /* type */
|
||||||
|
@ -411,10 +411,10 @@ int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *s
|
||||||
case DBUS_MESSAGE_METHOD_CALL: {
|
case DBUS_MESSAGE_METHOD_CALL: {
|
||||||
// these fields are required for DBUS_MESSAGE_METHOD_CALL, so we must (hackily) check for their presence
|
// these fields are required for DBUS_MESSAGE_METHOD_CALL, so we must (hackily) check for their presence
|
||||||
// interface is not strictly required by the spec, however we require it here anyways
|
// interface is not strictly required by the spec, however we require it here anyways
|
||||||
WireMsgField *path_field = &msg->fields[DBUS_HEADER_FIELD_PATH];
|
wire_message_field_t *path_field = &msg->fields[DBUS_HEADER_FIELD_PATH];
|
||||||
WireMsgField *interface_field = &msg->fields[DBUS_HEADER_FIELD_INTERFACE];
|
wire_message_field_t *interface_field = &msg->fields[DBUS_HEADER_FIELD_INTERFACE];
|
||||||
WireMsgField *member_field = &msg->fields[DBUS_HEADER_FIELD_MEMBER];
|
wire_message_field_t *member_field = &msg->fields[DBUS_HEADER_FIELD_MEMBER];
|
||||||
WireMsgField *signature_field = &msg->fields[DBUS_HEADER_FIELD_SIGNATURE];
|
wire_message_field_t *signature_field = &msg->fields[DBUS_HEADER_FIELD_SIGNATURE];
|
||||||
if (!path_field->present || !interface_field->present || !interface_field->present) {
|
if (!path_field->present || !interface_field->present || !interface_field->present) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -448,7 +448,7 @@ int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *s
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DBUS_MESSAGE_METHOD_RETURN: {
|
case DBUS_MESSAGE_METHOD_RETURN: {
|
||||||
WireMsgField *reply_serial_field = &msg->fields[DBUS_HEADER_FIELD_REPLY_SERIAL];
|
wire_message_field_t *reply_serial_field = &msg->fields[DBUS_HEADER_FIELD_REPLY_SERIAL];
|
||||||
if (!reply_serial_field->present) {
|
if (!reply_serial_field->present) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -458,7 +458,7 @@ int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *s
|
||||||
TRYPTR(wire_set_u32(c, reply_serial_field->t.u32));
|
TRYPTR(wire_set_u32(c, reply_serial_field->t.u32));
|
||||||
TRYPTR(wire_write_align(c, 8));
|
TRYPTR(wire_write_align(c, 8));
|
||||||
|
|
||||||
WireMsgField *signature_field = &msg->fields[DBUS_HEADER_FIELD_SIGNATURE];
|
wire_message_field_t *signature_field = &msg->fields[DBUS_HEADER_FIELD_SIGNATURE];
|
||||||
if (signature_field->present) {
|
if (signature_field->present) {
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE));
|
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE));
|
||||||
TRYPTR(wire_set_signature(c, "g"));
|
TRYPTR(wire_set_signature(c, "g"));
|
||||||
|
@ -473,8 +473,8 @@ int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *s
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DBUS_MESSAGE_ERROR: {
|
case DBUS_MESSAGE_ERROR: {
|
||||||
WireMsgField *reply_serial_field = &msg->fields[DBUS_HEADER_FIELD_REPLY_SERIAL];
|
wire_message_field_t *reply_serial_field = &msg->fields[DBUS_HEADER_FIELD_REPLY_SERIAL];
|
||||||
WireMsgField *error_name_field = &msg->fields[DBUS_HEADER_FIELD_ERROR_NAME];
|
wire_message_field_t *error_name_field = &msg->fields[DBUS_HEADER_FIELD_ERROR_NAME];
|
||||||
if (!reply_serial_field->present || !error_name_field->present) {
|
if (!reply_serial_field->present || !error_name_field->present) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -484,7 +484,7 @@ int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *s
|
||||||
TRYPTR(wire_set_u32(c, reply_serial_field->t.u32));
|
TRYPTR(wire_set_u32(c, reply_serial_field->t.u32));
|
||||||
TRYPTR(wire_write_align(c, 8));
|
TRYPTR(wire_write_align(c, 8));
|
||||||
|
|
||||||
WireMsgField *signature_field = &msg->fields[DBUS_HEADER_FIELD_SIGNATURE];
|
wire_message_field_t *signature_field = &msg->fields[DBUS_HEADER_FIELD_SIGNATURE];
|
||||||
if (signature_field->present) {
|
if (signature_field->present) {
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE));
|
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE));
|
||||||
TRYPTR(wire_set_signature(c, "g"));
|
TRYPTR(wire_set_signature(c, "g"));
|
||||||
|
@ -524,7 +524,7 @@ int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *s
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wire_collect_strings(WireCtx *c, WireMsg *msg, WireMsgBodyString *strings, int strings_count)
|
int wire_collect_strings(wire_context_t *c, wire_message_t *msg, wire_message_body_string_t *strings, int strings_count)
|
||||||
{
|
{
|
||||||
if (!msg->fields[DBUS_HEADER_FIELD_SIGNATURE].present) {
|
if (!msg->fields[DBUS_HEADER_FIELD_SIGNATURE].present) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
66
wire.h
66
wire.h
|
@ -38,47 +38,47 @@ enum {
|
||||||
DBUS_MESSAGE_SIGNAL,
|
DBUS_MESSAGE_SIGNAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct wire_context {
|
||||||
uint32_t byte_cursor;
|
uint32_t byte_cursor;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
size_t data_len;
|
size_t data_len;
|
||||||
} WireCtx;
|
} wire_context_t;
|
||||||
|
|
||||||
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
|
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
|
||||||
typedef struct {
|
typedef struct wire_message_field {
|
||||||
bool present;
|
bool present;
|
||||||
union {
|
union {
|
||||||
char *str;
|
char *str;
|
||||||
uint32_t u32;
|
uint32_t u32;
|
||||||
} t;
|
} t;
|
||||||
} WireMsgField;
|
} wire_message_field_t;
|
||||||
#define WIRE_MESSAGE_MAX_HEADER_FIELDS 9
|
#define WIRE_MESSAGE_MAX_HEADER_FIELDS 9
|
||||||
typedef struct {
|
typedef struct wire_message {
|
||||||
uint8_t endianness, type, flags, protocol_version;
|
uint8_t endianness, type, flags, protocol_version;
|
||||||
uint32_t body_length, serial, header_fields_length;
|
uint32_t body_length, serial, header_fields_length;
|
||||||
uint8_t header_fields_count;
|
uint8_t header_fields_count;
|
||||||
WireMsgField fields[WIRE_MESSAGE_MAX_HEADER_FIELDS]; /* cannot have more than 9 header fields */
|
wire_message_field_t fields[WIRE_MESSAGE_MAX_HEADER_FIELDS]; /* cannot have more than 9 header fields */
|
||||||
} WireMsg;
|
} wire_message_t;
|
||||||
typedef struct {
|
typedef struct wire_message_body_string {
|
||||||
uint16_t index;
|
uint16_t index;
|
||||||
char *str;
|
char *str;
|
||||||
} WireMsgBodyString;
|
} wire_message_body_string_t;
|
||||||
|
|
||||||
#define _WIRE_DECL_BYTE_TYPE(M_mnemonic, M_type) \
|
#define _WIRE_DECL_BYTE_TYPE(M_mnemonic, M_type) \
|
||||||
M_type *wire_get_##M_mnemonic(WireCtx *c); \
|
M_type *wire_get_##M_mnemonic(wire_context_t *c); \
|
||||||
M_type *wire_set_##M_mnemonic(WireCtx *c, M_type val); \
|
M_type *wire_set_##M_mnemonic(wire_context_t *c, M_type val); \
|
||||||
|
|
||||||
#define _WIRE_DECL_TYPE(M_mnemonic, M_type, M_alignment) \
|
#define _WIRE_DECL_TYPE(M_mnemonic, M_type, M_alignment) \
|
||||||
M_type *wire_get_##M_mnemonic(WireCtx *c); \
|
M_type *wire_get_##M_mnemonic(wire_context_t *c); \
|
||||||
M_type *wire_set_##M_mnemonic(WireCtx *c, M_type val); \
|
M_type *wire_set_##M_mnemonic(wire_context_t *c, M_type val); \
|
||||||
|
|
||||||
#define _WIRE_DEF_BYTE_TYPE(M_mnemonic, M_type) \
|
#define _WIRE_DEF_BYTE_TYPE(M_mnemonic, M_type) \
|
||||||
M_type *wire_get_##M_mnemonic(WireCtx *restrict c) { \
|
M_type *wire_get_##M_mnemonic(wire_context_t *restrict c) { \
|
||||||
if (unlikely(c->byte_cursor + 1 >= c->data_len)) return NULL; \
|
if (unlikely(c->byte_cursor + 1 >= c->data_len)) return NULL; \
|
||||||
M_type *value = (M_type*)&c->data[c->byte_cursor++]; \
|
M_type *value = (M_type*)&c->data[c->byte_cursor++]; \
|
||||||
return value; \
|
return value; \
|
||||||
} \
|
} \
|
||||||
M_type *wire_set_##M_mnemonic(WireCtx *restrict c, M_type val) { \
|
M_type *wire_set_##M_mnemonic(wire_context_t *restrict c, M_type val) { \
|
||||||
if (unlikely(c->byte_cursor + 1 >= c->data_len)) return NULL; \
|
if (unlikely(c->byte_cursor + 1 >= c->data_len)) return NULL; \
|
||||||
M_type *dest = (M_type*)&c->data[c->byte_cursor++]; \
|
M_type *dest = (M_type*)&c->data[c->byte_cursor++]; \
|
||||||
*dest = val; \
|
*dest = val; \
|
||||||
|
@ -86,7 +86,7 @@ typedef struct {
|
||||||
} \
|
} \
|
||||||
|
|
||||||
#define _WIRE_DEF_TYPE(M_mnemonic, M_type, M_alignment) \
|
#define _WIRE_DEF_TYPE(M_mnemonic, M_type, M_alignment) \
|
||||||
M_type *wire_get_##M_mnemonic(WireCtx *restrict c) { \
|
M_type *wire_get_##M_mnemonic(wire_context_t *restrict c) { \
|
||||||
if (unlikely(!wire_align(c, M_alignment))) return NULL; \
|
if (unlikely(!wire_align(c, M_alignment))) return NULL; \
|
||||||
uint32_t new_cursor = c->byte_cursor + sizeof(M_type); \
|
uint32_t new_cursor = c->byte_cursor + sizeof(M_type); \
|
||||||
if (unlikely(new_cursor >= c->data_len)) return NULL; \
|
if (unlikely(new_cursor >= c->data_len)) return NULL; \
|
||||||
|
@ -94,7 +94,7 @@ typedef struct {
|
||||||
c->byte_cursor = new_cursor; \
|
c->byte_cursor = new_cursor; \
|
||||||
return value; \
|
return value; \
|
||||||
} \
|
} \
|
||||||
M_type *wire_set_##M_mnemonic(WireCtx *restrict c, M_type val) { \
|
M_type *wire_set_##M_mnemonic(wire_context_t *restrict c, M_type val) { \
|
||||||
if (unlikely(!wire_write_align(c, M_alignment))) return NULL; \
|
if (unlikely(!wire_write_align(c, M_alignment))) return NULL; \
|
||||||
uint32_t new_cursor = c->byte_cursor + sizeof(M_type); \
|
uint32_t new_cursor = c->byte_cursor + sizeof(M_type); \
|
||||||
if (unlikely(new_cursor >= c->data_len)) return NULL; \
|
if (unlikely(new_cursor >= c->data_len)) return NULL; \
|
||||||
|
@ -104,8 +104,8 @@ typedef struct {
|
||||||
return dest; \
|
return dest; \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
bool wire_align(WireCtx *c, uint32_t alignment);
|
bool wire_align(wire_context_t *c, uint32_t alignment);
|
||||||
bool wire_write_align(WireCtx *c, uint32_t alignment);
|
bool wire_write_align(wire_context_t *c, uint32_t alignment);
|
||||||
|
|
||||||
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#id-1.4.6
|
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#id-1.4.6
|
||||||
_WIRE_DECL_BYTE_TYPE(i8, int8_t)
|
_WIRE_DECL_BYTE_TYPE(i8, int8_t)
|
||||||
|
@ -117,34 +117,34 @@ _WIRE_DECL_TYPE(u32, uint32_t, 4)
|
||||||
_WIRE_DECL_TYPE(boolean, uint32_t, 4)
|
_WIRE_DECL_TYPE(boolean, uint32_t, 4)
|
||||||
|
|
||||||
|
|
||||||
char *wire_get_string_impl(WireCtx *c, bool as_signature);
|
char *wire_get_string_impl(wire_context_t *c, bool as_signature);
|
||||||
char *wire_set_string_impl(WireCtx *c, const char *str, bool as_signature);
|
char *wire_set_string_impl(wire_context_t *c, const char *str, bool as_signature);
|
||||||
char *wire_get_string_check(WireCtx *c, int min_length, int max_length);
|
char *wire_get_string_check(wire_context_t *c, int min_length, int max_length);
|
||||||
int wire_parse_message(WireCtx *c, WireMsg *msg);
|
int wire_parse_message(wire_context_t *c, wire_message_t *msg);
|
||||||
int wire_compose_reply(WireCtx *c, WireMsg *msg, const char *signature, uint32_t **out_body_length);
|
int wire_compose_reply(wire_context_t *c, wire_message_t *msg, const char *signature, uint32_t **out_body_length);
|
||||||
int wire_compose_error(WireCtx *c, WireMsg *msg, const char *error_name);
|
int wire_compose_error(wire_context_t *c, wire_message_t *msg, const char *error_name);
|
||||||
int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *sender_unique_name);
|
int wire_compose_unicast_reply(wire_context_t *c, wire_context_t *msg_c, wire_message_t *msg, char *sender_unique_name);
|
||||||
int wire_compose_signal(WireCtx *c, WireMsg *out_msg, const char *signature, const char *member, uint32_t **out_body_length);
|
int wire_compose_signal(wire_context_t *c, wire_message_t *out_msg, const char *signature, const char *member, uint32_t **out_body_length);
|
||||||
int wire_collect_strings(WireCtx *c, WireMsg *msg, WireMsgBodyString *strings, int strings_count);
|
int wire_collect_strings(wire_context_t *c, wire_message_t *msg, wire_message_body_string_t *strings, int strings_count);
|
||||||
|
|
||||||
static inline char *wire_get_signature(WireCtx *c) {
|
static inline char *wire_get_signature(wire_context_t *c) {
|
||||||
return wire_get_string_impl(c, true);
|
return wire_get_string_impl(c, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *wire_set_signature(WireCtx *c, const char *str) {
|
static inline char *wire_set_signature(wire_context_t *c, const char *str) {
|
||||||
return wire_set_string_impl(c, str, true);
|
return wire_set_string_impl(c, str, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *wire_get_string(WireCtx *c) {
|
static inline char *wire_get_string(wire_context_t *c) {
|
||||||
return wire_get_string_impl(c, false);
|
return wire_get_string_impl(c, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *wire_set_string(WireCtx *c, const char *str) {
|
static inline char *wire_set_string(wire_context_t *c, const char *str) {
|
||||||
return wire_set_string_impl(c, str, false);
|
return wire_set_string_impl(c, str, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// maximum name length is 255
|
// maximum name length is 255
|
||||||
static inline char *wire_get_name_string(WireCtx *c) {
|
static inline char *wire_get_name_string(wire_context_t *c) {
|
||||||
return wire_get_string_check(c, 1, 255);
|
return wire_get_string_check(c, 1, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue