don't copy the header fields in wire_compose_unicast_reply
This commit is contained in:
parent
e744f4afed
commit
5acf0e6422
3 changed files with 47 additions and 131 deletions
27
server.c
27
server.c
|
@ -327,8 +327,15 @@ int bus_broadcast_message(Bus *s, BusClient *sender_client, WireMsg *msg, WireCt
|
||||||
|
|
||||||
uint32_t previous_cursor = ctx->byte_cursor;
|
uint32_t previous_cursor = ctx->byte_cursor;
|
||||||
if (match_rule_check(sender_client, c->matches[j], msg, ctx) >= 0) {
|
if (match_rule_check(sender_client, c->matches[j], msg, ctx) >= 0) {
|
||||||
TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, sender_client->unique_name->name, false));
|
struct iovec bufs[2] = {0};
|
||||||
TRYST(send(c->fd, reply_ctx->data, reply_ctx->byte_cursor, 0));
|
uint8_t header_data[384];
|
||||||
|
WireCtx header_ctx = {
|
||||||
|
.byte_cursor = 0,
|
||||||
|
.data_len = 384,
|
||||||
|
.data = header_data
|
||||||
|
};
|
||||||
|
TRYST(wire_compose_unicast_reply(ctx, msg, sender_client->unique_name->name, bufs, &header_ctx));
|
||||||
|
TRYST(writev(c->fd, bufs, sizeof(bufs) / sizeof(bufs[0])));
|
||||||
// TODO?
|
// TODO?
|
||||||
memset(reply_ctx->data, 0, reply_ctx->data_len);
|
memset(reply_ctx->data, 0, reply_ctx->data_len);
|
||||||
}
|
}
|
||||||
|
@ -375,17 +382,17 @@ int bus_broadcast_signal(Bus *s, BusClient *client, WireCtx *ctx, WireMsg *msg)
|
||||||
int bus_unicast_message(Bus *s, WireMsg *msg, WireCtx *ctx, char *target_name, char *sender_unique_name, WireCtx *reply_ctx)
|
int bus_unicast_message(Bus *s, WireMsg *msg, WireCtx *ctx, char *target_name, char *sender_unique_name, WireCtx *reply_ctx)
|
||||||
{
|
{
|
||||||
BusClient *target = TRYPTR(bus_name_find_client(s, target_name));
|
BusClient *target = TRYPTR(bus_name_find_client(s, target_name));
|
||||||
TRYST(wire_compose_unicast_reply(reply_ctx, ctx, msg, sender_unique_name, true));
|
struct iovec bufs[2] = {0};
|
||||||
|
uint8_t header_data[384];
|
||||||
struct iovec bufs[] = {
|
WireCtx header_ctx = {
|
||||||
{ reply_ctx->data, reply_ctx->byte_cursor }, /* header made by wire_compose_unicast_reply */
|
.byte_cursor = 0,
|
||||||
{ ctx->data + reply_ctx->byte_cursor, msg->body_length } /* body */
|
.data_len = 384,
|
||||||
|
.data = header_data
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx->byte_cursor += msg->body_length;
|
TRYST(wire_compose_unicast_reply(ctx, msg, sender_unique_name, bufs, &header_ctx));
|
||||||
reply_ctx->byte_cursor += msg->body_length;
|
|
||||||
|
|
||||||
TRYST(writev(target->fd, bufs, sizeof(bufs) / sizeof(bufs[0])));
|
TRYST(writev(target->fd, bufs, sizeof(bufs) / sizeof(bufs[0])));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
148
wire.c
148
wire.c
|
@ -1,5 +1,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
#include "try.h"
|
#include "try.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "wire.h"
|
#include "wire.h"
|
||||||
|
@ -131,7 +132,13 @@ int wire_parse_message(WireCtx *c, WireMsg *msg)
|
||||||
msg->serial = *(uint32_t*)TRYPTR(wire_get_u32(c));
|
msg->serial = *(uint32_t*)TRYPTR(wire_get_u32(c));
|
||||||
msg->header_fields_length = *(uint32_t*)TRYPTR(wire_get_u32(c));
|
msg->header_fields_length = *(uint32_t*)TRYPTR(wire_get_u32(c));
|
||||||
|
|
||||||
|
TRYPTR(wire_write_align(c, 8));
|
||||||
|
|
||||||
|
msg->header_length = c->byte_cursor;
|
||||||
size_t header_fields_end = c->byte_cursor + msg->header_fields_length;
|
size_t header_fields_end = c->byte_cursor + msg->header_fields_length;
|
||||||
|
if (unlikely(header_fields_end >= c->data_len)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
VERBOSE("start parse message: type=%d, no_reply_expected=%d\n", msg->type, msg->flags & DBUS_FLAG_NO_REPLY_EXPECTED);
|
VERBOSE("start parse message: type=%d, no_reply_expected=%d\n", msg->type, msg->flags & DBUS_FLAG_NO_REPLY_EXPECTED);
|
||||||
|
|
||||||
|
@ -412,134 +419,35 @@ int wire_compose_error(WireCtx *c, WireMsg *msg, const char *error_name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *sender_unique_name, bool partial)
|
int wire_compose_unicast_reply(WireCtx *msg_c, WireMsg *msg, char *sender_unique_name, struct iovec bufs[2], WireCtx *header_ctx)
|
||||||
{
|
{
|
||||||
TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */
|
TRYPTR(wire_set_u8(header_ctx, msg->endianness)); /* endianness */
|
||||||
TRYPTR(wire_set_u8(c, msg->type)); /* type */
|
TRYPTR(wire_set_u8(header_ctx, msg->type)); /* type */
|
||||||
TRYPTR(wire_set_u8(c, msg->flags)); /* flags */
|
TRYPTR(wire_set_u8(header_ctx, msg->flags)); /* flags */
|
||||||
TRYPTR(wire_set_u8(c, DBUS_PROTOCOL_VERSION)); /* protocol_version */
|
TRYPTR(wire_set_u8(header_ctx, DBUS_PROTOCOL_VERSION)); /* protocol_version */
|
||||||
TRYPTR(wire_set_u32(c, msg->body_length)); /* body length */
|
TRYPTR(wire_set_u32(header_ctx, msg->body_length)); /* body length */
|
||||||
TRYPTR(wire_set_u32(c, msg->serial)); /* serial */
|
TRYPTR(wire_set_u32(header_ctx, msg->serial)); /* serial */
|
||||||
uint32_t *header_fields_length = TRYPTR(wire_set_u32(c, 0)); /* header_fields_length */
|
uint32_t *header_fields_length = TRYPTR(wire_set_u32(header_ctx, 0)); /* header_fields_length */
|
||||||
|
|
||||||
uint32_t header_fields_start = c->byte_cursor;
|
TRYPTR(wire_write_align(header_ctx, 8));
|
||||||
|
|
||||||
switch (msg->type) {
|
uint32_t header_fields_start = header_ctx->byte_cursor;
|
||||||
case DBUS_MESSAGE_SIGNAL: /* through */
|
|
||||||
case DBUS_MESSAGE_METHOD_CALL: {
|
TRYPTR(wire_set_u8(header_ctx, DBUS_HEADER_FIELD_SENDER));
|
||||||
// these fields are required for DBUS_MESSAGE_METHOD_CALL, so we must (hackily) check for their presence
|
TRYPTR(wire_set_signature_single_char(header_ctx, 's'));
|
||||||
// interface is not strictly required by the spec, however we require it here anyways
|
TRYPTR(wire_set_string(header_ctx, sender_unique_name));
|
||||||
WireMsgField *path_field = &msg->fields[DBUS_HEADER_FIELD_PATH];
|
TRYPTR(wire_write_align(header_ctx, 8));
|
||||||
WireMsgField *interface_field = &msg->fields[DBUS_HEADER_FIELD_INTERFACE];
|
|
||||||
WireMsgField *member_field = &msg->fields[DBUS_HEADER_FIELD_MEMBER];
|
*header_fields_length = header_ctx->byte_cursor - header_fields_start + msg->header_fields_length;
|
||||||
WireMsgField *signature_field = &msg->fields[DBUS_HEADER_FIELD_SIGNATURE];
|
|
||||||
if (!path_field->present || !interface_field->present || !interface_field->present) {
|
if (msg_c->byte_cursor + msg->body_length >= msg_c->data_len) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_PATH));
|
bufs[0] = (struct iovec){ header_ctx->data, header_ctx->byte_cursor };
|
||||||
TRYPTR(wire_set_signature_single_char(c, 'o'));
|
bufs[1] = (struct iovec){ msg_c->data + msg->header_length, msg_c->byte_cursor + msg->body_length - msg->header_length };
|
||||||
TRYPTR(wire_set_string(c, path_field->t.str));
|
|
||||||
TRYPTR(wire_write_align(c, 8));
|
|
||||||
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_INTERFACE));
|
|
||||||
TRYPTR(wire_set_signature_single_char(c, 's'));
|
|
||||||
TRYPTR(wire_set_string(c, interface_field->t.str));
|
|
||||||
TRYPTR(wire_write_align(c, 8));
|
|
||||||
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_MEMBER));
|
|
||||||
TRYPTR(wire_set_signature_single_char(c, 's'));
|
|
||||||
TRYPTR(wire_set_string(c, member_field->t.str));
|
|
||||||
TRYPTR(wire_write_align(c, 8));
|
|
||||||
|
|
||||||
if (signature_field->present) {
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE));
|
|
||||||
TRYPTR(wire_set_signature_single_char(c, 'g'));
|
|
||||||
TRYPTR(wire_set_signature(c, signature_field->t.str));
|
|
||||||
TRYPTR(wire_write_align(c, 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SENDER));
|
|
||||||
TRYPTR(wire_set_signature_single_char(c, 's'));
|
|
||||||
TRYPTR(wire_set_string(c, sender_unique_name));
|
|
||||||
// last element, don't align
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case DBUS_MESSAGE_METHOD_RETURN: {
|
|
||||||
WireMsgField *reply_serial_field = &msg->fields[DBUS_HEADER_FIELD_REPLY_SERIAL];
|
|
||||||
if (!reply_serial_field->present) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_REPLY_SERIAL));
|
|
||||||
TRYPTR(wire_set_signature_single_char(c, 'u'));
|
|
||||||
TRYPTR(wire_set_u32(c, reply_serial_field->t.u32));
|
|
||||||
TRYPTR(wire_write_align(c, 8));
|
|
||||||
|
|
||||||
WireMsgField *signature_field = &msg->fields[DBUS_HEADER_FIELD_SIGNATURE];
|
|
||||||
if (signature_field->present) {
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE));
|
|
||||||
TRYPTR(wire_set_signature_single_char(c, 'g'));
|
|
||||||
TRYPTR(wire_set_signature(c, signature_field->t.str));
|
|
||||||
TRYPTR(wire_write_align(c, 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SENDER));
|
|
||||||
TRYPTR(wire_set_signature_single_char(c, 's'));
|
|
||||||
TRYPTR(wire_set_string(c, sender_unique_name));
|
|
||||||
// last element, don't align
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case DBUS_MESSAGE_ERROR: {
|
|
||||||
WireMsgField *reply_serial_field = &msg->fields[DBUS_HEADER_FIELD_REPLY_SERIAL];
|
|
||||||
WireMsgField *error_name_field = &msg->fields[DBUS_HEADER_FIELD_ERROR_NAME];
|
|
||||||
if (!reply_serial_field->present || !error_name_field->present) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_REPLY_SERIAL));
|
|
||||||
TRYPTR(wire_set_signature_single_char(c, 'u'));
|
|
||||||
TRYPTR(wire_set_u32(c, reply_serial_field->t.u32));
|
|
||||||
TRYPTR(wire_write_align(c, 8));
|
|
||||||
|
|
||||||
WireMsgField *signature_field = &msg->fields[DBUS_HEADER_FIELD_SIGNATURE];
|
|
||||||
if (signature_field->present) {
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE));
|
|
||||||
TRYPTR(wire_set_signature_single_char(c, 'g'));
|
|
||||||
TRYPTR(wire_set_signature(c, signature_field->t.str));
|
|
||||||
TRYPTR(wire_write_align(c, 8));
|
|
||||||
}
|
|
||||||
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_ERROR_NAME));
|
|
||||||
TRYPTR(wire_set_signature_single_char(c, 's'));
|
|
||||||
TRYPTR(wire_set_string(c, error_name_field->t.str));
|
|
||||||
TRYPTR(wire_write_align(c, 8));
|
|
||||||
|
|
||||||
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SENDER));
|
|
||||||
TRYPTR(wire_set_signature_single_char(c, 's'));
|
|
||||||
TRYPTR(wire_set_string(c, sender_unique_name));
|
|
||||||
// last element, don't align
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default: {
|
|
||||||
return -1;
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*header_fields_length = c->byte_cursor - header_fields_start;
|
|
||||||
|
|
||||||
// header ends on an 8 byte alignment
|
|
||||||
TRYPTR(wire_write_align(c, 8));
|
|
||||||
|
|
||||||
if (c->byte_cursor + msg->body_length >= c->data_len || msg_c->byte_cursor + msg->body_length >= msg_c->data_len) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!partial) {
|
|
||||||
memcpy(&c->data[c->byte_cursor], &msg_c->data[msg_c->byte_cursor], msg->body_length);
|
|
||||||
c->byte_cursor += msg->body_length;
|
|
||||||
msg_c->byte_cursor += msg->body_length;
|
msg_c->byte_cursor += msg->body_length;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
5
wire.h
5
wire.h
|
@ -4,6 +4,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "try.h"
|
#include "try.h"
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ typedef struct {
|
||||||
#define WIRE_MESSAGE_MAX_HEADER_FIELDS 9
|
#define WIRE_MESSAGE_MAX_HEADER_FIELDS 9
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t endianness, type, flags, protocol_version;
|
uint8_t endianness, type, flags, protocol_version;
|
||||||
uint32_t body_length, serial, header_fields_length;
|
uint32_t body_length, serial, header_fields_length, header_length;
|
||||||
uint8_t header_fields_count;
|
uint8_t header_fields_count;
|
||||||
WireMsgField fields[WIRE_MESSAGE_MAX_HEADER_FIELDS]; /* cannot have more than 9 header fields */
|
WireMsgField fields[WIRE_MESSAGE_MAX_HEADER_FIELDS]; /* cannot have more than 9 header fields */
|
||||||
} WireMsg;
|
} WireMsg;
|
||||||
|
@ -128,7 +129,7 @@ char *wire_get_string_check(WireCtx *c, int min_length, int max_length);
|
||||||
int wire_parse_message(WireCtx *c, WireMsg *msg);
|
int wire_parse_message(WireCtx *c, WireMsg *msg);
|
||||||
int wire_compose_reply(WireCtx *c, WireMsg *msg, const char *signature, uint32_t **out_body_length);
|
int wire_compose_reply(WireCtx *c, WireMsg *msg, const char *signature, uint32_t **out_body_length);
|
||||||
int wire_compose_error(WireCtx *c, WireMsg *msg, const char *error_name);
|
int wire_compose_error(WireCtx *c, WireMsg *msg, const char *error_name);
|
||||||
int wire_compose_unicast_reply(WireCtx *c, WireCtx *msg_c, WireMsg *msg, char *sender_unique_name, bool partial);
|
int wire_compose_unicast_reply(WireCtx *msg_c, WireMsg *msg, char *sender_unique_name, struct iovec bufs[2], WireCtx *header_ctx);
|
||||||
int wire_compose_signal(WireCtx *c, WireMsg *out_msg, const char *signature, const char *member, uint32_t **out_body_length);
|
int wire_compose_signal(WireCtx *c, WireMsg *out_msg, const char *signature, const char *member, uint32_t **out_body_length);
|
||||||
int wire_collect_strings(WireCtx *c, WireMsg *msg, WireMsgBodyString *strings, int strings_count);
|
int wire_collect_strings(WireCtx *c, WireMsg *msg, WireMsgBodyString *strings, int strings_count);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue