diff --git a/main.c b/main.c index 7083319..8bbe17a 100644 --- a/main.c +++ b/main.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "match.h" #include "server.h" @@ -23,6 +24,9 @@ int main(int argc, char *argv[]) const char *socket_path = arg_shift(&argc, &argv); socket_path = socket_path == NULL ? "/tmp/jitterbug-unix0" : socket_path; + /* we handle send() errors directly in the code */ + signal(SIGPIPE, SIG_IGN); + struct jb_server *srv = jb_server_create(socket_path); if (srv == NULL) { fprintf(stderr, "server_create failed\n"); diff --git a/server.c b/server.c index 0eb4d0b..5a7ed43 100644 --- a/server.c +++ b/server.c @@ -249,26 +249,47 @@ int jb_server_broadcast_message(struct jb_server *s, wire_message_t *msg, wire_c return 0; } +int jb_server_unicast_message(struct jb_server *s, wire_message_t *msg, wire_context_t *ctx, char *target_name, char *sender_unique_name) +{ + struct jb_client *target = jb_server_name_find_client(s, target_name); + if (!target) { + return -1; + } + + uint8_t reply_data[4096]; + memset(reply_data, 0, 4096); + wire_context_t reply_ctx = { + .byte_cursor = 0, + .data = reply_data, + .data_len = 4096, + }; + + TRYST(wire_compose_unicast_reply(&reply_ctx, ctx, msg, sender_unique_name)); + TRYST(send(target->fd, reply_data, reply_ctx.byte_cursor, 0)); + + return 0; +} + #define _reply_begin(M_sig) \ - do { \ + if (!(msg.flags & DBUS_FLAG_NO_REPLY_EXPECTED)) { \ TRYST(wire_compose_reply(&reply_ctx, &msg, (M_sig), &body_length)); \ body_start = reply_ctx.byte_cursor; \ - } while(0); \ #define _reply_end() \ - do { \ *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("send: sent %d bytes!\n", reply_ctx.byte_cursor); \ - } while(0); \ + } /* if (!(msg.flags & DBUS_FLAG_NO_REPLY_EXPECTED)) */ #define _reply_error(message) \ do { \ - TRYST(wire_compose_error(&reply_ctx, &msg, (message))); \ - if (send(s->fds[i].fd, reply_data, reply_ctx.byte_cursor, 0) != reply_ctx.byte_cursor) { \ - return -1; \ + if (!(msg.flags & DBUS_FLAG_NO_REPLY_EXPECTED)) { \ + TRYST(wire_compose_error(&reply_ctx, &msg, (message))); \ + if (send(s->fds[i].fd, reply_data, reply_ctx.byte_cursor, 0) != reply_ctx.byte_cursor) { \ + return -1; \ + } \ } \ } while(0) \ @@ -536,16 +557,16 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, } if (destination_field->present) { /* unicast */ - struct jb_client *target = jb_server_name_find_client(s, destination_field->t.str); - if (!target) { - _reply_error("org.freedesktop.DBus.Error.NameHasNoOwner"); + 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; } - TRYST(wire_compose_unicast_reply(&reply_ctx, &ctx, &msg, s->names[client->unique_name_index].name)); - TRYST(send(target->fd, reply_data, reply_ctx.byte_cursor, 0)); } else { /* broadcast */ - TRYST(jb_server_broadcast_message(s, &msg, &ctx, s->names[client->unique_name_index].name)); + if (jb_server_broadcast_message(s, &msg, &ctx, s->names[client->unique_name_index].name) < 0) { + _reply_error("xyz.hippoz.jitterbug.BroadcastFailed"); + return 0; + } } } diff --git a/wire.c b/wire.c index 382db6a..c0df1d5 100644 --- a/wire.c +++ b/wire.c @@ -172,7 +172,7 @@ int wire_compose_reply(wire_context_t *c, wire_message_t *msg, const char *signa TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */ TRYPTR(wire_set_u8(c, DBUS_MESSAGE_METHOD_RETURN)); /* type */ - TRYPTR(wire_set_u8(c, 0)); /* flags */ + TRYPTR(wire_set_u8(c, 0 | DBUS_FLAG_NO_REPLY_EXPECTED)); /* flags */ TRYPTR(wire_set_u8(c, DBUS_PROTOCOL_VERSION)); /* protocol_version */ uint32_t *body_length = TRYPTR(wire_set_u32(c, 0)); /* body length */ TRYPTR(wire_set_u32(c, msg->serial+1)); /* serial */ @@ -273,7 +273,7 @@ int wire_compose_unicast_reply(wire_context_t *c, wire_context_t *msg_c, wire_me { TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */ TRYPTR(wire_set_u8(c, msg->type)); /* type */ - TRYPTR(wire_set_u8(c, 0)); /* flags */ + TRYPTR(wire_set_u8(c, msg->flags)); /* flags */ TRYPTR(wire_set_u8(c, DBUS_PROTOCOL_VERSION)); /* protocol_version */ TRYPTR(wire_set_u32(c, msg->body_length)); /* body length */ TRYPTR(wire_set_u32(c, msg->serial)); /* serial */