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 <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
@ -130,7 +132,7 @@ int jb_server_client_assign_unique_name(struct jb_server *s, int i)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (snprintf(name, 16, ":%"PRIu32, id) < 0) {
|
||||
if (snprintf(name, 16, ":1.%"PRIu32, id) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -241,8 +243,10 @@ int jb_server_broadcast_message(struct jb_server *s, wire_message_t *msg, wire_c
|
|||
.data_len = 4096,
|
||||
};
|
||||
|
||||
uint32_t previous_cursor = ctx->byte_cursor;
|
||||
TRYST(wire_compose_unicast_reply(&reply_ctx, ctx, msg, sender_unique_name));
|
||||
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) \
|
||||
|
||||
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];
|
||||
|
||||
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");
|
||||
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 *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);
|
||||
} 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);
|
||||
if (name_len < 1 || name_len > 256) {
|
||||
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);
|
||||
}
|
||||
} 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);
|
||||
if (name_len < 1 || name_len > 256) {
|
||||
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));
|
||||
} _reply_end()
|
||||
} 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);
|
||||
if (name_len < 1 || name_len > 256) {
|
||||
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) {
|
||||
// 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);
|
||||
if (name_len < 1 || name_len > 256) {
|
||||
return -1;
|
||||
}
|
||||
/* unused flags value */
|
||||
TRYPTR(wire_get_u32(&ctx));
|
||||
TRYPTR(wire_get_u32(ctx));
|
||||
|
||||
printf("FIXME: STUB: StartServiceByName: %s\n", name);
|
||||
|
||||
_reply_begin("u") {
|
||||
TRYPTR(wire_set_u32(&reply_ctx, 1));
|
||||
} _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) {
|
||||
char *match = TRYPTR(wire_get_string(&ctx));
|
||||
char *match = TRYPTR(wire_get_string(ctx));
|
||||
int match_len = strlen(match);
|
||||
if (match_len < 1 || match_len > MATCH_RULE_MAX) {
|
||||
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) {
|
||||
// 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);
|
||||
if (match_len < 1 || match_len > MATCH_RULE_MAX) {
|
||||
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);
|
||||
|
||||
_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) {
|
||||
_reply_begin("a{sas}") {
|
||||
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;
|
||||
|
||||
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) {
|
||||
return -1;
|
||||
destination_field->t.str = s->names[client->unique_name_index].name;
|
||||
}
|
||||
|
||||
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) {
|
||||
/* 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");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* 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");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.byte_cursor < ctx.data_len && ctx.data[ctx.byte_cursor] == 'l') {
|
||||
// another message
|
||||
TRYST(jb_server_client_process_message(s, i, ctx.data + ctx.byte_cursor, ctx.data_len - ctx.byte_cursor));
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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_list[] = "REJECTED EXTERNAL\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
|
||||
// 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" */
|
||||
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) {
|
||||
if (jb_server_client_drain_messages(s, i, (uint8_t *)first_message_begin, data_buffer_len - 7) < 0) {
|
||||
_client_die("failed to process message");
|
||||
}
|
||||
}
|
||||
|
@ -765,7 +807,7 @@ int jb_server_turn(struct jb_server *s)
|
|||
} break;
|
||||
|
||||
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");
|
||||
}
|
||||
} 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 */
|
||||
{
|
||||
/* 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 */
|
||||
{
|
||||
/* 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) {
|
||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE));
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue