diff --git a/match.c b/match.c index 4766d91..c35aefe 100644 --- a/match.c +++ b/match.c @@ -10,6 +10,7 @@ void match_rule_free(match_rule_t *rule) { if (rule) { + free(rule->rule_string); free(rule->sender); free(rule->interface); free(rule->member); @@ -41,6 +42,8 @@ match_rule_t *match_rule_from_string(char *d) return NULL; } + rule->rule_string = string_dup(d); + while (*d) { /* key */ key = d; diff --git a/match.h b/match.h index 9050804..63ca924 100644 --- a/match.h +++ b/match.h @@ -11,7 +11,7 @@ typedef struct match_rule { uint8_t type; bool eavesdrop; - char *sender, *interface, *member, *path, *path_namespace, *destination, *arg0namespace; + 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_path[MATCH_RULE_MAX_ARG]; /* TODO: spec states that indexes 0 to 63 should be supported */ } match_rule_t; diff --git a/server.c b/server.c index b5463e4..20ee29c 100644 --- a/server.c +++ b/server.c @@ -288,6 +288,8 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, return -1; } + printf("process_message: processed %d/%zu bytes\n", ctx.byte_cursor, 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]; bool should_forward = false; @@ -390,19 +392,24 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, } _reply_end() } else if (strcmp(member, "ListNames") == 0) { _reply_begin("as") { - TRYPTR(wire_set_u32(&reply_ctx, s->names_count)); - printf("ListNames %d\n", s->names_count); + uint32_t *array_length = TRYPTR(wire_set_u32(&reply_ctx, 0)); + + /* arrays start with the alignment of the type they contain */ + TRYPTR(wire_write_align(&reply_ctx, 4)); + + uint32_t array_start = reply_ctx.byte_cursor; + + TRYPTR(wire_set_string(&reply_ctx, "org.freedesktop.DBus")); int left = s->names_count; - for (int i = 0; i < JB_MAX_NAMES; i++) { + for (int i = 0; i < JB_MAX_NAMES && left > 0; i++) { if (s->names[i].name && s->names[i].client_index >= 0) { left--; TRYPTR(wire_set_string(&reply_ctx, s->names[i].name)); } - if (left <= 0) { - break; - } } + + *array_length = reply_ctx.byte_cursor - array_start; } _reply_end() } else if (strcmp(member, "ListActivatableNames") == 0) { // TODO: stub (always returns empty array) @@ -436,9 +443,9 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, return -1; } - TRYST(jb_server_client_match_add(s, i, match)); + printf("client index %d adding match rule: '%s'\n", i, match); - printf("client index %d just added match rule: '%s'\n", i, match); + TRYST(jb_server_client_match_add(s, i, match)); _reply_begin("") {} _reply_end() } else if (strcmp(member, "RemoveMatch") == 0) { @@ -453,6 +460,44 @@ 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, "GetAllMatchRules") == 0) { + _reply_begin("a{sas}") { + uint32_t *outer_array_len = TRYPTR(wire_set_u32(&reply_ctx, 0)); + TRYPTR(wire_write_align(&reply_ctx, 8)); /* arrays start with the alignment of the type they contain */ + uint32_t outer_array_start = reply_ctx.byte_cursor; + + int left = s->names_count; + for (int i = 0; i < JB_MAX_NAMES && left > 0; i++) { + struct jb_name *n = &s->names[i]; + if (!n->name || n->client_index < 0 || *n->name != ':') { + continue; + } + left--; + + TRYPTR(wire_write_align(&reply_ctx, 8)); /* structs always aligned to 8 */ + + struct jb_client *c = &s->clients[s->names[i].client_index]; + + TRYPTR(wire_set_string(&reply_ctx, s->names[i].name)); /* unique name */ + + /* array of all match rules */ + int match_left = c->match_count; + uint32_t *name_array_len = TRYPTR(wire_set_u32(&reply_ctx, 0)); + TRYPTR(wire_write_align(&reply_ctx, 4)); /* arrays start with the alignment of the type they contain */ + uint32_t name_array_start = reply_ctx.byte_cursor; + for (int i = 0; i < JB_MAX_MATCH && match_left > 0; i++) { + if (!c->matches[i]) { + continue; + } + match_left--; + + TRYPTR(wire_set_string(&reply_ctx, c->matches[i]->rule_string)); + } + *name_array_len = reply_ctx.byte_cursor - name_array_start; + } + + *outer_array_len = reply_ctx.byte_cursor - outer_array_start; + } _reply_end() } else { printf("FIXME: daemon method '%s' is not implemented or invalid\n", member); _reply_error("org.freedesktop.DBus.Error.UnknownMethod"); @@ -497,6 +542,11 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, } } + 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; } @@ -637,6 +687,8 @@ int jb_server_turn(struct jb_server *s) continue; } + printf("\nrecv: got %zd bytes\n", bytes); + struct jb_client *c = &s->clients[i]; switch (c->state) { case JB_CLIENT_STATE_WAIT_AUTH: { diff --git a/try.h b/try.h index 39a5306..2b55122 100644 --- a/try.h +++ b/try.h @@ -1,5 +1,9 @@ -#define TRYPTR_NIL(M_expr) ({ void* _result = (void*)(M_expr); if (!_result) { return (NULL); } _result; }) -#define TRYPTR(M_expr) ({ void* _result = (void*)(M_expr); if (!_result) { return (-1); } _result; }) +#define __TRY_TRACE() do { \ + printf("trace: %s:%d\n", __FILE__, __LINE__); \ + } while(0) \ -#define TRYST_NIL(M_expr) ({ int _result = (int)(M_expr); if (_result < 0) { return (NULL); } _result; }) -#define TRYST(M_expr) ({ int _result = (int)(M_expr); if (_result < 0) { return (-1); } _result; }) +#define TRYPTR_NIL(M_expr) ({ void* _result = (void*)(M_expr); if (!_result) { __TRY_TRACE(); return (NULL); } _result; }) +#define TRYPTR(M_expr) ({ void* _result = (void*)(M_expr); if (!_result) { __TRY_TRACE(); return (-1); } _result; }) + +#define TRYST_NIL(M_expr) ({ int _result = (int)(M_expr); if (_result < 0) { __TRY_TRACE(); return (NULL); } _result; }) +#define TRYST(M_expr) ({ int _result = (int)(M_expr); if (_result < 0) { __TRY_TRACE(); return (-1); } _result; }) diff --git a/wire.c b/wire.c index 6b84dde..382db6a 100644 --- a/wire.c +++ b/wire.c @@ -118,7 +118,7 @@ int wire_parse_message(wire_context_t *c, wire_message_t *msg) size_t header_fields_end = c->byte_cursor + msg->header_fields_length; - WIRE_VERBOSE("\nstart parse message: type=%d, no_reply_expected=%d\n", msg->type, msg->flags & DBUS_FLAG_NO_REPLY_EXPECTED); + WIRE_VERBOSE("start parse message: type=%d, no_reply_expected=%d\n", msg->type, msg->flags & DBUS_FLAG_NO_REPLY_EXPECTED); while (c->byte_cursor < header_fields_end) { uint8_t field_code = *(uint8_t*)TRYPTR(wire_get_u8(c));