diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/client.c | 6 | ||||
-rw-r--r-- | lib/client.h | 7 | ||||
-rw-r--r-- | lib/data.h | 209 | ||||
-rw-r--r-- | lib/meson.build | 3 | ||||
-rw-r--r-- | lib/protocol.c | 161 | ||||
-rw-r--r-- | lib/protocol.h | 19 | ||||
-rw-r--r-- | lib/server.c | 5 | ||||
-rw-r--r-- | lib/server.h | 7 |
8 files changed, 287 insertions, 130 deletions
diff --git a/lib/client.c b/lib/client.c index 4186ce4..f1c4da1 100644 --- a/lib/client.c +++ b/lib/client.c @@ -40,7 +40,7 @@ void icipc_client_free(struct icipc_client *self) { bool icipc_client_send_request( struct icipc_client *self, const char *name, - const struct spa_pod *args, + const struct icipc_data *args, icipc_sender_reply_func_t reply, void *data) { struct icipc_sender *base = icipc_client_to_sender(self); @@ -55,7 +55,7 @@ bool icipc_client_send_request( return icipc_sender_send(base, buffer, size, reply, data); } -const struct spa_pod *icipc_client_send_request_finish( +const struct icipc_data *icipc_client_send_request_finish( struct icipc_sender *self, const uint8_t * buffer, size_t size, @@ -68,7 +68,7 @@ const struct spa_pod *icipc_client_send_request_finish( /* ok */ if (icipc_protocol_is_reply_ok(buffer, size)) { - const struct spa_pod *value = NULL; + const struct icipc_data *value = NULL; if (icipc_protocol_parse_reply_ok(buffer, size, &value)) return value; } diff --git a/lib/client.h b/lib/client.h index 597552c..226d87a 100644 --- a/lib/client.h +++ b/lib/client.h @@ -9,8 +9,6 @@ #ifndef __ICIPC_CLIENT_H__ #define __ICIPC_CLIENT_H__ -#include <spa/pod/pod.h> - #include <stddef.h> #include "sender.h" @@ -23,6 +21,7 @@ extern "C" { #define icipc_client_to_sender(self) ((struct icipc_sender *)(self)) struct icipc_client; +struct icipc_data; ICIPC_API struct icipc_client *icipc_client_new(const char *path, bool connect); @@ -34,14 +33,14 @@ ICIPC_API bool icipc_client_send_request( struct icipc_client *self, const char *name, - const struct spa_pod *args, + const struct icipc_data *args, icipc_sender_reply_func_t reply, void *data); /* for reply handlers only */ ICIPC_API -const struct spa_pod *icipc_client_send_request_finish( +const struct icipc_data *icipc_client_send_request_finish( struct icipc_sender *self, const uint8_t *buffer, size_t size, diff --git a/lib/data.h b/lib/data.h new file mode 100644 index 0000000..7072ba9 --- /dev/null +++ b/lib/data.h @@ -0,0 +1,209 @@ +/* PipeWire AGL Cluster IPC + * + * Copyright © 2018 Wim Taymans + * Copyright © 2021 Collabora Ltd. + * @author George Kiagiadakis <george.kiagiadakis@collabora.com> + * + * SPDX-License-Identifier: MIT + */ + +#include <assert.h> +#include <stddef.h> +#include <stdint.h> +#include <stdbool.h> +#include <string.h> + +/* Trimmed down version of struct spa_pod from PipeWire's Simple Plugin API + * This aims to be compatible with spa_pod, so you can cast icipc_data + * to spa_pod and still be able to use it */ + +struct icipc_data { + uint32_t size; /* size of the body */ + uint32_t type; /* type of the body */ + /* type-specific body follows */ +}; + +#define ICIPC_DATA_BODY_SIZE(d) (((const struct icipc_data*)(d))->size) +#define ICIPC_DATA_TYPE(d) (((const struct icipc_data*)(d))->type) +#define ICIPC_DATA_SIZE(d) (sizeof(struct icipc_data) + ICIPC_DATA_BODY_SIZE(d)) +#define ICIPC_DATA_BODY(d) ((void*)(((uint8_t *) d) + sizeof(struct icipc_data))) +#define ICIPC_DATA_BODY_CONST(d) ((const void*)(((const uint8_t *) d) + sizeof(struct icipc_data))) + +enum { + DATA_TYPE_NONE = 1, /* SPA_TYPE_None */ + DATA_TYPE_ID = 3, /* SPA_TYPE_Id */ + DATA_TYPE_INT = 4, /* SPA_TYPE_Int */ + DATA_TYPE_STRING = 8, /* SPA_TYPE_String */ + DATA_TYPE_STRUCT = 14, /* SPA_TYPE_Struct */ +}; + +#define PTR_ALIGNMENT 8 +#define ROUND_UP_TO_ALIGN(num) (((num) + (PTR_ALIGNMENT - 1)) & ~((PTR_ALIGNMENT) - 1)) +#define PTR_IS_ALIGNED(p) (((intptr_t)(p) & (PTR_ALIGNMENT-1)) == 0) + +typedef struct DataBuilder { + union { + uint8_t *buffer; + struct icipc_data *data; + }; + union { + uint8_t *ptr; + struct icipc_data *ptr_as_data; + }; + size_t buf_size; +} DataBuilder; + +typedef struct DataParser { + union { + const uint8_t *buffer; + const struct icipc_data *data; + }; + union { + const uint8_t *ptr; + const struct icipc_data *ptr_as_data; + }; + size_t buf_size; +} DataParser; + +static inline void data_builder_init( + DataBuilder *b, + uint8_t *buffer, + size_t size) { + assert(size >= sizeof(struct icipc_data)); + memset(buffer, 0, size); + b->buffer = buffer; + b->buf_size = size; + b->data->type = DATA_TYPE_STRUCT; + b->ptr = ICIPC_DATA_BODY(b->data); + assert(PTR_IS_ALIGNED(b->ptr)); +} + +static inline size_t data_type_id_calc_size(void) { + return sizeof(struct icipc_data) + ROUND_UP_TO_ALIGN(sizeof(uint32_t)); +} + +static inline void data_builder_push_id(DataBuilder *b, uint32_t id) { + + const size_t body_size = ROUND_UP_TO_ALIGN(sizeof(uint32_t)); + const size_t additional_size = sizeof(struct icipc_data) + body_size; + assert(b->buf_size >= ICIPC_DATA_SIZE(b->data) + additional_size); + + b->ptr_as_data->size = body_size; + b->ptr_as_data->type = DATA_TYPE_ID; + *((uint32_t *) ICIPC_DATA_BODY(b->ptr)) = id; + + b->data->size += additional_size; + b->ptr += additional_size; + assert(PTR_IS_ALIGNED(b->ptr)); +} + +static inline size_t data_type_string_calc_size(const char *str) { + size_t str_size = strlen(str) + 1; + return sizeof(struct icipc_data) + ROUND_UP_TO_ALIGN(str_size); +} + +static inline void data_builder_push_string(DataBuilder *b, const char *str) { + + size_t str_size = strlen(str) + 1; + const size_t body_size = ROUND_UP_TO_ALIGN(str_size); + const size_t additional_size = sizeof(struct icipc_data) + body_size; + assert(b->buf_size >= ICIPC_DATA_SIZE(b->data) + additional_size); + + b->ptr_as_data->size = body_size; + b->ptr_as_data->type = DATA_TYPE_STRING; + strncpy((char *) ICIPC_DATA_BODY(b->ptr), str, str_size); + + b->data->size += additional_size; + b->ptr += additional_size; + assert(PTR_IS_ALIGNED(b->ptr)); +} + +static inline size_t data_type_raw_calc_size(const struct icipc_data *raw) { + return sizeof(struct icipc_data) + + ROUND_UP_TO_ALIGN(ICIPC_DATA_BODY_SIZE(raw)); +} + +static inline void data_builder_push_raw( + DataBuilder *b, + const struct icipc_data *raw) { + + const size_t body_size = ROUND_UP_TO_ALIGN(ICIPC_DATA_BODY_SIZE(raw)); + const size_t additional_size = sizeof(struct icipc_data) + body_size; + assert(b->buf_size >= ICIPC_DATA_SIZE(b->data) + additional_size); + + b->ptr_as_data->size = body_size; + b->ptr_as_data->type = raw->type; + memcpy(ICIPC_DATA_BODY(b->ptr), + ICIPC_DATA_BODY(raw), + ICIPC_DATA_BODY_SIZE(raw)); + + b->data->size += additional_size; + b->ptr += additional_size; + assert(PTR_IS_ALIGNED(b->ptr)); +} + +static inline bool data_parser_init( + DataParser *p, + const uint8_t *buffer, + size_t size) { + assert(size >= sizeof(struct icipc_data)); + p->buffer = buffer; + p->buf_size = size; + + if (p->data->type != DATA_TYPE_STRUCT || + ICIPC_DATA_SIZE(p->data) > size) + return false; + + p->ptr = ICIPC_DATA_BODY(p->data); + assert(PTR_IS_ALIGNED(p->ptr)); + return true; +} + +static inline bool data_parser_get_id(DataParser *p, uint32_t *id) { + + if (p->ptr_as_data->type != DATA_TYPE_ID || + ICIPC_DATA_BODY_SIZE(p->ptr) != ROUND_UP_TO_ALIGN(sizeof(uint32_t))) + return false; + + *id = *((const uint32_t *) ICIPC_DATA_BODY_CONST(p->ptr)); + + p->ptr += ICIPC_DATA_SIZE(p->ptr); + assert(PTR_IS_ALIGNED(p->ptr)); + return true; +} + +static inline bool data_parser_get_string(DataParser *p, const char **str) { + + if (p->ptr_as_data->type != DATA_TYPE_STRING || + ICIPC_DATA_BODY_SIZE(p->ptr) == 0 || + ICIPC_DATA_BODY_SIZE(p->ptr) != + ROUND_UP_TO_ALIGN(ICIPC_DATA_BODY_SIZE(p->ptr)) || + (p->ptr - p->buffer) + ICIPC_DATA_SIZE(p->ptr) > p->buf_size) + return false; + + *str = (const char *) ICIPC_DATA_BODY_CONST(p->ptr); + + /* check that the string has a terminating null character */ + if (strnlen(*str, ICIPC_DATA_BODY_SIZE(p->ptr)) == + ICIPC_DATA_BODY_SIZE(p->ptr)) + return false; + + p->ptr += ICIPC_DATA_SIZE(p->ptr); + assert(PTR_IS_ALIGNED(p->ptr)); + return true; +} + +static inline bool data_parser_get_raw( + DataParser *p, + const struct icipc_data **raw) { + if (ICIPC_DATA_BODY_SIZE(p->ptr) != + ROUND_UP_TO_ALIGN(ICIPC_DATA_BODY_SIZE(p->ptr)) || + (p->ptr - p->buffer) + ICIPC_DATA_SIZE(p->ptr) > p->buf_size) + return false; + + *raw = p->ptr_as_data; + + p->ptr += ICIPC_DATA_SIZE(p->ptr); + assert(PTR_IS_ALIGNED(p->ptr)); + return true; +} diff --git a/lib/meson.build b/lib/meson.build index dc19c1f..7b8a21b 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -33,7 +33,7 @@ icipc_lib = library('icipc-' + icipc_api_version, '-DG_LOG_DOMAIN="icipc"', ], install: true, - dependencies : [threads_dep, spa_dep], + dependencies : [threads_dep], soversion: icipc_so_version, version: meson.project_version(), ) @@ -41,7 +41,6 @@ icipc_lib = library('icipc-' + icipc_api_version, icipc_dep = declare_dependency( link_with: icipc_lib, include_directories: include_directories('.'), - dependencies: [spa_dep], ) pkgconfig.generate(icipc_lib, diff --git a/lib/protocol.c b/lib/protocol.c index 35a9485..ac53d2b 100644 --- a/lib/protocol.c +++ b/lib/protocol.c @@ -6,35 +6,22 @@ * SPDX-License-Identifier: MIT */ -#include <assert.h> - -#include <spa/pod/builder.h> -#include <spa/pod/parser.h> - +#include "data.h" #include "protocol.h" -#define SIZE_PADDING 128 - enum { REPLY_CODE_ERROR = 0, REPLY_CODE_OK, }; -static bool is_reply(const uint8_t *buffer, size_t size, int code) { - const struct spa_pod *pod = (const struct spa_pod *)buffer; - struct spa_pod_parser p; - struct spa_pod_frame f; - int parsed_code = 0; +static bool is_reply(const uint8_t *buffer, size_t size, uint32_t code) { + DataParser p; + uint32_t parsed_code = 0; - /* check if struct */ - if (!spa_pod_is_struct(pod)) + if (!data_parser_init(&p, buffer, size) || + !data_parser_get_id(&p, &parsed_code)) return false; - /* parse */ - spa_pod_parser_pod(&p, pod); - spa_pod_parser_push_struct(&p, &f); - spa_pod_parser_get_int(&p, &parsed_code); - return parsed_code == code; } @@ -42,56 +29,40 @@ static bool is_reply(const uint8_t *buffer, size_t size, int code) { size_t icipc_protocol_calculate_request_size( const char *name, - const struct spa_pod *args) { + const struct icipc_data *args) { assert (name); - return strlen(name) + (args ? SPA_POD_SIZE(args) : 8) + SIZE_PADDING; + return sizeof(struct icipc_data) + + data_type_string_calc_size(name) + + (args ? data_type_raw_calc_size(args) : sizeof(struct icipc_data)); } void icipc_protocol_build_request( uint8_t *buffer, size_t size, const char *name, - const struct spa_pod *args) { - const struct spa_pod none = SPA_POD_INIT_None(); - struct spa_pod_builder b; - struct spa_pod_frame f; - - memset(buffer, 0, size); - + const struct icipc_data *args) { + DataBuilder b; + const struct icipc_data none = { 0, DATA_TYPE_NONE }; if (args == NULL) args = &none; - spa_pod_builder_init(&b, buffer, size); - spa_pod_builder_push_struct(&b, &f); - spa_pod_builder_string(&b, name); - spa_pod_builder_primitive (&b, args); - spa_pod_builder_pop(&b, &f); + data_builder_init(&b, buffer, size); + data_builder_push_string(&b, name); + data_builder_push_raw(&b, args); } bool icipc_protocol_parse_request( const uint8_t *buffer, size_t size, const char **name, - const struct spa_pod **args) { - const struct spa_pod *pod = (const struct spa_pod *)buffer; - struct spa_pod_parser p; - struct spa_pod_frame f; + const struct icipc_data **args) { + DataParser p; const char *parsed_name = NULL; - struct spa_pod *parsed_args = NULL; + const struct icipc_data *parsed_args = NULL; - /* check if struct */ - if (!spa_pod_is_struct(pod)) - return false; - - /* parse */ - spa_pod_parser_pod(&p, pod); - spa_pod_parser_push_struct(&p, &f); - spa_pod_parser_get_string(&p, &parsed_name); - spa_pod_parser_get_pod(&p, &parsed_args); - spa_pod_parser_pop(&p, &f); - - /* check name and args */ - if (name == NULL || args == NULL) + if (!data_parser_init(&p, buffer, size) || + !data_parser_get_string(&p, &parsed_name) || + !data_parser_get_raw(&p, &parsed_args)) return false; if (name != NULL) @@ -101,49 +72,41 @@ bool icipc_protocol_parse_request( return true; } -size_t icipc_protocol_calculate_reply_ok_size(const struct spa_pod *value) { - return (value ? SPA_POD_SIZE(value) : 8) + SIZE_PADDING; +size_t icipc_protocol_calculate_reply_ok_size(const struct icipc_data *value) { + return sizeof(struct icipc_data) + + data_type_id_calc_size() + + (value ? data_type_raw_calc_size(value) : sizeof(struct icipc_data)); } size_t icipc_protocol_calculate_reply_error_size(const char *msg) { assert (msg); - return strlen(msg) + SIZE_PADDING; + return sizeof(struct icipc_data) + + data_type_id_calc_size() + + data_type_string_calc_size(msg); } void icipc_protocol_build_reply_ok( uint8_t *buffer, size_t size, - const struct spa_pod *value) { - const struct spa_pod none = SPA_POD_INIT_None(); - struct spa_pod_builder b; - struct spa_pod_frame f; - - memset(buffer, 0, size); - + const struct icipc_data *value) { + DataBuilder b; + const struct icipc_data none = { 0, DATA_TYPE_NONE }; if (value == NULL) value = &none; - spa_pod_builder_init(&b, buffer, size); - spa_pod_builder_push_struct(&b, &f); - spa_pod_builder_int(&b, REPLY_CODE_OK); - spa_pod_builder_primitive(&b, value); - spa_pod_builder_pop(&b, &f); + data_builder_init(&b, buffer, size); + data_builder_push_id(&b, REPLY_CODE_OK); + data_builder_push_raw(&b, value); } void icipc_protocol_build_reply_error( uint8_t *buffer, size_t size, const char *msg) { - struct spa_pod_builder b; - struct spa_pod_frame f; - - memset(buffer, 0, size); - - spa_pod_builder_init(&b, buffer, size); - spa_pod_builder_push_struct(&b, &f); - spa_pod_builder_int(&b, REPLY_CODE_ERROR); - spa_pod_builder_string (&b, msg); - spa_pod_builder_pop(&b, &f); + DataBuilder b; + data_builder_init(&b, buffer, size); + data_builder_push_id(&b, REPLY_CODE_ERROR); + data_builder_push_string(&b, msg); } bool icipc_protocol_is_reply_ok(const uint8_t *buffer, size_t size) { @@ -154,53 +117,37 @@ bool icipc_protocol_is_reply_error(const uint8_t *buffer, size_t size) { return is_reply (buffer, size, REPLY_CODE_ERROR); } -bool icipc_protocol_parse_reply_ok ( +bool icipc_protocol_parse_reply_ok( const uint8_t *buffer, size_t size, - const struct spa_pod **value) { - const struct spa_pod *pod = (const struct spa_pod *)buffer; - struct spa_pod_parser p; - struct spa_pod_frame f; - int parsed_code = 0; - struct spa_pod *parsed_value = NULL; - - /* check if struct */ - if (!spa_pod_is_struct(pod)) + const struct icipc_data **value) { + DataParser p; + uint32_t parsed_code = 0; + const struct icipc_data *parsed_value = NULL; + + if (!data_parser_init(&p, buffer, size) || + !data_parser_get_id(&p, &parsed_code) || + !data_parser_get_raw(&p, &parsed_value)) return false; - /* parse */ - spa_pod_parser_pod(&p, pod); - spa_pod_parser_push_struct(&p, &f); - spa_pod_parser_get_int(&p, &parsed_code); - spa_pod_parser_get_pod(&p, &parsed_value); - spa_pod_parser_pop(&p, &f); - if (value != NULL) *value = parsed_value; return true; } -bool icipc_protocol_parse_reply_error ( +bool icipc_protocol_parse_reply_error( const uint8_t *buffer, size_t size, const char **msg) { - const struct spa_pod *pod = (const struct spa_pod *)buffer; - struct spa_pod_parser p; - struct spa_pod_frame f; - int parsed_code = 0; + DataParser p; + uint32_t parsed_code = 0; const char *parsed_msg = NULL; - /* check if struct */ - if (!spa_pod_is_struct(pod)) + if (!data_parser_init(&p, buffer, size) || + !data_parser_get_id(&p, &parsed_code) || + !data_parser_get_string(&p, &parsed_msg)) return false; - /* parse */ - spa_pod_parser_pod(&p, pod); - spa_pod_parser_push_struct(&p, &f); - spa_pod_parser_get_int(&p, &parsed_code); - spa_pod_parser_get_string(&p, &parsed_msg); - spa_pod_parser_pop(&p, &f); - if (msg != NULL) *msg = parsed_msg; return true; diff --git a/lib/protocol.h b/lib/protocol.h index 34a92a0..821edf2 100644 --- a/lib/protocol.h +++ b/lib/protocol.h @@ -9,39 +9,42 @@ #ifndef __ICIPC_PROTOCOL_H__ #define __ICIPC_PROTOCOL_H__ -#include <spa/pod/pod.h> - +#include <stddef.h> +#include <stdint.h> +#include <stdbool.h> #include "defs.h" #ifdef __cplusplus extern "C" { #endif +struct icipc_data; + /* request */ ICIPC_API size_t icipc_protocol_calculate_request_size( const char *name, - const struct spa_pod *args); + const struct icipc_data *args); ICIPC_API void icipc_protocol_build_request( uint8_t *buffer, size_t size, const char *name, - const struct spa_pod *args); + const struct icipc_data *args); ICIPC_API bool icipc_protocol_parse_request( const uint8_t *buffer, size_t size, const char **name, - const struct spa_pod **args); + const struct icipc_data **args); /* reply */ ICIPC_API -size_t icipc_protocol_calculate_reply_ok_size(const struct spa_pod *value); +size_t icipc_protocol_calculate_reply_ok_size(const struct icipc_data *value); ICIPC_API size_t icipc_protocol_calculate_reply_error_size(const char *msg); @@ -50,7 +53,7 @@ ICIPC_API void icipc_protocol_build_reply_ok( uint8_t *buffer, size_t size, - const struct spa_pod *value); + const struct icipc_data *value); ICIPC_API void icipc_protocol_build_reply_error( @@ -68,7 +71,7 @@ ICIPC_API bool icipc_protocol_parse_reply_ok( const uint8_t *buffer, size_t size, - const struct spa_pod **value); + const struct icipc_data **value); ICIPC_API bool icipc_protocol_parse_reply_error( diff --git a/lib/server.c b/lib/server.c index 747b829..6229ecd 100644 --- a/lib/server.c +++ b/lib/server.c @@ -7,6 +7,7 @@ */ #include <pthread.h> +#include <string.h> #include "private.h" #include "protocol.h" @@ -60,7 +61,7 @@ static bool handle_message( void *data) { ServerPriv *priv = icipc_receiver_get_user_data(base); const char *name = NULL; - const struct spa_pod *args = NULL; + const struct icipc_data *args = NULL; icipc_log_info("server: message from client %d received", sender_fd); @@ -231,7 +232,7 @@ void icipc_server_clear_request_handler( bool icipc_server_reply_ok( struct icipc_server *self, int client_fd, - const struct spa_pod *value) { + const struct icipc_data *value) { const size_t s = icipc_protocol_calculate_reply_ok_size(value); uint8_t b[s]; icipc_protocol_build_reply_ok(b, s, value); diff --git a/lib/server.h b/lib/server.h index 6345035..cacb095 100644 --- a/lib/server.h +++ b/lib/server.h @@ -9,8 +9,6 @@ #ifndef __ICIPC_SERVER_H__ #define __ICIPC_SERVER_H__ -#include <spa/pod/pod.h> - #include "defs.h" #include "receiver.h" @@ -21,6 +19,7 @@ extern "C" { #define icipc_server_to_receiver(self) ((struct icipc_receiver *)(self)) struct icipc_server; +struct icipc_data; typedef void (*icipc_server_client_handler_func_t)( struct icipc_server *self, @@ -32,7 +31,7 @@ typedef bool (*icipc_server_request_handler_func_t)( struct icipc_server *self, int client_fd, const char *name, - const struct spa_pod *args, + const struct icipc_data *args, void *data); ICIPC_API @@ -68,7 +67,7 @@ ICIPC_API bool icipc_server_reply_ok( struct icipc_server *self, int client_fd, - const struct spa_pod *value); + const struct icipc_data *value); ICIPC_API bool icipc_server_reply_error( |