diff --git a/meson.build b/meson.build index d4fcab4..6390191 100644 --- a/meson.build +++ b/meson.build @@ -39,6 +39,8 @@ src_libei = [ 'src/libei-device.c', 'src/libei-socket.c', 'src/libei-fd.c', + 'src/libei-proto.h', + 'src/libei-proto.c', proto_headers, ] diff --git a/src/libei-proto.c b/src/libei-proto.c new file mode 100644 index 0000000..0f3e48d --- /dev/null +++ b/src/libei-proto.c @@ -0,0 +1,349 @@ +/* + * Copyright © 2020 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include + +#include "util-object.h" +#include "util-io.h" +#include "util-logger.h" + +#include "proto/ei.pb-c.h" +#include "libei-proto.h" + +void +message_free(struct message *msg) +{ + switch (msg->type) { + default: + break; + } + free(msg); +} + +static void frame_cleanup(Frame **f) { + if (*f) + frame__free_unpacked(*f, NULL); +} + +static void servermessage_cleanup(ServerMessage **m) { + if (*m) + server_message__free_unpacked(*m, NULL); +} +#define _cleanup_frame_ _cleanup_(frame_cleanup) +#define _cleanup_servermessage_ _cleanup_(servermessage_cleanup) + +static const unsigned char * +next_message(const char *data, size_t *msglen, size_t *consumed) +{ + /* Every message is prefixed by a fixed-length Frame message which + * contains the length of the next message. Frames are always the + * same length, so we only need to calculate the size once. + */ + static size_t framelen = 0; + + if (framelen == 0) { + Frame f = FRAME__INIT; + f.length = 0xffff; + framelen = frame__get_packed_size(&f); + assert(framelen >= 5); + } + + _cleanup_frame_ Frame *frame = frame__unpack(NULL, framelen, (const unsigned char *)data); + if (!frame) + return NULL; + + *msglen = frame->length; + *consumed = framelen; + + return (const unsigned char*)data + framelen; +} + +struct message * +ei_proto_parse_message(const char *data, size_t len, size_t *consumed) +{ + size_t headerbytes = 0; + size_t msglen = 0; + const unsigned char *msgdata = next_message(data, &msglen, &headerbytes); + + _cleanup_servermessage_ ServerMessage *proto = server_message__unpack(NULL, msglen, msgdata); + if (!proto) + return NULL; + + *consumed = headerbytes + msglen; + + _cleanup_message_ struct message *msg = xalloc(sizeof(*msg)); + + bool success = true; + switch (proto->msg_case) { + case SERVER_MESSAGE__MSG_CONNECTED: + *msg = (struct message) { + .type = MESSAGE_CONNECTED, + }; + break; + case SERVER_MESSAGE__MSG_DISCONNECTED: + *msg = (struct message) { + .type = MESSAGE_DISCONNECTED, + }; + break; + case SERVER_MESSAGE__MSG_DEVICE_ADDED: + { + DeviceAdded *a = proto->device_added; + *msg = (struct message) { + .type = MESSAGE_DEVICE_ADDED, + .added.deviceid = a->deviceid, + .added.capabilities = a->capabilities, + }; + } + break; + case SERVER_MESSAGE__MSG_DEVICE_REMOVED: + { + DeviceRemoved *r = proto->device_removed; + *msg = (struct message) { + .type = MESSAGE_DEVICE_REMOVED, + .removed.deviceid = r->deviceid, + }; + } + break; + default: + success = false; + break; + } + + return success ? steal(&msg) : NULL; +} + +static inline void +log_wire_message(struct ei *ei, const ClientMessage *msg) +{ + const char *message = NULL; + +#define MSG_STRING_CASE(_name) \ + case CLIENT_MESSAGE__MSG_##_name: message = #_name; break; + + switch (msg->msg_case) { + case CLIENT_MESSAGE__MSG__NOT_SET: + abort(); + MSG_STRING_CASE(CONNECT); + MSG_STRING_CASE(DISCONNECT); + MSG_STRING_CASE(ADD_DEVICE); + MSG_STRING_CASE(REMOVE_DEVICE); + MSG_STRING_CASE(REL); + MSG_STRING_CASE(BUTTON); + MSG_STRING_CASE(KEY); + MSG_STRING_CASE(CONFIGURE_NAME); + MSG_STRING_CASE(CONFIGURE_CAPS); + default: + assert(!"Unimplemented message type"); + break; + } + log_debug(ei, "sending wire message %s\n", message); + +#undef MSG_STRING_CASE +} + +static int +ei_proto_send_msg(struct ei *ei, const ClientMessage *msg) +{ + log_wire_message(ei, msg); + + size_t msglen = client_message__get_packed_size(msg); + Frame frame = FRAME__INIT; + frame.length = msglen; + size_t framelen = frame__get_packed_size(&frame); + + uint8_t buf[framelen + msglen]; + frame__pack(&frame, buf); + client_message__pack(msg, buf + framelen); + return min(0, xsend(source_get_fd(ei->source), buf, sizeof(buf))); +} + +int +ei_proto_send_connect(struct ei *ei) +{ + ClientMessage msg = CLIENT_MESSAGE__INIT; + Connect connect = CONNECT__INIT; + connect.name = ei->name; + + msg.connect = &connect; + msg.msg_case = CLIENT_MESSAGE__MSG_CONNECT; + + return ei_proto_send_msg(ei, &msg); +} + +int +ei_proto_send_disconnect(struct ei *ei) +{ + ClientMessage msg = CLIENT_MESSAGE__INIT; + Disconnect disconnect = DISCONNECT__INIT; + + msg.disconnect = &disconnect; + msg.msg_case = CLIENT_MESSAGE__MSG_DISCONNECT; + + return ei_proto_send_msg(ei, &msg); +} + +int +ei_proto_send_add(struct ei *ei, struct ei_device *device) +{ + ClientMessage msg = CLIENT_MESSAGE__INIT; + AddDevice add = ADD_DEVICE__INIT; + + add.deviceid = device->id; + add.capabilities = device->capabilities; + add.pointer_width = device->abs.dim.width; + add.pointer_height = device->abs.dim.height; + add.touch_width = device->touch.dim.width; + add.touch_height = device->touch.dim.height; + + msg.add_device = &add; + msg.msg_case = CLIENT_MESSAGE__MSG_ADD_DEVICE; + + return ei_proto_send_msg(ei, &msg); +} + +int +ei_proto_send_remove(struct ei *ei, struct ei_device *device) +{ + ClientMessage msg = CLIENT_MESSAGE__INIT; + RemoveDevice remove = REMOVE_DEVICE__INIT; + + remove.deviceid = device->id; + + msg.remove_device = &remove; + msg.msg_case = CLIENT_MESSAGE__MSG_REMOVE_DEVICE; + + return ei_proto_send_msg(ei, &msg); +} + +int +ei_proto_send_rel(struct ei *ei, struct ei_device *device, + double x, double y) +{ + ClientMessage msg = CLIENT_MESSAGE__INIT; + PointerRelative rel = POINTER_RELATIVE__INIT; + + rel.deviceid = device->id; + rel.x = x; + rel.y = y; + + msg.rel = &rel; + msg.msg_case = CLIENT_MESSAGE__MSG_REL; + + return ei_proto_send_msg(ei, &msg); +} + +int +ei_proto_send_button(struct ei *ei, struct ei_device *device, + uint32_t b, bool is_press) +{ + ClientMessage msg = CLIENT_MESSAGE__INIT; + PointerButton button = POINTER_BUTTON__INIT; + + button.deviceid = device->id; + button.button = b; + button.state = is_press; + + msg.button = &button; + msg.msg_case = CLIENT_MESSAGE__MSG_BUTTON; + + return ei_proto_send_msg(ei, &msg); +} + +int +ei_proto_send_key(struct ei *ei, struct ei_device *device, + uint32_t k, bool is_press) +{ + ClientMessage msg = CLIENT_MESSAGE__INIT; + KeyboardKey key = KEYBOARD_KEY__INIT; + + key.deviceid = device->id; + key.key = k; + key.state = is_press; + + msg.key = &key; + msg.msg_case = CLIENT_MESSAGE__MSG_KEY; + + return ei_proto_send_msg(ei, &msg); +} + + +#ifdef _enable_tests_ +#include + +static MunitResult +test_proto_next_message(const MunitParameter params[], void *user_data) +{ + char data[64]; + + /* Invalid frame, rest can be random */ + data[0] = 0xaa; + + size_t msglen = 0xab; + size_t consumed = 0xbc; + + const unsigned char *rval = next_message(data, &msglen, &consumed); + munit_assert_ptr_null(rval); + munit_assert_int(msglen, ==, 0xab); + munit_assert_int(consumed, ==, 0xbc); + + /* Now try a valid one */ + Frame f = FRAME__INIT; + f.length = 0xcd; + size_t framelen = frame__get_packed_size(&f); + + unsigned char buf[framelen * 4]; + for (int i = 0; i < 4; i++) + frame__pack(&f, buf + framelen * i); + + const char *ptr = (char*)buf; + for (int i = 0; i < 4; i++) { + const unsigned char *next_frame = next_message(ptr, &msglen, &consumed); + munit_assert_ptr_equal(next_frame, buf + (i + 1) * framelen); + munit_assert_int(consumed, ==, framelen); + munit_assert_int(msglen, ==, 0xcd); + ptr += consumed; + } + + return MUNIT_OK; +} + +#define TEST(_func) \ + { .name = #_func, .test = _func } + +static MunitTest ei_tests[] = { + TEST(test_proto_next_message), + { NULL }, +}; + +static const MunitSuite libei_suite +__attribute__((used)) +__attribute__((section("test_section"))) = { + "", + ei_tests, + NULL, + 1, + MUNIT_SUITE_OPTION_NONE, +}; +#endif diff --git a/src/libei-proto.h b/src/libei-proto.h new file mode 100644 index 0000000..0b5f482 --- /dev/null +++ b/src/libei-proto.h @@ -0,0 +1,90 @@ +/* + * Copyright © 2020 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include "config.h" + +#include "util-macros.h" +#include "util-mem.h" + +#include "libei-private.h" + +/* The message type for the wire format */ +enum message_type { + MESSAGE_CONNECTED = 1, + MESSAGE_DISCONNECTED, + MESSAGE_DEVICE_ADDED, + MESSAGE_DEVICE_REMOVED, +}; + +struct message { + enum message_type type; + union { + struct message_connected { + uint8_t pad; /* no data */ + } connected; + struct message_disconnected { + uint8_t pad; /* no data */ + } disconnected; + struct message_device_added { + uint32_t deviceid; + uint32_t capabilities; + } added; + struct message_device_removed { + uint32_t deviceid; + } removed; + }; +}; + +void message_free(struct message *msg); + +DEFINE_TRIVIAL_CLEANUP_FUNC(struct message*, message_free); +#define _cleanup_message_ _cleanup_(message_freep) + +struct message * +ei_proto_parse_message(const char *data, size_t len, size_t *consumed); + +int +ei_proto_send_connect(struct ei *ei); + +int +ei_proto_send_disconnect(struct ei *ei); + +int +ei_proto_send_add(struct ei *ei, struct ei_device *device); + +int +ei_proto_send_remove(struct ei *ei, struct ei_device *device); + +int +ei_proto_send_rel(struct ei *ei, struct ei_device *device, + double x, double y); + +int +ei_proto_send_button(struct ei *ei, struct ei_device *device, + uint32_t b, bool is_press); + +int +ei_proto_send_key(struct ei *ei, struct ei_device *device, + uint32_t k, bool is_press); diff --git a/src/libei.c b/src/libei.c index 9ce1f02..6fbe37f 100644 --- a/src/libei.c +++ b/src/libei.c @@ -37,48 +37,7 @@ #include "libei.h" #include "libei-private.h" - -#include "proto/ei.pb-c.h" - -/* The message type for the wire format */ -enum message_type { - MESSAGE_CONNECTED = 1, - MESSAGE_DISCONNECTED, - MESSAGE_DEVICE_ADDED, - MESSAGE_DEVICE_REMOVED, -}; - -struct message { - enum message_type type; - union { - struct message_connected { - uint8_t pad; /* no data */ - } connected; - struct message_disconnected { - uint8_t pad; /* no data */ - } disconnected; - struct MESSAGE_DEVICE_ADDED { - uint32_t deviceid; - uint32_t capabilities; - } added; - struct MESSAGE_DEVICE_REMOVED { - uint32_t deviceid; - } removed; - }; -}; - -static void -message_free(struct message *msg) -{ - switch (msg->type) { - default: - break; - } - free(msg); -} - -DEFINE_TRIVIAL_CLEANUP_FUNC(struct message*, message_free); -#define _cleanup_message_ _cleanup_(message_freep) +#include "libei-proto.h" static void ei_event_destroy(struct ei_event *event) @@ -219,52 +178,6 @@ ei_queue_removed_event(struct ei_device *device) ei_queue_event(ei, e); } -static inline void -log_wire_message(struct ei *ei, const ClientMessage *msg) -{ - const char *message = NULL; - -#define MSG_STRING_CASE(_name) \ - case CLIENT_MESSAGE__MSG_##_name: message = #_name; break; - - switch (msg->msg_case) { - case CLIENT_MESSAGE__MSG__NOT_SET: - abort(); - MSG_STRING_CASE(CONNECT); - MSG_STRING_CASE(DISCONNECT); - MSG_STRING_CASE(ADD_DEVICE); - MSG_STRING_CASE(REMOVE_DEVICE); - MSG_STRING_CASE(REL); - MSG_STRING_CASE(BUTTON); - MSG_STRING_CASE(KEY); - MSG_STRING_CASE(CONFIGURE_NAME); - MSG_STRING_CASE(CONFIGURE_CAPS); - default: - assert(!"Unimplemented message type"); - break; - } - log_debug(ei, "sending wire message %s\n", message); - -#undef MSG_STRING_CASE -} - - -static int -connection_send_msg(struct ei *ei, const ClientMessage *msg) -{ - log_wire_message(ei, msg); - - size_t msglen = client_message__get_packed_size(msg); - Frame frame = FRAME__INIT; - frame.length = msglen; - size_t framelen = frame__get_packed_size(&frame); - - uint8_t buf[framelen + msglen]; - frame__pack(&frame, buf); - client_message__pack(msg, buf + framelen); - return min(0, xsend(source_get_fd(ei->source), buf, sizeof(buf))); -} - static int connection_send_connect(struct ei *ei) { @@ -272,14 +185,7 @@ connection_send_connect(struct ei *ei) ei->state == EI_STATE_DISCONNECTED) return 0; - ClientMessage msg = CLIENT_MESSAGE__INIT; - Connect connect = CONNECT__INIT; - connect.name = ei->name; - - msg.connect = &connect; - msg.msg_case = CLIENT_MESSAGE__MSG_CONNECT; - - return connection_send_msg(ei, &msg); + return ei_proto_send_connect(ei); } static int @@ -289,13 +195,7 @@ connection_send_disconnect(struct ei *ei) ei->state == EI_STATE_DISCONNECTED) return 0; - ClientMessage msg = CLIENT_MESSAGE__INIT; - Disconnect disconnect = DISCONNECT__INIT; - - msg.disconnect = &disconnect; - msg.msg_case = CLIENT_MESSAGE__MSG_DISCONNECT; - - return connection_send_msg(ei, &msg); + return ei_proto_send_disconnect(ei); } static int @@ -305,20 +205,7 @@ connection_send_add(struct ei *ei, struct ei_device *device) ei->state == EI_STATE_DISCONNECTED) return 0; - ClientMessage msg = CLIENT_MESSAGE__INIT; - AddDevice add = ADD_DEVICE__INIT; - - add.deviceid = device->id; - add.capabilities = device->capabilities; - add.pointer_width = device->abs.dim.width; - add.pointer_height = device->abs.dim.height; - add.touch_width = device->touch.dim.width; - add.touch_height = device->touch.dim.height; - - msg.add_device = &add; - msg.msg_case = CLIENT_MESSAGE__MSG_ADD_DEVICE; - - return connection_send_msg(ei, &msg); + return ei_proto_send_add(ei, device); } static int @@ -328,15 +215,7 @@ connection_send_remove(struct ei *ei, struct ei_device *device) ei->state == EI_STATE_DISCONNECTED) return 0; - ClientMessage msg = CLIENT_MESSAGE__INIT; - RemoveDevice remove = REMOVE_DEVICE__INIT; - - remove.deviceid = device->id; - - msg.remove_device = &remove; - msg.msg_case = CLIENT_MESSAGE__MSG_REMOVE_DEVICE; - - return connection_send_msg(ei, &msg); + return ei_proto_send_remove(ei, device); } static int @@ -347,17 +226,7 @@ connection_send_rel(struct ei *ei, struct ei_device *device, ei->state == EI_STATE_DISCONNECTED) return 0; - ClientMessage msg = CLIENT_MESSAGE__INIT; - PointerRelative rel = POINTER_RELATIVE__INIT; - - rel.deviceid = device->id; - rel.x = x; - rel.y = y; - - msg.rel = &rel; - msg.msg_case = CLIENT_MESSAGE__MSG_REL; - - return connection_send_msg(ei, &msg); + return ei_proto_send_rel(ei, device, x, y); } static int @@ -368,17 +237,7 @@ connection_send_button(struct ei *ei, struct ei_device *device, ei->state == EI_STATE_DISCONNECTED) return 0; - ClientMessage msg = CLIENT_MESSAGE__INIT; - PointerButton button = POINTER_BUTTON__INIT; - - button.deviceid = device->id; - button.button = b; - button.state = is_press; - - msg.button = &button; - msg.msg_case = CLIENT_MESSAGE__MSG_BUTTON; - - return connection_send_msg(ei, &msg); + return ei_proto_send_button(ei, device, b, is_press); } static int @@ -389,17 +248,7 @@ connection_send_key(struct ei *ei, struct ei_device *device, ei->state == EI_STATE_DISCONNECTED) return 0; - ClientMessage msg = CLIENT_MESSAGE__INIT; - KeyboardKey key = KEYBOARD_KEY__INIT; - - key.deviceid = device->id; - key.key = k; - key.state = is_press; - - msg.key = &key; - msg.msg_case = CLIENT_MESSAGE__MSG_KEY; - - return connection_send_msg(ei, &msg); + return ei_proto_send_key(ei, device, k, is_press); } static void @@ -552,97 +401,6 @@ ei_peek_event(struct ei *ei) return ei_event_ref(e); } -static void frame_cleanup(Frame **f) { - if (*f) - frame__free_unpacked(*f, NULL); -} -static void servermessage_cleanup(ServerMessage **m) { - if (*m) - server_message__free_unpacked(*m, NULL); -} -#define _cleanup_frame_ _cleanup_(frame_cleanup) -#define _cleanup_servermessage_ _cleanup_(servermessage_cleanup) - -static const unsigned char * -next_message(const char *data, size_t *msglen, size_t *consumed) -{ - /* Every message is prefixed by a fixed-length Frame message which - * contains the length of the next message. Frames are always the - * same length, so we only need to calculate the size once. - */ - static size_t framelen = 0; - - if (framelen == 0) { - Frame f = FRAME__INIT; - f.length = 0xffff; - framelen = frame__get_packed_size(&f); - assert(framelen >= 5); - } - - _cleanup_frame_ Frame *frame = frame__unpack(NULL, framelen, (const unsigned char *)data); - if (!frame) - return NULL; - - *msglen = frame->length; - *consumed = framelen; - - return (const unsigned char*)data + framelen; -} - -static struct message * -connection_parse_message(const char *data, size_t len, size_t *consumed) -{ - size_t headerbytes = 0; - size_t msglen = 0; - const unsigned char *msgdata = next_message(data, &msglen, &headerbytes); - - _cleanup_servermessage_ ServerMessage *proto = server_message__unpack(NULL, msglen, msgdata); - if (!proto) - return NULL; - - *consumed = headerbytes + msglen; - - _cleanup_message_ struct message *msg = xalloc(sizeof(*msg)); - - bool success = true; - switch (proto->msg_case) { - case SERVER_MESSAGE__MSG_CONNECTED: - *msg = (struct message) { - .type = MESSAGE_CONNECTED, - }; - break; - case SERVER_MESSAGE__MSG_DISCONNECTED: - *msg = (struct message) { - .type = MESSAGE_DISCONNECTED, - }; - break; - case SERVER_MESSAGE__MSG_DEVICE_ADDED: - { - DeviceAdded *a = proto->device_added; - *msg = (struct message) { - .type = MESSAGE_DEVICE_ADDED, - .added.deviceid = a->deviceid, - .added.capabilities = a->capabilities, - }; - } - break; - case SERVER_MESSAGE__MSG_DEVICE_REMOVED: - { - DeviceRemoved *r = proto->device_removed; - *msg = (struct message) { - .type = MESSAGE_DEVICE_REMOVED, - .removed.deviceid = r->deviceid, - }; - } - break; - default: - success = false; - break; - } - - return success ? steal(&msg) : NULL; -} - static int connection_new_handle_msg(struct ei *ei, struct message *msg) { @@ -731,8 +489,8 @@ connection_dispatch(struct source *source, void *userdata) if (len == 0) break; - _cleanup_(message_freep) struct message *msg = - connection_parse_message(data, len, &consumed); + _cleanup_message_ struct message *msg = + ei_proto_parse_message(data, len, &consumed); if (!msg) { rc = -EBADMSG; break; @@ -875,50 +633,12 @@ test_configure_name(const MunitParameter params[], void *user_data) return MUNIT_OK; } -static MunitResult -test_proto_next_message(const MunitParameter params[], void *user_data) -{ - char data[64]; - - /* Invalid frame, rest can be random */ - data[0] = 0xaa; - - size_t msglen = 0xab; - size_t consumed = 0xbc; - - const unsigned char *rval = next_message(data, &msglen, &consumed); - munit_assert_ptr_null(rval); - munit_assert_int(msglen, ==, 0xab); - munit_assert_int(consumed, ==, 0xbc); - - /* Now try a valid one */ - Frame f = FRAME__INIT; - f.length = 0xcd; - size_t framelen = frame__get_packed_size(&f); - - unsigned char buf[framelen * 4]; - for (int i = 0; i < 4; i++) - frame__pack(&f, buf + framelen * i); - - const char *ptr = (char*)buf; - for (int i = 0; i < 4; i++) { - const unsigned char *next_frame = next_message(ptr, &msglen, &consumed); - munit_assert_ptr_equal(next_frame, buf + (i + 1) * framelen); - munit_assert_int(consumed, ==, framelen); - munit_assert_int(msglen, ==, 0xcd); - ptr += consumed; - } - - return MUNIT_OK; -} - #define TEST(_func) \ { .name = #_func, .test = _func } static MunitTest ei_tests[] = { TEST(test_init_unref), TEST(test_configure_name), - TEST(test_proto_next_message), { NULL }, };