jitterbug/wire.h

151 lines
5.5 KiB
C
Raw Normal View History

#ifndef _JITTERBUG__WIRE_H
#define _JITTERBUG__WIRE_H
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#define DBUS_PROTOCOL_VERSION 1
/* The caller is now the primary owner of the name, replacing any previous owner.
Either the name had no owner before, or the caller specified DBUS_NAME_FLAG_REPLACE_EXISTING
and the current owner specified DBUS_NAME_FLAG_ALLOW_REPLACEMENT. */
#define DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1
/* The name already had an owner, DBUS_NAME_FLAG_DO_NOT_QUEUE was not specified,
and either the current owner did not specify DBUS_NAME_FLAG_ALLOW_REPLACEMENT or
the requesting application did not specify DBUS_NAME_FLAG_REPLACE_EXISTING. */
#define DBUS_REQUEST_NAME_REPLY_IN_QUEUE 2
/* The name already has an owner, DBUS_NAME_FLAG_DO_NOT_QUEUE was specified,
and either DBUS_NAME_FLAG_ALLOW_REPLACEMENT was not specified by the current owner,
or DBUS_NAME_FLAG_REPLACE_EXISTING was not specified by the requesting application. */
#define DBUS_REQUEST_NAME_REPLY_EXISTS 3
/* The application trying to request ownership of a name is already the owner of it. */
#define DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4
enum {
DBUS_HEADER_FIELD_INVALID,
DBUS_HEADER_FIELD_PATH,
DBUS_HEADER_FIELD_INTERFACE,
DBUS_HEADER_FIELD_MEMBER,
DBUS_HEADER_FIELD_ERROR_NAME,
DBUS_HEADER_FIELD_REPLY_SERIAL,
DBUS_HEADER_FIELD_DESTINATION,
DBUS_HEADER_FIELD_SENDER,
DBUS_HEADER_FIELD_SIGNATURE,
DBUS_HEADER_FIELD_UNIX_FDS,
};
enum {
DBUS_MESSAGE_INVALID,
DBUS_MESSAGE_METHOD_CALL,
DBUS_MESSAGE_METHOD_RETURN,
DBUS_MESSAGE_ERROR,
DBUS_MESSAGE_SIGNAL,
};
typedef struct wire_context {
uint32_t byte_cursor;
uint8_t *data;
size_t data_len;
} wire_context_t;
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
typedef struct wire_message_field {
2022-12-23 23:58:18 +02:00
bool present;
union {
char *str;
2022-12-23 23:58:18 +02:00
uint32_t u32;
} t;
} wire_message_field_t;
#define WIRE_MESSAGE_MAX_HEADER_FIELDS 9
typedef struct wire_message {
uint8_t endianness, type, flags, protocol_version;
uint32_t body_length, serial, header_fields_length;
uint8_t header_fields_count;
wire_message_field_t fields[WIRE_MESSAGE_MAX_HEADER_FIELDS]; /* cannot have more than 9 header fields */
} wire_message_t;
#define _WIRE_DECL_BYTE_TYPE(M_mnemonic, M_type) \
M_type *wire_get_##M_mnemonic(wire_context_t *c); \
M_type *wire_set_##M_mnemonic(wire_context_t *c, M_type val); \
#define _WIRE_DECL_TYPE(M_mnemonic, M_type, M_alignment) \
M_type *wire_get_##M_mnemonic(wire_context_t *c); \
M_type *wire_set_##M_mnemonic(wire_context_t *c, M_type val); \
#define _WIRE_DEF_BYTE_TYPE(M_mnemonic, M_type) \
M_type *wire_get_##M_mnemonic(wire_context_t *c) { \
uint32_t new_cursor = c->byte_cursor + 1; \
if (new_cursor >= c->data_len) return NULL; \
M_type *value = (M_type*)&c->data[c->byte_cursor]; \
c->byte_cursor = new_cursor; \
return value; \
} \
M_type *wire_set_##M_mnemonic(wire_context_t *c, M_type val) { \
uint32_t new_cursor = c->byte_cursor + 1; \
if (new_cursor >= c->data_len) return NULL; \
M_type *dest = (M_type*)&c->data[c->byte_cursor]; \
*dest = val; \
c->byte_cursor = new_cursor; \
return dest; \
} \
#define _WIRE_DEF_TYPE(M_mnemonic, M_type, M_alignment) \
M_type *wire_get_##M_mnemonic(wire_context_t *c) { \
if (!wire_align(c, M_alignment)) return NULL; \
uint32_t new_cursor = c->byte_cursor + sizeof(M_type); \
if (new_cursor >= c->data_len) return NULL; \
M_type *value = (M_type*)&c->data[c->byte_cursor]; \
c->byte_cursor = new_cursor; \
return value; \
} \
M_type *wire_set_##M_mnemonic(wire_context_t *c, M_type val) { \
if (!wire_write_align(c, M_alignment)) return NULL; \
uint32_t new_cursor = c->byte_cursor + sizeof(M_type); \
if (new_cursor >= c->data_len) return NULL; \
M_type *dest = (M_type*)&c->data[c->byte_cursor]; \
*dest = val; \
c->byte_cursor = new_cursor; \
return dest; \
} \
bool wire_align(wire_context_t *c, uint32_t alignment);
bool wire_write_align(wire_context_t *c, uint32_t alignment);
// SPEC: https://dbus.freedesktop.org/doc/dbus-specification.html#id-1.4.6
_WIRE_DECL_BYTE_TYPE(i8, int8_t);
_WIRE_DECL_BYTE_TYPE(u8, uint8_t);
_WIRE_DECL_TYPE(i16, int16_t, 2);
_WIRE_DECL_TYPE(u16, uint16_t, 2);
_WIRE_DECL_TYPE(i32, int32_t, 4);
_WIRE_DECL_TYPE(u32, uint32_t, 4);
_WIRE_DECL_TYPE(boolean, uint32_t, 4);
2022-12-26 21:13:09 +02:00
char *wire_get_string_impl(wire_context_t *c, bool as_signature);
char *wire_set_string_impl(wire_context_t *c, const char *str, bool as_signature);
int wire_parse_message(wire_context_t *c, wire_message_t *msg);
int wire_compose_reply(wire_context_t *c, wire_message_t *msg, const char *signature, uint32_t **out_body_length);
int wire_compose_error(wire_context_t *c, wire_message_t *msg, const char *error_name);
2022-12-23 23:58:18 +02:00
int wire_compose_unicast_reply(wire_context_t *c, wire_context_t *msg_c, wire_message_t *msg, char *sender_unique_name);
2022-12-26 21:13:09 +02:00
static inline char *wire_get_signature(wire_context_t *c) {
return wire_get_string_impl(c, true);
}
static inline char *wire_set_signature(wire_context_t *c, const char *str) {
return wire_set_string_impl(c, str, true);
}
static inline char *wire_get_string(wire_context_t *c) {
return wire_get_string_impl(c, false);
}
static inline char *wire_set_string(wire_context_t *c, const char *str) {
return wire_set_string_impl(c, str, false);
}
#endif // _JITTERBUG__WIRE_H