2022-12-21 00:38:10 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
2022-12-21 21:38:48 +02:00
|
|
|
#include <inttypes.h>
|
2022-12-21 00:38:10 +02:00
|
|
|
#include "try.h"
|
|
|
|
#include "server.h"
|
|
|
|
#include "wire.h"
|
|
|
|
|
2022-12-21 21:38:48 +02:00
|
|
|
char *string_dup(const char *s)
|
|
|
|
{
|
|
|
|
size_t len = strlen(s) + 1;
|
|
|
|
char *p = malloc(len);
|
|
|
|
return p ? memcpy(p, s, len) : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function#FNV-1a_hash
|
|
|
|
uint64_t hashmap_hash(const char *bytes, size_t bytes_n, size_t map_len)
|
|
|
|
{
|
|
|
|
uint64_t hash = 0xcbf29ce484222325;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < bytes_n; i++) {
|
|
|
|
hash *= 0x100000001b3;
|
|
|
|
hash ^= bytes[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return (hash % map_len);
|
|
|
|
}
|
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
int jb_server_client_add(struct jb_server *s, int fd)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < JB_MAX_CLIENTS; i++) {
|
|
|
|
if (s->clients[i].fd < 0) {
|
|
|
|
s->clients[i].fd = fd;
|
2022-12-21 21:38:48 +02:00
|
|
|
s->clients[i].owned_name_index = -1;
|
|
|
|
s->clients[i].unique_name_index = -1;
|
2022-12-21 00:38:10 +02:00
|
|
|
s->clients[i].state = JB_CLIENT_STATE_WAIT_AUTH;
|
|
|
|
s->fds[i].fd = fd;
|
|
|
|
s->fds[i].events = POLLIN;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-12-21 21:38:48 +02:00
|
|
|
int jb_server_name_find(struct jb_server *s, char *name)
|
|
|
|
{
|
|
|
|
int bucket = hashmap_hash(name, strlen(name), JB_MAX_NAMES);
|
|
|
|
|
|
|
|
for (int i = bucket; i < bucket + 12 && i < JB_MAX_NAMES; i++) {
|
|
|
|
if (s->names[i].name && strcmp(s->names[i].name, name) == 0) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
struct jb_client *jb_server_name_find_client(struct jb_server *s, char *name)
|
|
|
|
{
|
|
|
|
int name_index = jb_server_name_find(s, name);
|
|
|
|
if (name_index < 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s->names[name_index].client_index < 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (s->clients[s->names[name_index].client_index].state != JB_CLIENT_STATE_READY) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return &s->clients[s->names[name_index].client_index];
|
|
|
|
}
|
|
|
|
|
2022-12-21 21:38:48 +02:00
|
|
|
int jb_server_name_add(struct jb_server *s, char *name, int client_index)
|
|
|
|
{
|
|
|
|
if (jb_server_name_find(s, name) >= 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int bucket = hashmap_hash(name, strlen(name), JB_MAX_NAMES);
|
|
|
|
|
|
|
|
for (int i = bucket; i < bucket + 12 && i < JB_MAX_NAMES; i++) {
|
|
|
|
if (s->names[i].client_index == -1) {
|
|
|
|
s->names[i].client_index = client_index;
|
|
|
|
s->names[i].name = name;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int jb_server_client_assign_unique_name(struct jb_server *s, int i)
|
|
|
|
{
|
|
|
|
struct jb_client *c = &s->clients[i];
|
|
|
|
if (c->unique_name_index != -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
uint32_t id = 0;
|
|
|
|
FILE *urandom_file = fopen("/dev/urandom", "rb");
|
|
|
|
if (!urandom_file) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (fread(&id, 1, sizeof(uint32_t), urandom_file) != sizeof(uint32_t)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
char *name = malloc(sizeof(char) * 16);
|
|
|
|
if (!name) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (snprintf(name, 16, ":%"PRIu32, id) < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int name_index = jb_server_name_add(s, name, i);
|
|
|
|
if (name_index < 0) {
|
|
|
|
free(name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
c->unique_name_index = name_index;
|
|
|
|
|
|
|
|
return name_index;
|
|
|
|
}
|
|
|
|
|
|
|
|
int jb_server_client_assign_own_name(struct jb_server *s, int i, char *name)
|
|
|
|
{
|
|
|
|
struct jb_client *c = &s->clients[i];
|
|
|
|
if (c->owned_name_index != -1) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int name_index = jb_server_name_add(s, name, i);
|
|
|
|
if (name_index < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
c->owned_name_index = name_index;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void jb_server_name_remove(struct jb_server *s, int i)
|
|
|
|
{
|
|
|
|
if (i >= 0) {
|
|
|
|
if (s->names[i].name) {
|
|
|
|
free(s->names[i].name);
|
|
|
|
s->names[i].name = NULL;
|
|
|
|
}
|
|
|
|
s->names[i].client_index = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
void jb_server_client_remove(struct jb_server *s, int i)
|
|
|
|
{
|
|
|
|
if (s->clients[i].fd >= 0) {
|
|
|
|
close(s->clients[i].fd);
|
|
|
|
}
|
2022-12-21 21:38:48 +02:00
|
|
|
jb_server_name_remove(s, s->clients[i].unique_name_index);
|
|
|
|
jb_server_name_remove(s, s->clients[i].owned_name_index);
|
|
|
|
s->clients[i].unique_name_index = -1;
|
|
|
|
s->clients[i].owned_name_index = -1;
|
2022-12-21 00:38:10 +02:00
|
|
|
s->clients[i].fd = -1;
|
|
|
|
s->clients[i].state = JB_CLIENT_STATE_NONE;
|
|
|
|
s->fds[i].fd = -1;
|
|
|
|
s->fds[i].events = 0;
|
|
|
|
s->fds[i].revents = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void jb_server_client_error(struct jb_server *s, int i, const char *msg)
|
|
|
|
{
|
|
|
|
printf("jb_server_client_error: %s\n", msg);
|
|
|
|
send(s->clients[i].fd, msg, strlen(msg), 0);
|
|
|
|
jb_server_client_remove(s, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t jb_server_client_recv(struct jb_server *s, int i, void *buf, size_t n)
|
|
|
|
{
|
|
|
|
ssize_t status = recv(s->fds[i].fd, buf, n, 0);
|
|
|
|
if (status <= 0) {
|
|
|
|
jb_server_client_remove(s, i);
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, size_t data_len)
|
|
|
|
{
|
2022-12-21 21:38:48 +02:00
|
|
|
struct jb_client *client = &s->clients[i];
|
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
wire_context_t ctx = {
|
|
|
|
.byte_cursor = 0,
|
|
|
|
.data = data,
|
|
|
|
.data_len = data_len,
|
|
|
|
};
|
|
|
|
|
|
|
|
wire_message_t msg = {0};
|
|
|
|
|
|
|
|
TRY_NONNEGATIVE(int, wire_parse_message(&ctx, &msg), -1);
|
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
uint8_t reply_data[4096];
|
|
|
|
memset(reply_data, 0, 4096);
|
2022-12-21 21:38:48 +02:00
|
|
|
wire_context_t reply_ctx = {
|
|
|
|
.byte_cursor = 0,
|
|
|
|
.data = reply_data,
|
2022-12-23 23:58:18 +02:00
|
|
|
.data_len = 4096,
|
2022-12-21 21:38:48 +02:00
|
|
|
};
|
2022-12-21 00:38:10 +02:00
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
wire_message_field_t *destination_field = &msg.fields[DBUS_HEADER_FIELD_DESTINATION];
|
|
|
|
wire_message_field_t *member_field = &msg.fields[DBUS_HEADER_FIELD_MEMBER];
|
|
|
|
|
|
|
|
bool should_unicast = false;
|
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
switch (msg.type) {
|
|
|
|
case DBUS_MESSAGE_METHOD_CALL: {
|
2022-12-23 23:58:18 +02:00
|
|
|
if (!destination_field->present || !member_field->present) {
|
|
|
|
return -1;
|
2022-12-21 00:38:10 +02:00
|
|
|
}
|
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
char *member = member_field->t.str;
|
2022-12-21 00:38:10 +02:00
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
if (strcmp(destination_field->t.str, "org.freedesktop.DBus") != 0) {
|
|
|
|
// not for dbus.
|
|
|
|
should_unicast = true;
|
|
|
|
break;
|
|
|
|
}
|
2022-12-21 21:38:48 +02:00
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
if (strcmp(member, "Hello") == 0) {
|
|
|
|
int unique_name_index = jb_server_client_assign_unique_name(s, i);
|
|
|
|
if (unique_name_index < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
2022-12-21 21:38:48 +02:00
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
uint32_t *body_length;
|
|
|
|
TRY_NONNEGATIVE(int, wire_compose_reply(&reply_ctx, &msg, "s", &body_length), -1);
|
|
|
|
uint32_t body_start = reply_ctx.byte_cursor;
|
|
|
|
TRY_NONNULL(char*, wire_set_string(&reply_ctx, s->names[unique_name_index].name), -1);
|
|
|
|
*body_length = reply_ctx.byte_cursor - body_start;
|
|
|
|
if (send(s->fds[i].fd, reply_data, reply_ctx.byte_cursor, 0) != reply_ctx.byte_cursor) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
printf("assigned unique name '%s' to connection %d\n", s->names[unique_name_index].name, i);
|
|
|
|
} else if (strcmp(member, "RequestName") == 0) {
|
|
|
|
char *name = TRY_NONNULL(char*, wire_get_string(&ctx, NULL), -1);
|
|
|
|
int name_len = strlen(name);
|
|
|
|
if (name_len < 1 || name_len > 256) {
|
|
|
|
return -1;
|
|
|
|
}
|
2022-12-21 21:38:48 +02:00
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
char *name_str = string_dup(name);
|
|
|
|
if (!name_str) {
|
|
|
|
return -1;
|
|
|
|
}
|
2022-12-21 21:38:48 +02:00
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
int status_code = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
|
2022-12-21 21:38:48 +02:00
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
if (jb_server_client_assign_own_name(s, i, name_str) < 0) {
|
|
|
|
free(name_str);
|
|
|
|
// TODO: report the actual error
|
|
|
|
status_code = DBUS_REQUEST_NAME_REPLY_EXISTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t *body_length;
|
|
|
|
TRY_NONNEGATIVE(int, wire_compose_reply(&reply_ctx, &msg, "u", &body_length), -1);
|
|
|
|
uint32_t body_start = reply_ctx.byte_cursor;
|
|
|
|
TRY_NONNULL(uint32_t*, wire_set_u32(&reply_ctx, status_code), -1);
|
|
|
|
*body_length = reply_ctx.byte_cursor - body_start;
|
|
|
|
if (send(s->fds[i].fd, reply_data, reply_ctx.byte_cursor, 0) != reply_ctx.byte_cursor) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status_code == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
|
|
|
|
printf("client '%s' (index=%d) now owns name '%s'\n", s->names[client->unique_name_index].name, i, name_str);
|
2022-12-21 00:38:10 +02:00
|
|
|
}
|
|
|
|
} else {
|
2022-12-23 23:58:18 +02:00
|
|
|
TRY_NONNEGATIVE(int, wire_compose_error(&reply_ctx, &msg, "org.freedesktop.DBus.Error.UnknownMethod"), -1);
|
|
|
|
if (send(s->fds[i].fd, reply_data, reply_ctx.byte_cursor, 0) != reply_ctx.byte_cursor) {
|
|
|
|
return -1;
|
|
|
|
}
|
2022-12-21 00:38:10 +02:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
case DBUS_MESSAGE_METHOD_RETURN: {
|
|
|
|
if (!destination_field->present) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
should_unicast = true;
|
|
|
|
} break;
|
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
default: {
|
2022-12-23 23:58:18 +02:00
|
|
|
printf("xyz.hippoz.jitterbug.NotImplemented\n");
|
2022-12-21 21:38:48 +02:00
|
|
|
TRY_NONNEGATIVE(int, wire_compose_error(&reply_ctx, &msg, "xyz.hippoz.jitterbug.NotImplemented"), -1);
|
|
|
|
if (send(s->fds[i].fd, reply_data, reply_ctx.byte_cursor, 0) != reply_ctx.byte_cursor) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return -1;
|
2022-12-21 00:38:10 +02:00
|
|
|
} break;
|
|
|
|
}
|
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
if (should_unicast) {
|
|
|
|
if (client->unique_name_index < 0 || !destination_field->present) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
printf("sending unicast message from %s\n", s->names[client->unique_name_index].name);
|
|
|
|
struct jb_client *target = jb_server_name_find_client(s, destination_field->t.str);
|
|
|
|
if (!target) {
|
|
|
|
uint8_t error_reply_data[512];
|
|
|
|
memset(error_reply_data, 0, 512);
|
|
|
|
wire_context_t error_reply_ctx = {
|
|
|
|
.byte_cursor = 0,
|
|
|
|
.data = error_reply_data,
|
|
|
|
.data_len = 511,
|
|
|
|
};
|
|
|
|
TRY_NONNEGATIVE(int, wire_compose_error(&error_reply_ctx, &msg, "xyz.hippoz.jitterbug.NotImplemented"), -1);
|
|
|
|
if (send(s->fds[i].fd, error_reply_data, error_reply_ctx.byte_cursor, 0) != error_reply_ctx.byte_cursor) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
TRY_NONNEGATIVE(int, wire_compose_unicast_reply(&reply_ctx, &ctx, &msg, s->names[client->unique_name_index].name), -1);
|
|
|
|
TRY_NONNEGATIVE(int, send(target->fd, reply_data, reply_ctx.byte_cursor, 0), -1);
|
|
|
|
}
|
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void jb_server_free(struct jb_server *s)
|
|
|
|
{
|
|
|
|
if (!s) return;
|
|
|
|
if (s->sock_fd) close(s->sock_fd);
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct jb_server *jb_server_create(const char *socket_path)
|
|
|
|
{
|
|
|
|
struct jb_server *s = malloc(sizeof(struct jb_server));
|
|
|
|
if (s == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
s->sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
|
|
if (s->sock_fd == -1) {
|
|
|
|
free(s);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sockaddr_un name;
|
|
|
|
memset(&name, 0, sizeof(name));
|
|
|
|
name.sun_family = AF_UNIX;
|
|
|
|
strncpy(name.sun_path, socket_path, sizeof(name.sun_path) - 1);
|
|
|
|
|
|
|
|
unlink(socket_path);
|
|
|
|
|
|
|
|
if (bind(s->sock_fd, (const struct sockaddr *)&name, sizeof(name)) == -1) {
|
|
|
|
close(s->sock_fd);
|
|
|
|
free(s);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (listen(s->sock_fd, JB_BACKLOG) == -1) {
|
|
|
|
close(s->sock_fd);
|
|
|
|
free(s);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < JB_MAX_CLIENTS; i++) {
|
|
|
|
s->clients[i].fd = -1;
|
2022-12-21 21:38:48 +02:00
|
|
|
s->clients[i].owned_name_index = -1;
|
|
|
|
s->clients[i].unique_name_index = -1;
|
2022-12-21 00:38:10 +02:00
|
|
|
s->clients[i].state = JB_CLIENT_STATE_NONE;
|
|
|
|
s->fds[i].fd = -1;
|
|
|
|
s->fds[i].events = 0;
|
|
|
|
s->fds[i].revents = 0;
|
|
|
|
}
|
|
|
|
|
2022-12-21 21:38:48 +02:00
|
|
|
for (int i = 0; i < JB_MAX_NAMES; i++) {
|
|
|
|
s->names[i].client_index = -1;
|
|
|
|
s->names[i].name = NULL;
|
|
|
|
}
|
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
s->fds[JB_MAX_CLIENTS].fd = s->sock_fd;
|
|
|
|
s->fds[JB_MAX_CLIENTS].events = POLLIN;
|
|
|
|
s->fd_num = JB_MAX_CLIENTS + 1;
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define _client_die(m) ({jb_server_client_error(s,i,m);continue;})
|
|
|
|
int jb_server_turn(struct jb_server *s)
|
|
|
|
{
|
|
|
|
static const char agree_unix_fd[] = "AGREE_UNIX_FD\r\n";
|
|
|
|
static const char auth_ok[] = "OK 1234deadbeef\r\n";
|
2022-12-23 23:58:18 +02:00
|
|
|
static const int data_buffer_len = 4096;
|
2022-12-21 00:38:10 +02:00
|
|
|
|
|
|
|
TRY_NONNEGATIVE(int, poll(s->fds, s->fd_num, -1), -1);
|
|
|
|
|
|
|
|
for (int i = 0; i < s->fd_num; i++) {
|
|
|
|
int fd = s->fds[i].fd;
|
|
|
|
if (s->fds[i].revents & POLLIN) {
|
|
|
|
// file descriptor ready for reading
|
|
|
|
|
|
|
|
if (fd == s->sock_fd) {
|
|
|
|
// new connection
|
|
|
|
int fd = TRY_NONNEGATIVE(int, accept(s->sock_fd, NULL, NULL), -1);
|
|
|
|
|
|
|
|
if (jb_server_client_add(s, fd) == -1) {
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
char data[data_buffer_len];
|
|
|
|
memset(data, 0, sizeof(data));
|
|
|
|
ssize_t bytes = recv(fd, data, sizeof(data) - 1, 0);
|
|
|
|
if (bytes < 0) {
|
|
|
|
// error during recv(), disconnect the client
|
|
|
|
// TODO: should we actually do this?
|
|
|
|
close(fd);
|
|
|
|
jb_server_client_remove(s, i);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (bytes == 0) {
|
|
|
|
// client disconnected
|
|
|
|
jb_server_client_remove(s, i);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct jb_client *c = &s->clients[i];
|
|
|
|
switch (c->state) {
|
|
|
|
case JB_CLIENT_STATE_WAIT_AUTH: {
|
|
|
|
// The D-Bus authentication protocol is a simple plain text protocol.
|
|
|
|
// Before the flow of messages can begin, the two applications must authenticate.
|
|
|
|
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
|
|
|
|
|
|
|
|
// Immediately after connecting, clients must send a null byte
|
|
|
|
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#auth-nul-byte
|
|
|
|
if (*data != '\0' || *(data + 1) == '\0') {
|
|
|
|
_client_die("expected initial auth message to begin with a nul byte");
|
|
|
|
}
|
|
|
|
|
|
|
|
char *auth_string = data + 1;
|
|
|
|
|
2022-12-23 23:58:18 +02:00
|
|
|
if (strcmp(auth_string, "AUTH EXTERNAL 31303030\r\n") != 0 && strcmp(auth_string, "AUTH\r\n") != 0)
|
2022-12-21 00:38:10 +02:00
|
|
|
_client_die("bad auth");
|
|
|
|
send(fd, auth_ok, sizeof(auth_ok) - 1, 0);
|
|
|
|
c->state = JB_CLIENT_STATE_WAIT_BEGIN;
|
|
|
|
} break;
|
|
|
|
case JB_CLIENT_STATE_WAIT_BEGIN: {
|
|
|
|
// Right now, we're expecting the client to either immediately begin the connection,
|
|
|
|
// or to negotiate UNIX file descriptor passing.
|
|
|
|
if (strncmp(data, "BEGIN\r\n", 7) == 0) {
|
|
|
|
c->state = JB_CLIENT_STATE_READY;
|
|
|
|
// At this point, a D-Bus connection has been established.
|
|
|
|
// The first octet after the \r\n of the BEGIN command is the first octet of the D-Bus communication.
|
|
|
|
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#auth-command-begin
|
|
|
|
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 (jb_server_client_process_message(s, i, (uint8_t *)first_message_begin, data_buffer_len - 7) < 0) {
|
|
|
|
_client_die("failed to process message");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (strcmp(data, "NEGOTIATE_UNIX_FD\r\n") == 0) {
|
|
|
|
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#auth-command-negotiate-unix-fd
|
|
|
|
send(fd, agree_unix_fd, sizeof(agree_unix_fd) - 1, 0);
|
|
|
|
} else {
|
|
|
|
_client_die("bad auth response (expected BEGIN or NEGOTIATE_UNIX_FD)");
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case JB_CLIENT_STATE_READY: {
|
2022-12-21 21:38:48 +02:00
|
|
|
if (jb_server_client_process_message(s, i, (uint8_t*)data, data_buffer_len) < 0) {
|
|
|
|
_client_die("failed to process message");
|
|
|
|
}
|
2022-12-21 00:38:10 +02:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case JB_CLIENT_STATE_NONE: {} /* through */
|
|
|
|
default: {
|
|
|
|
_client_die("bad state");
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|