fixes
This commit is contained in:
parent
f7da39acea
commit
de00067fd1
2 changed files with 94 additions and 38 deletions
114
server.c
114
server.c
|
@ -1,3 +1,5 @@
|
||||||
|
#define _GNU_SOURCE 1
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -130,7 +132,7 @@ int jb_server_client_assign_unique_name(struct jb_server *s, int i)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snprintf(name, 16, ":%"PRIu32, id) < 0) {
|
if (snprintf(name, 16, ":1.%"PRIu32, id) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,8 +243,10 @@ int jb_server_broadcast_message(struct jb_server *s, wire_message_t *msg, wire_c
|
||||||
.data_len = 4096,
|
.data_len = 4096,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint32_t previous_cursor = ctx->byte_cursor;
|
||||||
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(c->fd, reply_data, reply_ctx.byte_cursor, 0));
|
TRYST(send(c->fd, reply_data, reply_ctx.byte_cursor, 0));
|
||||||
|
ctx->byte_cursor = previous_cursor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,23 +297,18 @@ int jb_server_unicast_message(struct jb_server *s, wire_message_t *msg, wire_con
|
||||||
} \
|
} \
|
||||||
} while(0) \
|
} while(0) \
|
||||||
|
|
||||||
int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, size_t data_len)
|
int jb_server_client_process_message(struct jb_server *s, int i, wire_context_t *ctx)
|
||||||
{
|
{
|
||||||
struct jb_client *client = &s->clients[i];
|
struct jb_client *client = &s->clients[i];
|
||||||
|
|
||||||
wire_message_t msg = {0};
|
wire_message_t msg = {0};
|
||||||
wire_context_t ctx = {
|
|
||||||
.byte_cursor = 0,
|
|
||||||
.data = data,
|
|
||||||
.data_len = data_len,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (wire_parse_message(&ctx, &msg) < 0) {
|
if (wire_parse_message(ctx, &msg) < 0) {
|
||||||
printf("parsing failed\n");
|
printf("parsing failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("process_message: processed %d/%zu bytes\n", ctx.byte_cursor, data_len);
|
printf("process_message: processed %d/%zu bytes\n", ctx->byte_cursor, ctx->data_len);
|
||||||
|
|
||||||
wire_message_field_t *destination_field = &msg.fields[DBUS_HEADER_FIELD_DESTINATION];
|
wire_message_field_t *destination_field = &msg.fields[DBUS_HEADER_FIELD_DESTINATION];
|
||||||
wire_message_field_t *member_field = &msg.fields[DBUS_HEADER_FIELD_MEMBER];
|
wire_message_field_t *member_field = &msg.fields[DBUS_HEADER_FIELD_MEMBER];
|
||||||
|
@ -356,7 +355,7 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data,
|
||||||
|
|
||||||
printf("assigned unique name '%s' to connection %d\n", s->names[unique_name_index].name, i);
|
printf("assigned unique name '%s' to connection %d\n", s->names[unique_name_index].name, i);
|
||||||
} else if (strcmp(member, "RequestName") == 0) {
|
} else if (strcmp(member, "RequestName") == 0) {
|
||||||
char *name = TRYPTR(wire_get_string(&ctx));
|
char *name = TRYPTR(wire_get_string(ctx));
|
||||||
int name_len = strlen(name);
|
int name_len = strlen(name);
|
||||||
if (name_len < 1 || name_len > 256) {
|
if (name_len < 1 || name_len > 256) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -380,7 +379,7 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data,
|
||||||
printf("client '%s' (index=%d) now owns name '%s'\n", s->names[client->unique_name_index].name, i, name_str);
|
printf("client '%s' (index=%d) now owns name '%s'\n", s->names[client->unique_name_index].name, i, name_str);
|
||||||
}
|
}
|
||||||
} else if (strcmp(member, "GetNameOwner") == 0) {
|
} else if (strcmp(member, "GetNameOwner") == 0) {
|
||||||
char *name = TRYPTR(wire_get_string(&ctx));
|
char *name = TRYPTR(wire_get_string(ctx));
|
||||||
int name_len = strlen(name);
|
int name_len = strlen(name);
|
||||||
if (name_len < 1 || name_len > 256) {
|
if (name_len < 1 || name_len > 256) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -396,7 +395,7 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data,
|
||||||
TRYPTR(wire_set_string(&reply_ctx, s->names[target->unique_name_index].name));
|
TRYPTR(wire_set_string(&reply_ctx, s->names[target->unique_name_index].name));
|
||||||
} _reply_end()
|
} _reply_end()
|
||||||
} else if (strcmp(member, "NameHasOwner") == 0) {
|
} else if (strcmp(member, "NameHasOwner") == 0) {
|
||||||
char *name = TRYPTR(wire_get_string(&ctx));
|
char *name = TRYPTR(wire_get_string(ctx));
|
||||||
int name_len = strlen(name);
|
int name_len = strlen(name);
|
||||||
if (name_len < 1 || name_len > 256) {
|
if (name_len < 1 || name_len > 256) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -440,32 +439,21 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data,
|
||||||
} else if (strcmp(member, "StartServiceByName") == 0) {
|
} else if (strcmp(member, "StartServiceByName") == 0) {
|
||||||
// TODO: stub (does nothing and always returns success)
|
// TODO: stub (does nothing and always returns success)
|
||||||
|
|
||||||
char *name = TRYPTR(wire_get_string(&ctx));
|
char *name = TRYPTR(wire_get_string(ctx));
|
||||||
int name_len = strlen(name);
|
int name_len = strlen(name);
|
||||||
if (name_len < 1 || name_len > 256) {
|
if (name_len < 1 || name_len > 256) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* unused flags value */
|
/* unused flags value */
|
||||||
TRYPTR(wire_get_u32(&ctx));
|
TRYPTR(wire_get_u32(ctx));
|
||||||
|
|
||||||
printf("FIXME: STUB: StartServiceByName: %s\n", name);
|
printf("FIXME: STUB: StartServiceByName: %s\n", name);
|
||||||
|
|
||||||
_reply_begin("u") {
|
_reply_begin("u") {
|
||||||
TRYPTR(wire_set_u32(&reply_ctx, 1));
|
TRYPTR(wire_set_u32(&reply_ctx, 1));
|
||||||
} _reply_end()
|
} _reply_end()
|
||||||
} else if (strcmp(member, "GetConnectionUnixProcessID") == 0) {
|
|
||||||
// TODO: stub (returns an error)
|
|
||||||
char *name = TRYPTR(wire_get_string(&ctx));
|
|
||||||
int name_len = strlen(name);
|
|
||||||
if (name_len < 1 || name_len > 256) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("FIXME: STUB: GetConnectionUnixProcessID: %s\n", name);
|
|
||||||
|
|
||||||
_reply_error("xyz.hippoz.jitterbug.NotImplemented");
|
|
||||||
} else if (strcmp(member, "AddMatch") == 0) {
|
} else if (strcmp(member, "AddMatch") == 0) {
|
||||||
char *match = TRYPTR(wire_get_string(&ctx));
|
char *match = TRYPTR(wire_get_string(ctx));
|
||||||
int match_len = strlen(match);
|
int match_len = strlen(match);
|
||||||
if (match_len < 1 || match_len > MATCH_RULE_MAX) {
|
if (match_len < 1 || match_len > MATCH_RULE_MAX) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -479,7 +467,7 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data,
|
||||||
} else if (strcmp(member, "RemoveMatch") == 0) {
|
} else if (strcmp(member, "RemoveMatch") == 0) {
|
||||||
// TODO: stub (does nothing and always returns success)
|
// TODO: stub (does nothing and always returns success)
|
||||||
|
|
||||||
char *match = TRYPTR(wire_get_string(&ctx));
|
char *match = TRYPTR(wire_get_string(ctx));
|
||||||
int match_len = strlen(match);
|
int match_len = strlen(match);
|
||||||
if (match_len < 1 || match_len > MATCH_RULE_MAX) {
|
if (match_len < 1 || match_len > MATCH_RULE_MAX) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -488,6 +476,39 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data,
|
||||||
printf("FIXME: STUB: RemoveMatch: %s\n", match);
|
printf("FIXME: STUB: RemoveMatch: %s\n", match);
|
||||||
|
|
||||||
_reply_begin("") {} _reply_end()
|
_reply_begin("") {} _reply_end()
|
||||||
|
} else if (strcmp(member, "GetConnectionStats") == 0) {
|
||||||
|
// TODO: stub (always returns empty array)
|
||||||
|
printf("FIXME: STUB: GetConnectionStats\n");
|
||||||
|
|
||||||
|
_reply_begin("as") {
|
||||||
|
TRYPTR(wire_set_u32(&reply_ctx, 0));
|
||||||
|
// empty arrays still need to align
|
||||||
|
TRYPTR(wire_write_align(&reply_ctx, 8));
|
||||||
|
} _reply_end()
|
||||||
|
} else if (strcmp(member, "GetConnectionUnixProcessID") == 0) {
|
||||||
|
char *name = TRYPTR(wire_get_string(ctx));
|
||||||
|
int name_len = strlen(name);
|
||||||
|
if (name_len < 1 || name_len > 256) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct jb_client *target = jb_server_name_find_client(s, name);
|
||||||
|
if (!target || target->unique_name_index < 0 || target->fd < 0) {
|
||||||
|
_reply_error("org.freedesktop.DBus.Error.NameHasNoOwner");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ucred cred;
|
||||||
|
socklen_t len = sizeof(struct ucred);
|
||||||
|
|
||||||
|
if (getsockopt(target->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1) {
|
||||||
|
_reply_error("xyz.hippoz.jitterbug.FailedToGetPID");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_reply_begin("u") {
|
||||||
|
TRYPTR(wire_set_u32(&reply_ctx, cred.pid));
|
||||||
|
} _reply_end()
|
||||||
} else if (strcmp(member, "GetAllMatchRules") == 0) {
|
} else if (strcmp(member, "GetAllMatchRules") == 0) {
|
||||||
_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));
|
||||||
|
@ -534,8 +555,10 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data,
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case DBUS_MESSAGE_METHOD_RETURN: {
|
case DBUS_MESSAGE_METHOD_RETURN: {
|
||||||
|
// we assume that method returns without any destination field are directed at their sender
|
||||||
|
// TODO: this is probably not correct
|
||||||
if (!destination_field->present) {
|
if (!destination_field->present) {
|
||||||
return -1;
|
destination_field->t.str = s->names[client->unique_name_index].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
should_forward = true;
|
should_forward = true;
|
||||||
|
@ -557,22 +580,41 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data,
|
||||||
}
|
}
|
||||||
if (destination_field->present) {
|
if (destination_field->present) {
|
||||||
/* unicast */
|
/* unicast */
|
||||||
if (jb_server_unicast_message(s, &msg, &ctx, destination_field->t.str, s->names[client->unique_name_index].name) < 0) {
|
if (jb_server_unicast_message(s, &msg, ctx, destination_field->t.str, s->names[client->unique_name_index].name) < 0) {
|
||||||
_reply_error("xyz.hippoz.jitterbug.UnicastFailed");
|
_reply_error("xyz.hippoz.jitterbug.UnicastFailed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* broadcast */
|
/* broadcast */
|
||||||
if (jb_server_broadcast_message(s, &msg, &ctx, s->names[client->unique_name_index].name) < 0) {
|
if (jb_server_broadcast_message(s, &msg, ctx, s->names[client->unique_name_index].name) < 0) {
|
||||||
_reply_error("xyz.hippoz.jitterbug.BroadcastFailed");
|
_reply_error("xyz.hippoz.jitterbug.BroadcastFailed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.byte_cursor < ctx.data_len && ctx.data[ctx.byte_cursor] == 'l') {
|
return 0;
|
||||||
// another message
|
}
|
||||||
TRYST(jb_server_client_process_message(s, i, ctx.data + ctx.byte_cursor, ctx.data_len - ctx.byte_cursor));
|
|
||||||
|
int jb_server_client_drain_messages(struct jb_server *s, int ci, uint8_t *data, uint32_t data_len)
|
||||||
|
{
|
||||||
|
wire_context_t ctx = {
|
||||||
|
.byte_cursor = 0,
|
||||||
|
.data = data,
|
||||||
|
.data_len = data_len
|
||||||
|
};
|
||||||
|
|
||||||
|
TRYST(jb_server_client_process_message(s, ci, &ctx));
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
if (ctx.byte_cursor >= ctx.data_len || ctx.data[ctx.byte_cursor] != 'l') {
|
||||||
|
// no more messages
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ctx.data = ctx.data + ctx.byte_cursor;
|
||||||
|
ctx.data_len = ctx.data_len - ctx.byte_cursor;
|
||||||
|
ctx.byte_cursor = 0;
|
||||||
|
TRYST(jb_server_client_process_message(s, ci, &ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -655,7 +697,7 @@ int jb_server_turn(struct jb_server *s)
|
||||||
static const char auth_ok[] = "OK aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n";
|
static const char auth_ok[] = "OK aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n";
|
||||||
static const char auth_list[] = "REJECTED EXTERNAL\r\n";
|
static const char auth_list[] = "REJECTED EXTERNAL\r\n";
|
||||||
static const char auth_data[] = "DATA\r\n";
|
static const char auth_data[] = "DATA\r\n";
|
||||||
static const int data_buffer_len = 4096;
|
static const int data_buffer_len = 8192;
|
||||||
|
|
||||||
// We can keep a padding of null bytes for the data buffer. In the event that, for
|
// We can keep a padding of null bytes for the data buffer. In the event that, for
|
||||||
// example, a string function is called on a char array without a proper ending null
|
// example, a string function is called on a char array without a proper ending null
|
||||||
|
@ -752,7 +794,7 @@ int jb_server_turn(struct jb_server *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 (jb_server_client_process_message(s, i, (uint8_t *)first_message_begin, data_buffer_len - 7) < 0) {
|
if (jb_server_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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -765,7 +807,7 @@ int jb_server_turn(struct jb_server *s)
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case JB_CLIENT_STATE_READY: {
|
case JB_CLIENT_STATE_READY: {
|
||||||
if (jb_server_client_process_message(s, i, (uint8_t*)data, data_buffer_len) < 0) {
|
if (jb_server_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;
|
||||||
|
|
18
wire.c
18
wire.c
|
@ -182,6 +182,20 @@ int wire_compose_reply(wire_context_t *c, wire_message_t *msg, const char *signa
|
||||||
|
|
||||||
/* header fields */
|
/* header fields */
|
||||||
{
|
{
|
||||||
|
/* SENDER */
|
||||||
|
{
|
||||||
|
/* byte (field code) */
|
||||||
|
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SENDER));
|
||||||
|
/* variant */
|
||||||
|
/* signature */
|
||||||
|
TRYPTR(wire_set_signature(c, "s"));
|
||||||
|
/* string */
|
||||||
|
TRYPTR(wire_set_string(c, "org.freedesktop.DBus"));
|
||||||
|
|
||||||
|
// need to align to 8 byte boundry after each array element?
|
||||||
|
TRYPTR(wire_write_align(c, 8));
|
||||||
|
}
|
||||||
|
|
||||||
/* SIGNATURE */
|
/* SIGNATURE */
|
||||||
{
|
{
|
||||||
/* byte (field code) */
|
/* byte (field code) */
|
||||||
|
@ -336,7 +350,7 @@ int wire_compose_unicast_reply(wire_context_t *c, wire_context_t *msg_c, wire_me
|
||||||
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"));
|
||||||
TRYPTR(wire_set_string(c, signature_field->t.str));
|
TRYPTR(wire_set_signature(c, signature_field->t.str));
|
||||||
TRYPTR(wire_write_align(c, 8));
|
TRYPTR(wire_write_align(c, 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +370,7 @@ int wire_compose_unicast_reply(wire_context_t *c, wire_context_t *msg_c, wire_me
|
||||||
// header ends on an 8 byte alignment
|
// header ends on an 8 byte alignment
|
||||||
TRYPTR(wire_write_align(c, 8));
|
TRYPTR(wire_write_align(c, 8));
|
||||||
|
|
||||||
if (c->byte_cursor + msg->body_length > c->data_len) {
|
if (c->byte_cursor + msg->body_length >= c->data_len || msg_c->byte_cursor + msg->body_length >= msg_c->data_len) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue