From d61cc219f6bd3c4ffc96239893a8ded9b5a83b30 Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Fri, 9 Jul 2021 13:22:35 +0300 Subject: lib: remove dependency on spa_pod and spa in general Replace spa_pod with a custom icipc_data structure, which is based on spa_pod and it's fully compatible with it Signed-off-by: George Kiagiadakis --- lib/client.c | 6 +- lib/client.h | 7 +- lib/data.h | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/meson.build | 3 +- lib/protocol.c | 161 +++++++++++++------------------------- lib/protocol.h | 19 +++-- lib/server.c | 5 +- lib/server.h | 7 +- meson.build | 1 - src/icipc-client.c | 35 +++------ tests/client-server.c | 45 +++++++---- tests/protocol.c | 58 +++++++++----- 12 files changed, 368 insertions(+), 188 deletions(-) create mode 100644 lib/data.h 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 - #include #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 + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include +#include + +/* 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 - -#include -#include - +#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 - +#include +#include +#include #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 +#include #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 - #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( diff --git a/meson.build b/meson.build index 3aac10f..246196b 100644 --- a/meson.build +++ b/meson.build @@ -9,7 +9,6 @@ project('icipc', ['c'], ) threads_dep = dependency('threads', required: true) -spa_dep = dependency('libspa-0.2', version: '>= 0.2', required: true) pkgconfig = import('pkgconfig') cc = meson.get_compiler('c') diff --git a/src/icipc-client.c b/src/icipc-client.c index c1d2de7..9f47ba4 100644 --- a/src/icipc-client.c +++ b/src/icipc-client.c @@ -6,10 +6,10 @@ * SPDX-License-Identifier: MIT */ +#include +#include #include #include - -#include #include typedef struct ClientData { @@ -28,9 +28,9 @@ static void reply_handler( const char *error = NULL; if (buffer) { - const struct spa_pod *pod = + const struct icipc_data *data = icipc_client_send_request_finish(self, buffer, size, &error); - if (!pod) + if (!data) printf("error: %s\n", error ? error : "unknown"); else printf("success!\n"); @@ -68,36 +68,21 @@ int main(int argc, char *argv[]) { if (strncmp(str, "help", 4) == 0) { printf("help\tprints this message\n"); printf("quit\texits the client\n"); - printf("send\tsends a request, usage: send [args]\n"); + printf("send\tsends a request, usage: send \n"); } else if (strncmp(str, "quit", 4) == 0) { printf("exiting...\n"); break; } else if (strncmp(str, "send", 4) == 0) { - char request_name[128]; - char request_args[1024]; + char request_name[1024]; int n = - sscanf(str, "send %s %s", request_name, - request_args); + sscanf(str, "send %s", request_name); if (n <= 0) continue; /* send request */ - if (n >= 2) { - /* TODO: for now we always create a string pod for args */ - struct { - struct spa_pod_string pod; - char str[1024]; - } args; - args.pod = SPA_POD_INIT_String(1024); - strncpy(args.str, request_args, 1024); - icipc_client_send_request(data.c, request_name, - (const struct spa_pod *)&args, - reply_handler, &data); - } else { - icipc_client_send_request(data.c, request_name, - NULL, reply_handler, - &data); - } + icipc_client_send_request(data.c, request_name, + NULL, reply_handler, + &data); /* wait for reply */ pthread_mutex_lock(&data.mutex); diff --git a/tests/client-server.c b/tests/client-server.c index 9954b86..f6e8fa5 100644 --- a/tests/client-server.c +++ b/tests/client-server.c @@ -8,12 +8,16 @@ #define _GNU_SOURCE #include "test.h" -#include -#include +#include "data.h" #include #include #include +typedef struct DataInt { + struct icipc_data hdr; + int value; +} DataInt; + static inline char *new_address() { char *address = NULL; (void)asprintf(&address, "icipc-test-%d-%d", getpid(), rand()); @@ -25,20 +29,27 @@ static bool increment_request_handler( struct icipc_server *self, int client_fd, const char *name, - const struct spa_pod *args, + const struct icipc_data *args, void *data) { int32_t val = 0; - test_bool_true(spa_pod_is_int(args)); - test_bool_true(spa_pod_get_int(args, &val) == 0); - struct spa_pod_int res = SPA_POD_INIT_Int(val + 1); - return icipc_server_reply_ok(self, client_fd, (struct spa_pod *)&res); + test_cmpint(args->type, ==, (uint32_t) DATA_TYPE_INT); + test_cmpint(ICIPC_DATA_BODY_SIZE(args), ==, + ROUND_UP_TO_ALIGN(sizeof(int))); + val = *((const int*)ICIPC_DATA_BODY_CONST(args)); + + DataInt res = { + .hdr.size = sizeof(int), + .hdr.type = DATA_TYPE_INT, + .value = val + 1, + }; + return icipc_server_reply_ok(self, client_fd, (struct icipc_data *)&res); } static bool error_request_handler( struct icipc_server *self, int client_fd, const char *name, - const struct spa_pod *args, + const struct icipc_data *args, void *data) { return icipc_server_reply_error(self, client_fd, "error message"); } @@ -68,11 +79,13 @@ static void reply_handler( pthread_mutex_lock(&data->mutex); - const struct spa_pod *pod = + const struct icipc_data *args = icipc_client_send_request_finish(self, buffer, size, &data->error); - if (pod) { - test_bool_true(spa_pod_is_int(pod)); - test_bool_true(spa_pod_get_int(pod, &data->incremented) == 0); + if (args) { + test_cmpint(args->type, ==, (uint32_t) DATA_TYPE_INT); + test_cmpint(ICIPC_DATA_BODY_SIZE(args), ==, + ROUND_UP_TO_ALIGN(sizeof(int))); + data->incremented = *((const int*)ICIPC_DATA_BODY_CONST(args)); } data->n_replies++; pthread_cond_signal(&data->cond); @@ -100,9 +113,13 @@ static void test_icipc_server_client() { data.incremented = -1; data.error = NULL; data.n_replies = 0; - struct spa_pod_int i = SPA_POD_INIT_Int(3); + DataInt i = { + .hdr.size = sizeof(int), + .hdr.type = DATA_TYPE_INT, + .value = 3, + }; test_bool_true(icipc_client_send_request - (c, "INCREMENT", (struct spa_pod *)&i, reply_handler, + (c, "INCREMENT", (struct icipc_data *)&i, reply_handler, &data)); wait_for_reply(&data, 1); test_ptr_null(data.error); diff --git a/tests/protocol.c b/tests/protocol.c index 1d29db3..c0d28e7 100644 --- a/tests/protocol.c +++ b/tests/protocol.c @@ -7,36 +7,49 @@ */ #include "test.h" -#include -#include +#include "data.h" #include +typedef struct DataInt { + struct icipc_data hdr; + int value; +} DataInt; + static void test_icipc_protocol() { uint8_t b[1024]; /* request null value */ { - icipc_protocol_build_request(b, sizeof(b), "name", NULL); const char *name = NULL; - const struct spa_pod *value = NULL; + const struct icipc_data *value = NULL; + + icipc_protocol_build_request(b, sizeof(b), "name", NULL); test_bool_true(icipc_protocol_parse_request (b, sizeof(b), &name, &value)); test_str_eq(name, "name"); - test_bool_true(spa_pod_is_none(value)); + test_cmpint(value->type, ==, (uint32_t) DATA_TYPE_NONE); } /* request */ { - struct spa_pod_int i = SPA_POD_INIT_Int(8); - icipc_protocol_build_request(b, sizeof(b), "name", - (struct spa_pod *)&i); + DataInt i = { + .hdr.size = sizeof(int), + .hdr.type = DATA_TYPE_INT, + .value = 8, + }; const char *name = NULL; - const struct spa_pod_int *value = NULL; + const struct icipc_data *value = NULL; + + icipc_protocol_build_request(b, sizeof(b), "name", + (struct icipc_data *)&i); test_bool_true(icipc_protocol_parse_request (b, sizeof(b), &name, - (const struct spa_pod **)&value)); + (const struct icipc_data **)&value)); test_str_eq(name, "name"); - test_cmpint(value->value, ==, 8); + test_cmpint(ICIPC_DATA_BODY_SIZE(value), ==, + ROUND_UP_TO_ALIGN(sizeof(int))); + test_cmpint(value->type, ==, (uint32_t) DATA_TYPE_INT); + test_cmpint(*((const int*)ICIPC_DATA_BODY_CONST(value)), ==, 8); } /* reply error */ @@ -51,25 +64,34 @@ static void test_icipc_protocol() { /* reply ok null value */ { + const struct icipc_data *value = NULL; + icipc_protocol_build_reply_ok(b, sizeof(b), NULL); test_bool_true(icipc_protocol_is_reply_ok(b, sizeof(b))); - const struct spa_pod *value = NULL; test_bool_true(icipc_protocol_parse_reply_ok (b, sizeof(b), &value)); test_ptr_notnull(value); - test_bool_true(spa_pod_is_none(value)); + test_cmpint(value->type, ==, (uint32_t) DATA_TYPE_NONE); } /* reply ok */ { - struct spa_pod_int i = SPA_POD_INIT_Int(3); + DataInt i = { + .hdr.size = sizeof(int), + .hdr.type = DATA_TYPE_INT, + .value = 3, + }; + const struct icipc_data *value = NULL; + icipc_protocol_build_reply_ok(b, sizeof(b), - (struct spa_pod *)&i); + (struct icipc_data *)&i); test_bool_true(icipc_protocol_is_reply_ok(b, sizeof(b))); - const struct spa_pod_int *value = NULL; test_bool_true(icipc_protocol_parse_reply_ok - (b, sizeof(b), (const struct spa_pod **)&value)); - test_cmpint(value->value, ==, 3); + (b, sizeof(b), (const struct icipc_data **)&value)); + test_cmpint(ICIPC_DATA_BODY_SIZE(value), ==, + ROUND_UP_TO_ALIGN(sizeof(int))); + test_cmpint(value->type, ==, (uint32_t) DATA_TYPE_INT); + test_cmpint(*((const int*)ICIPC_DATA_BODY_CONST(value)), ==, 3); } } -- cgit 1.2.3-korg