2022-12-21 00:38:10 +02:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2023-01-21 05:43:00 +02:00
|
|
|
#include <sys/uio.h>
|
2022-12-21 00:38:10 +02:00
|
|
|
#include "try.h"
|
2023-01-19 22:47:47 +02:00
|
|
|
#include "util.h"
|
2022-12-21 00:38:10 +02:00
|
|
|
#include "wire.h"
|
2023-01-16 02:20:53 +02:00
|
|
|
#include "log.h"
|
2022-12-26 20:28:56 +02:00
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#id-1.4.6
|
2023-01-16 00:39:13 +02:00
|
|
|
_WIRE_DEF_BYTE_TYPE(i8, int8_t)
|
|
|
|
_WIRE_DEF_BYTE_TYPE(u8, uint8_t)
|
|
|
|
_WIRE_DEF_TYPE(i16, int16_t, 2)
|
|
|
|
_WIRE_DEF_TYPE(u16, uint16_t, 2)
|
|
|
|
_WIRE_DEF_TYPE(i32, int32_t, 4)
|
|
|
|
_WIRE_DEF_TYPE(u32, uint32_t, 4)
|
|
|
|
_WIRE_DEF_TYPE(boolean, uint32_t, 4)
|
2022-12-21 00:38:10 +02:00
|
|
|
|
2023-01-19 22:47:47 +02:00
|
|
|
bool wire_write_align(WireCtx *c, uint32_t alignment)
|
|
|
|
{
|
|
|
|
// Thanks: https://github.com/c-util/c-stdaux/blob/ed5fee49a3ec13fe79f30324b23c73cd41805514/src/c-stdaux-gnuc.h#L431
|
|
|
|
uint32_t new_cursor = ((c->byte_cursor) + (alignment) - 1) & ~((alignment) - 1);
|
|
|
|
|
|
|
|
if (unlikely(new_cursor >= c->data_len || new_cursor < c->byte_cursor)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
while (c->byte_cursor < new_cursor) {
|
|
|
|
c->data[c->byte_cursor++] = '\0';
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool wire_align(WireCtx *c, uint32_t alignment)
|
|
|
|
{
|
|
|
|
// Thanks: https://github.com/c-util/c-stdaux/blob/ed5fee49a3ec13fe79f30324b23c73cd41805514/src/c-stdaux-gnuc.h#L431
|
|
|
|
uint32_t new_cursor = ((c->byte_cursor) + (alignment) - 1) & ~((alignment) - 1);
|
|
|
|
|
|
|
|
if (unlikely(new_cursor >= c->data_len || new_cursor < c->byte_cursor)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
c->byte_cursor = new_cursor;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *wire_set_signature_single_char(WireCtx *c, const char s)
|
|
|
|
{
|
|
|
|
TRYPTR_NIL(wire_set_u8(c, 1));
|
|
|
|
|
|
|
|
uint32_t new_cursor = c->byte_cursor + 2; /* + 2 because of the extra null termination that strings have */
|
|
|
|
if (unlikely(new_cursor >= c->data_len)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO?
|
|
|
|
char *dest = (char*)&c->data[c->byte_cursor];
|
|
|
|
dest[0] = s;
|
|
|
|
dest[1] = '\0';
|
|
|
|
|
|
|
|
c->byte_cursor = new_cursor;
|
|
|
|
|
|
|
|
return dest;
|
|
|
|
}
|
|
|
|
|
2023-01-19 02:46:49 +02:00
|
|
|
char *wire_get_string_impl(WireCtx *c, bool as_signature)
|
2022-12-21 00:38:10 +02:00
|
|
|
{
|
2022-12-26 21:13:09 +02:00
|
|
|
uint32_t len = 0;
|
|
|
|
if (as_signature) {
|
|
|
|
len = *(uint8_t*)TRYPTR_NIL(wire_get_u8(c));
|
|
|
|
} else {
|
|
|
|
len = *(uint32_t*)TRYPTR_NIL(wire_get_u32(c));
|
2022-12-21 00:38:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t new_cursor = c->byte_cursor + len + 1; /* + 1 because of the extra null termination that strings have */
|
2023-01-16 16:04:09 +02:00
|
|
|
if (unlikely(new_cursor >= c->data_len)) {
|
2022-12-21 00:38:10 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-12-26 23:10:22 +02:00
|
|
|
// strings always end with a null byte
|
2023-01-16 16:04:09 +02:00
|
|
|
if (unlikely(c->data[c->byte_cursor + len] != '\0')) {
|
2022-12-26 23:10:22 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
char *str = (char *)&c->data[c->byte_cursor];
|
|
|
|
|
|
|
|
c->byte_cursor = new_cursor;
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2023-01-19 02:46:49 +02:00
|
|
|
char *wire_set_string_impl(WireCtx *c, const char *str, bool as_signature)
|
2022-12-21 00:38:10 +02:00
|
|
|
{
|
|
|
|
uint32_t len = strlen(str);
|
2022-12-26 21:13:09 +02:00
|
|
|
if (as_signature) {
|
|
|
|
TRYPTR_NIL(wire_set_u8(c, len));
|
|
|
|
} else {
|
|
|
|
TRYPTR_NIL(wire_set_u32(c, len));
|
2022-12-21 00:38:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t new_cursor = c->byte_cursor + len + 1; /* + 1 because of the extra null termination that strings have */
|
2023-01-16 16:04:09 +02:00
|
|
|
if (unlikely(new_cursor >= c->data_len)) {
|
2022-12-21 00:38:10 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO?
|
|
|
|
char *dest = (char*)&c->data[c->byte_cursor];
|
|
|
|
memcpy(dest, str, len + 1);
|
|
|
|
|
|
|
|
c->byte_cursor = new_cursor;
|
|
|
|
|
|
|
|
return dest;
|
|
|
|
}
|
|
|
|
|
2023-01-19 02:46:49 +02:00
|
|
|
char *wire_get_string_check(WireCtx *c, int min_length, int max_length) {
|
2023-01-10 15:17:50 +02:00
|
|
|
char *str = TRYPTR_NIL(wire_get_string_impl(c, false));
|
|
|
|
int length = strlen(str);
|
2023-01-16 16:04:09 +02:00
|
|
|
if (unlikely(length < min_length || length > max_length)) return NULL;
|
2023-01-10 15:17:50 +02:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2023-01-19 02:46:49 +02:00
|
|
|
int wire_parse_message(WireCtx *c, WireMsg *msg)
|
2022-12-21 00:38:10 +02:00
|
|
|
{
|
|
|
|
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
|
2022-12-25 20:54:10 +02:00
|
|
|
msg->endianness = *(uint8_t*)TRYPTR(wire_get_u8(c));
|
2022-12-26 20:31:12 +02:00
|
|
|
if (msg->endianness == 'B') {
|
|
|
|
// we only support little endian
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2022-12-25 20:54:10 +02:00
|
|
|
msg->type = *(uint8_t*)TRYPTR(wire_get_u8(c));
|
|
|
|
msg->flags = *(uint8_t*)TRYPTR(wire_get_u8(c));
|
|
|
|
msg->protocol_version = *(uint8_t*)TRYPTR(wire_get_u8(c));
|
|
|
|
msg->body_length = *(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));
|
2022-12-21 00:38:10 +02:00
|
|
|
|
2023-01-21 05:43:00 +02:00
|
|
|
TRYPTR(wire_write_align(c, 8));
|
|
|
|
|
|
|
|
msg->header_length = c->byte_cursor;
|
2022-12-21 00:38:10 +02:00
|
|
|
size_t header_fields_end = c->byte_cursor + msg->header_fields_length;
|
2023-01-21 05:43:00 +02:00
|
|
|
if (unlikely(header_fields_end >= c->data_len)) {
|
|
|
|
return -1;
|
|
|
|
}
|
2022-12-21 00:38:10 +02:00
|
|
|
|
2023-01-16 02:20:53 +02:00
|
|
|
VERBOSE("start parse message: type=%d, no_reply_expected=%d\n", msg->type, msg->flags & DBUS_FLAG_NO_REPLY_EXPECTED);
|
2022-12-26 18:05:12 +02:00
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
while (c->byte_cursor < header_fields_end) {
|
2022-12-25 20:54:10 +02:00
|
|
|
uint8_t field_code = *(uint8_t*)TRYPTR(wire_get_u8(c));
|
2022-12-26 21:13:09 +02:00
|
|
|
TRYPTR(wire_get_signature(c));
|
2022-12-21 00:38:10 +02:00
|
|
|
|
|
|
|
switch (field_code) {
|
2022-12-23 23:58:18 +02:00
|
|
|
case DBUS_HEADER_FIELD_PATH: /* through */
|
|
|
|
case DBUS_HEADER_FIELD_INTERFACE: /* through */
|
|
|
|
case DBUS_HEADER_FIELD_MEMBER: /* through */
|
2023-01-16 17:44:45 +02:00
|
|
|
case DBUS_HEADER_FIELD_ERROR_NAME: /* through */
|
2022-12-21 00:38:10 +02:00
|
|
|
case DBUS_HEADER_FIELD_DESTINATION: {
|
2022-12-26 21:13:09 +02:00
|
|
|
char *str = TRYPTR(wire_get_string(c));
|
2023-01-16 02:20:53 +02:00
|
|
|
VERBOSE("field: %s\n", str);
|
2022-12-23 23:58:18 +02:00
|
|
|
msg->fields[field_code].t.str = str;
|
2022-12-21 00:38:10 +02:00
|
|
|
} break;
|
2022-12-21 21:38:48 +02:00
|
|
|
case DBUS_HEADER_FIELD_SIGNATURE: {
|
2022-12-26 21:13:09 +02:00
|
|
|
char *str = TRYPTR(wire_get_signature(c));
|
2023-01-16 02:20:53 +02:00
|
|
|
VERBOSE("field: %s\n", str);
|
2022-12-23 23:58:18 +02:00
|
|
|
msg->fields[field_code].t.str = str;
|
|
|
|
} break;
|
|
|
|
case DBUS_HEADER_FIELD_REPLY_SERIAL: {
|
2022-12-25 20:54:10 +02:00
|
|
|
uint32_t u = *(uint32_t*)TRYPTR(wire_get_u32(c));
|
2023-01-16 02:20:53 +02:00
|
|
|
VERBOSE("field: %d\n", u);
|
2022-12-23 23:58:18 +02:00
|
|
|
msg->fields[field_code].t.u32 = u;
|
2022-12-21 21:38:48 +02:00
|
|
|
} break;
|
2022-12-21 00:38:10 +02:00
|
|
|
default: {
|
2023-01-18 01:23:07 +02:00
|
|
|
WARN("header: unknown field: %d\n", field_code);
|
2022-12-21 00:38:10 +02:00
|
|
|
return -1;
|
|
|
|
} break;
|
|
|
|
}
|
2022-12-23 23:58:18 +02:00
|
|
|
msg->fields[field_code].present = true;
|
2022-12-21 00:38:10 +02:00
|
|
|
|
|
|
|
// Structs are always aligned to `8`.
|
|
|
|
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#id-1.4.6
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_align(c, 8));
|
2022-12-21 00:38:10 +02:00
|
|
|
|
|
|
|
if (msg->header_fields_count++ > WIRE_MESSAGE_MAX_HEADER_FIELDS) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-16 02:20:53 +02:00
|
|
|
VERBOSE("end parse message\n");
|
2022-12-26 18:05:12 +02:00
|
|
|
|
2022-12-21 21:38:48 +02:00
|
|
|
/* header ends at 8 byte boundry */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_align(c, 8));
|
2022-12-21 21:38:48 +02:00
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-01-19 02:46:49 +02:00
|
|
|
int wire_compose_signal(WireCtx *c, WireMsg *out_msg, const char *signature, const char *member, uint32_t **out_body_length)
|
2023-01-15 04:32:51 +02:00
|
|
|
{
|
|
|
|
out_msg->endianness = 'l';
|
|
|
|
TRYPTR(wire_set_u8(c, 'l')); /* endianness */
|
|
|
|
out_msg->type = DBUS_MESSAGE_SIGNAL;
|
|
|
|
TRYPTR(wire_set_u8(c, DBUS_MESSAGE_SIGNAL)); /* type */
|
|
|
|
out_msg->flags = 0 | DBUS_FLAG_NO_REPLY_EXPECTED;
|
|
|
|
TRYPTR(wire_set_u8(c, out_msg->flags)); /* flags */
|
|
|
|
out_msg->protocol_version = DBUS_PROTOCOL_VERSION;
|
|
|
|
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, 1)); /* serial */
|
|
|
|
uint32_t *header_fields_length = TRYPTR(wire_set_u32(c, 0)); /* header_fields_length */
|
|
|
|
|
|
|
|
uint32_t header_fields_start = c->byte_cursor;
|
|
|
|
|
|
|
|
/* header fields */
|
|
|
|
{
|
|
|
|
/* SENDER */
|
|
|
|
{
|
|
|
|
out_msg->fields[DBUS_HEADER_FIELD_SENDER].t.str = "org.freedesktop.DBus";
|
|
|
|
out_msg->fields[DBUS_HEADER_FIELD_SENDER].present = true;
|
|
|
|
|
|
|
|
/* 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));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* INTERFACE */
|
|
|
|
{
|
|
|
|
out_msg->fields[DBUS_HEADER_FIELD_INTERFACE].t.str = "org.freedesktop.DBus";
|
|
|
|
out_msg->fields[DBUS_HEADER_FIELD_INTERFACE].present = true;
|
|
|
|
|
|
|
|
/* byte (field code) */
|
|
|
|
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_INTERFACE));
|
|
|
|
/* 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));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* PATH */
|
|
|
|
{
|
|
|
|
out_msg->fields[DBUS_HEADER_FIELD_PATH].t.str = "/org/freedesktop/DBus";
|
|
|
|
out_msg->fields[DBUS_HEADER_FIELD_PATH].present = true;
|
|
|
|
|
|
|
|
/* byte (field code) */
|
|
|
|
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_PATH));
|
|
|
|
/* variant */
|
|
|
|
/* signature */
|
|
|
|
TRYPTR(wire_set_signature(c, "o"));
|
|
|
|
/* 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));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* MEMBER */
|
|
|
|
{
|
|
|
|
out_msg->fields[DBUS_HEADER_FIELD_MEMBER].t.str = (char*)member;
|
|
|
|
out_msg->fields[DBUS_HEADER_FIELD_MEMBER].present = true;
|
|
|
|
|
|
|
|
/* byte (field code) */
|
|
|
|
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_MEMBER));
|
|
|
|
/* variant */
|
|
|
|
/* signature */
|
|
|
|
TRYPTR(wire_set_signature(c, "s"));
|
|
|
|
/* string */
|
|
|
|
TRYPTR(wire_set_string(c, member));
|
|
|
|
|
|
|
|
// need to align to 8 byte boundry after each array element?
|
|
|
|
TRYPTR(wire_write_align(c, 8));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* SIGNATURE */
|
|
|
|
{
|
|
|
|
out_msg->fields[DBUS_HEADER_FIELD_SIGNATURE].t.str = (char*)signature;
|
|
|
|
out_msg->fields[DBUS_HEADER_FIELD_SIGNATURE].present = true;
|
|
|
|
|
|
|
|
/* byte (field code) */
|
|
|
|
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE));
|
|
|
|
/* variant */
|
|
|
|
/* signature */
|
|
|
|
TRYPTR(wire_set_signature(c, "g"));
|
|
|
|
/* signature */
|
|
|
|
TRYPTR(wire_set_signature(c, signature));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*header_fields_length = c->byte_cursor - header_fields_start;
|
|
|
|
|
|
|
|
// header ends on an 8 byte alignment
|
|
|
|
TRYPTR(wire_write_align(c, 8));
|
|
|
|
|
|
|
|
if (out_body_length) {
|
|
|
|
*out_body_length = body_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-01-19 02:46:49 +02:00
|
|
|
int wire_compose_reply(WireCtx *c, WireMsg *msg, const char *signature, uint32_t **out_body_length)
|
2022-12-21 00:38:10 +02:00
|
|
|
{
|
|
|
|
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */
|
|
|
|
TRYPTR(wire_set_u8(c, DBUS_MESSAGE_METHOD_RETURN)); /* type */
|
2023-01-03 17:20:02 +02:00
|
|
|
TRYPTR(wire_set_u8(c, 0 | DBUS_FLAG_NO_REPLY_EXPECTED)); /* flags */
|
2022-12-25 20:54:10 +02:00
|
|
|
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 */
|
|
|
|
uint32_t *header_fields_length = TRYPTR(wire_set_u32(c, 0)); /* header_fields_length */
|
2022-12-21 00:38:10 +02:00
|
|
|
|
|
|
|
uint32_t header_fields_start = c->byte_cursor;
|
|
|
|
|
|
|
|
/* header fields */
|
|
|
|
{
|
2023-01-03 19:06:44 +02:00
|
|
|
/* 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));
|
|
|
|
}
|
|
|
|
|
2022-12-21 00:38:10 +02:00
|
|
|
/* SIGNATURE */
|
|
|
|
{
|
|
|
|
/* byte (field code) */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE));
|
2022-12-21 00:38:10 +02:00
|
|
|
/* variant */
|
|
|
|
/* signature */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_signature(c, "g"));
|
2022-12-21 00:38:10 +02:00
|
|
|
/* signature */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_signature(c, signature));
|
2022-12-21 00:38:10 +02:00
|
|
|
|
|
|
|
// need to align to 8 byte boundry after each array element?
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_write_align(c, 8));
|
2022-12-21 00:38:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* REPLY_SERIAL */
|
|
|
|
{
|
|
|
|
/* byte (field code) */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_REPLY_SERIAL));
|
2022-12-21 00:38:10 +02:00
|
|
|
/* variant */
|
|
|
|
/* signature */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_signature(c, "u"));
|
2022-12-21 00:38:10 +02:00
|
|
|
/* reply serial */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_u32(c, msg->serial));
|
2022-12-21 00:38:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*header_fields_length = c->byte_cursor - header_fields_start;
|
|
|
|
|
|
|
|
// header ends on an 8 byte alignment
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_write_align(c, 8));
|
2022-12-21 00:38:10 +02:00
|
|
|
|
|
|
|
if (out_body_length) {
|
|
|
|
*out_body_length = body_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2022-12-21 21:38:48 +02:00
|
|
|
|
2023-01-19 02:46:49 +02:00
|
|
|
int wire_compose_error(WireCtx *c, WireMsg *msg, const char *error_name)
|
2022-12-21 21:38:48 +02:00
|
|
|
{
|
|
|
|
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_u8(c, msg->endianness)); /* endianness */
|
|
|
|
TRYPTR(wire_set_u8(c, DBUS_MESSAGE_ERROR)); /* type */
|
|
|
|
TRYPTR(wire_set_u8(c, 0)); /* flags */
|
|
|
|
TRYPTR(wire_set_u8(c, DBUS_PROTOCOL_VERSION)); /* protocol_version */
|
|
|
|
TRYPTR(wire_set_u32(c, 0)); /* body length */
|
|
|
|
TRYPTR(wire_set_u32(c, msg->serial+1)); /* serial */
|
|
|
|
uint32_t *header_fields_length = TRYPTR(wire_set_u32(c, 0)); /* header_fields_length */
|
2022-12-21 21:38:48 +02:00
|
|
|
|
|
|
|
uint32_t header_fields_start = c->byte_cursor;
|
|
|
|
|
|
|
|
/* header fields */
|
|
|
|
{
|
|
|
|
/* ERROR_NAME */
|
|
|
|
{
|
|
|
|
/* byte (field code) */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_ERROR_NAME));
|
2022-12-21 21:38:48 +02:00
|
|
|
/* variant */
|
|
|
|
/* signature */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_signature(c, "s"));
|
2022-12-21 21:38:48 +02:00
|
|
|
/* string */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_string(c, error_name));
|
2022-12-21 21:38:48 +02:00
|
|
|
|
|
|
|
// need to align to 8 byte boundry after each array element?
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_write_align(c, 8));
|
2022-12-21 21:38:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* REPLY_SERIAL */
|
|
|
|
{
|
|
|
|
/* byte (field code) */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_REPLY_SERIAL));
|
2022-12-21 21:38:48 +02:00
|
|
|
/* variant */
|
|
|
|
/* signature */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_signature(c, "u"));
|
2022-12-21 21:38:48 +02:00
|
|
|
/* reply serial */
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_set_u32(c, msg->serial));
|
2022-12-21 21:38:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*header_fields_length = c->byte_cursor - header_fields_start;
|
|
|
|
|
|
|
|
// header ends on an 8 byte alignment
|
2022-12-25 20:54:10 +02:00
|
|
|
TRYPTR(wire_write_align(c, 8));
|
2022-12-21 21:38:48 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2022-12-23 23:58:18 +02:00
|
|
|
|
2023-01-21 05:43:00 +02:00
|
|
|
int wire_compose_unicast_reply(WireCtx *msg_c, WireMsg *msg, char *sender_unique_name, struct iovec bufs[2], WireCtx *header_ctx)
|
2022-12-23 23:58:18 +02:00
|
|
|
{
|
2023-01-21 05:43:00 +02:00
|
|
|
TRYPTR(wire_set_u8(header_ctx, msg->endianness)); /* endianness */
|
|
|
|
TRYPTR(wire_set_u8(header_ctx, msg->type)); /* type */
|
|
|
|
TRYPTR(wire_set_u8(header_ctx, msg->flags)); /* flags */
|
|
|
|
TRYPTR(wire_set_u8(header_ctx, DBUS_PROTOCOL_VERSION)); /* protocol_version */
|
|
|
|
TRYPTR(wire_set_u32(header_ctx, msg->body_length)); /* body length */
|
|
|
|
TRYPTR(wire_set_u32(header_ctx, msg->serial)); /* serial */
|
|
|
|
uint32_t *header_fields_length = TRYPTR(wire_set_u32(header_ctx, 0)); /* header_fields_length */
|
2022-12-23 23:58:18 +02:00
|
|
|
|
2023-01-21 05:43:00 +02:00
|
|
|
TRYPTR(wire_write_align(header_ctx, 8));
|
2023-01-16 17:44:45 +02:00
|
|
|
|
2023-01-21 05:43:00 +02:00
|
|
|
uint32_t header_fields_start = header_ctx->byte_cursor;
|
2023-01-16 17:44:45 +02:00
|
|
|
|
2023-01-21 05:43:00 +02:00
|
|
|
TRYPTR(wire_set_u8(header_ctx, DBUS_HEADER_FIELD_SENDER));
|
|
|
|
TRYPTR(wire_set_signature_single_char(header_ctx, 's'));
|
|
|
|
TRYPTR(wire_set_string(header_ctx, sender_unique_name));
|
|
|
|
TRYPTR(wire_write_align(header_ctx, 8));
|
2023-01-16 17:44:45 +02:00
|
|
|
|
2023-01-21 05:43:00 +02:00
|
|
|
*header_fields_length = header_ctx->byte_cursor - header_fields_start + msg->header_fields_length;
|
2023-01-16 17:44:45 +02:00
|
|
|
|
2023-01-21 05:43:00 +02:00
|
|
|
if (msg_c->byte_cursor + msg->body_length >= msg_c->data_len) {
|
2022-12-23 23:58:18 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2023-01-21 05:43:00 +02:00
|
|
|
bufs[0] = (struct iovec){ header_ctx->data, header_ctx->byte_cursor };
|
|
|
|
bufs[1] = (struct iovec){ msg_c->data + msg->header_length, msg_c->byte_cursor + msg->body_length - msg->header_length };
|
|
|
|
|
|
|
|
msg_c->byte_cursor += msg->body_length;
|
2022-12-23 23:58:18 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2022-12-29 20:10:36 +02:00
|
|
|
|
2023-01-19 02:46:49 +02:00
|
|
|
int wire_collect_strings(WireCtx *c, WireMsg *msg, WireMsgBodyString *strings, int strings_count)
|
2022-12-29 20:10:36 +02:00
|
|
|
{
|
|
|
|
if (!msg->fields[DBUS_HEADER_FIELD_SIGNATURE].present) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *sig = msg->fields[DBUS_HEADER_FIELD_SIGNATURE].t.str;
|
|
|
|
int stri = 0;
|
|
|
|
int sigi = 0;
|
|
|
|
uint32_t body_cursor = c->byte_cursor;
|
|
|
|
|
|
|
|
while (*sig) {
|
|
|
|
switch (*sig) {
|
|
|
|
case 'y': {
|
|
|
|
TRYPTR(wire_get_u8(c));
|
|
|
|
} break;
|
|
|
|
case 'b': {
|
|
|
|
TRYPTR(wire_get_u32(c));
|
|
|
|
} break;
|
|
|
|
case 'n': {
|
|
|
|
TRYPTR(wire_get_i16(c));
|
|
|
|
} break;
|
|
|
|
case 'q': {
|
|
|
|
TRYPTR(wire_get_u16(c));
|
|
|
|
} break;
|
|
|
|
case 'i': {
|
|
|
|
TRYPTR(wire_get_i32(c));
|
|
|
|
} break;
|
|
|
|
case 'u': {
|
|
|
|
TRYPTR(wire_get_u32(c));
|
|
|
|
} break;
|
|
|
|
case 'o': /* through */
|
|
|
|
case 's': {
|
|
|
|
char *s = TRYPTR(wire_get_string(c));
|
|
|
|
if (sigi >= strings_count) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
strings[sigi].index = sigi;
|
|
|
|
strings[sigi].str = s;
|
|
|
|
} break;
|
|
|
|
case 'g': {
|
|
|
|
char *s = TRYPTR(wire_get_signature(c));
|
|
|
|
if (sigi >= strings_count) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
strings[sigi].index = sigi;
|
|
|
|
strings[sigi].str = s;
|
|
|
|
} break;
|
|
|
|
case 'a': {
|
|
|
|
uint32_t array_size = *(uint32_t*)TRYPTR(wire_get_u32(c));
|
|
|
|
uint32_t new_cursor = c->byte_cursor + array_size;
|
|
|
|
if (new_cursor >= c->data_len) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
c->byte_cursor = new_cursor;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
default: {
|
2023-01-16 19:47:40 +02:00
|
|
|
goto end_nonfatal;
|
2022-12-29 20:10:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sigi++;
|
|
|
|
sig++;
|
|
|
|
}
|
|
|
|
|
2023-01-16 19:47:40 +02:00
|
|
|
end_nonfatal:
|
|
|
|
|
2022-12-29 20:10:36 +02:00
|
|
|
c->byte_cursor = body_cursor;
|
|
|
|
|
|
|
|
return stri;
|
|
|
|
}
|