From f8df5088407d06154d16ee18d691c0313b7eec07 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Fri, 11 Oct 2024 18:43:59 +0200 Subject: [PATCH 01/17] Improve throughput performance (trigger local subscriber focus) (#730) * feat: switch null functions to static inline * feat: switch check fct to static inline * feat: check if there are subs to trigger * feat: pass by ref with keyexpr alias and duplicate * feat: switch null fct to return {0} * feat: add local sub config token * feat: simplify slice_init / string_preallocate * feat: add expanded key case * feat: make _alias fct static inline * doc: fix typo * fix: add local subscriber token to config.h * doc: add warning on null functions * feat: add reply_data_init function --- CMakeLists.txt | 1 + include/zenoh-pico/collections/bytes.h | 3 +- include/zenoh-pico/collections/slice.h | 18 ++++++---- include/zenoh-pico/collections/string.h | 10 ++++-- include/zenoh-pico/config.h | 1 + include/zenoh-pico/config.h.in | 1 + include/zenoh-pico/net/encoding.h | 9 +++-- include/zenoh-pico/net/publish.h | 5 +-- include/zenoh-pico/net/query.h | 9 +++-- include/zenoh-pico/net/reply.h | 11 ++++-- include/zenoh-pico/net/sample.h | 8 +++-- include/zenoh-pico/net/subscribe.h | 7 ++-- include/zenoh-pico/protocol/core.h | 16 ++++++--- .../protocol/definitions/declarations.h | 27 +++++++++----- .../protocol/definitions/interest.h | 4 +-- .../zenoh-pico/protocol/definitions/network.h | 4 ++- include/zenoh-pico/protocol/keyexpr.h | 17 +++++---- src/api/api.c | 8 +++-- src/collections/bytes.c | 6 ---- src/collections/slice.c | 36 ++++--------------- src/collections/string.c | 21 +++-------- src/net/encoding.c | 16 +++------ src/net/primitives.c | 2 +- src/net/publish.c | 13 ------- src/net/query.c | 16 --------- src/net/reply.c | 13 ++----- src/net/sample.c | 18 ---------- src/net/subscribe.c | 3 -- src/protocol/core.c | 10 ------ src/protocol/definitions/declarations.c | 16 ++------- src/protocol/definitions/interest.c | 2 -- src/protocol/definitions/network.c | 5 --- src/protocol/keyexpr.c | 15 ++------ src/session/interest.c | 2 +- src/session/query.c | 3 +- src/session/resource.c | 25 +++++++------ src/session/subscription.c | 8 +++-- 37 files changed, 158 insertions(+), 231 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f5d01971..cd03262b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -204,6 +204,7 @@ set(Z_FEATURE_MULTICAST_TRANSPORT 1 CACHE STRING "Toggle multicast transport") set(Z_FEATURE_UNICAST_TRANSPORT 1 CACHE STRING "Toggle unicast transport") set(Z_FEATURE_RAWETH_TRANSPORT 0 CACHE STRING "Toggle raw ethernet transport") set(Z_FEATURE_TCP_NODELAY 1 CACHE STRING "Toggle TCP_NODELAY") +set(Z_FEATURE_LOCAL_SUBSCRIBER 0 CACHE STRING "Toggle local subscriptions") add_compile_definitions("Z_BUILD_DEBUG=$") message(STATUS "Building with feature confing:\n\ diff --git a/include/zenoh-pico/collections/bytes.h b/include/zenoh-pico/collections/bytes.h index b662ff613..2496520c1 100644 --- a/include/zenoh-pico/collections/bytes.h +++ b/include/zenoh-pico/collections/bytes.h @@ -45,8 +45,9 @@ typedef struct { _z_arc_slice_svec_t _slices; } _z_bytes_t; +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_bytes_t _z_bytes_null(void) { return (_z_bytes_t){0}; } bool _z_bytes_check(const _z_bytes_t *bytes); -_z_bytes_t _z_bytes_null(void); z_result_t _z_bytes_append_bytes(_z_bytes_t *dst, _z_bytes_t *src); z_result_t _z_bytes_append_slice(_z_bytes_t *dst, _z_arc_slice_t *s); z_result_t _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src); diff --git a/include/zenoh-pico/collections/slice.h b/include/zenoh-pico/collections/slice.h index 8027f6b1c..b6b6f45a5 100644 --- a/include/zenoh-pico/collections/slice.h +++ b/include/zenoh-pico/collections/slice.h @@ -26,9 +26,13 @@ typedef struct { void *context; } _z_delete_context_t; -_z_delete_context_t _z_delete_context_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_delete_context_t _z_delete_context_null(void) { return (_z_delete_context_t){0}; } + +static inline _z_delete_context_t _z_delete_context_create(void (*deleter)(void *context, void *data), void *context) { + return (_z_delete_context_t){.deleter = deleter, .context = context}; +} bool _z_delete_context_is_null(const _z_delete_context_t *c); -_z_delete_context_t _z_delete_context_create(void (*deleter)(void *context, void *data), void *context); _z_delete_context_t _z_delete_context_default(void); void _z_delete_context_delete(_z_delete_context_t *c, void *data); @@ -47,21 +51,23 @@ typedef struct { _z_delete_context_t _delete_context; } _z_slice_t; -_z_slice_t _z_slice_empty(void); -inline static bool _z_slice_check(const _z_slice_t *slice) { return slice->start != NULL; } +static inline _z_slice_t _z_slice_empty(void) { return (_z_slice_t){0}; } +static inline bool _z_slice_is_empty(const _z_slice_t *bs) { return bs->len == 0; } +static inline bool _z_slice_check(const _z_slice_t *slice) { return slice->start != NULL; } +static inline _z_slice_t _z_slice_alias(const _z_slice_t bs) { + return (_z_slice_t){.len = bs.len, .start = bs.start, ._delete_context = _z_delete_context_null()}; +} z_result_t _z_slice_init(_z_slice_t *bs, size_t capacity); _z_slice_t _z_slice_make(size_t capacity); _z_slice_t _z_slice_alias_buf(const uint8_t *bs, size_t len); _z_slice_t _z_slice_from_buf_custom_deleter(const uint8_t *p, size_t len, _z_delete_context_t dc); _z_slice_t _z_slice_copy_from_buf(const uint8_t *bs, size_t len); _z_slice_t _z_slice_steal(_z_slice_t *b); -_z_slice_t _z_slice_alias(const _z_slice_t *bs); z_result_t _z_slice_copy(_z_slice_t *dst, const _z_slice_t *src); z_result_t _z_slice_n_copy(_z_slice_t *dst, const _z_slice_t *src, size_t offset, size_t len); _z_slice_t _z_slice_duplicate(const _z_slice_t *src); void _z_slice_move(_z_slice_t *dst, _z_slice_t *src); void _z_slice_reset(_z_slice_t *bs); -bool _z_slice_is_empty(const _z_slice_t *bs); bool _z_slice_eq(const _z_slice_t *left, const _z_slice_t *right); void _z_slice_clear(_z_slice_t *bs); void _z_slice_free(_z_slice_t **bs); diff --git a/include/zenoh-pico/collections/string.h b/include/zenoh-pico/collections/string.h index f2ebd15ac..167604774 100644 --- a/include/zenoh-pico/collections/string.h +++ b/include/zenoh-pico/collections/string.h @@ -66,8 +66,13 @@ typedef struct { _z_slice_t _slice; } _z_string_t; -_z_string_t _z_string_null(void); -bool _z_string_check(const _z_string_t *value); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_string_t _z_string_null(void) { return (_z_string_t){0}; } +static inline bool _z_string_check(const _z_string_t *value) { return !_z_slice_is_empty(&value->_slice); } +static inline _z_string_t _z_string_alias(const _z_string_t str) { + return (_z_string_t){._slice = _z_slice_alias(str._slice)}; +} + _z_string_t _z_string_copy_from_str(const char *value); _z_string_t _z_string_copy_from_substr(const char *value, size_t len); _z_string_t *_z_string_copy_from_str_as_ptr(const char *value); @@ -84,7 +89,6 @@ z_result_t _z_string_copy(_z_string_t *dst, const _z_string_t *src); z_result_t _z_string_copy_substring(_z_string_t *dst, const _z_string_t *src, size_t offset, size_t len); void _z_string_move(_z_string_t *dst, _z_string_t *src); _z_string_t _z_string_steal(_z_string_t *str); -_z_string_t _z_string_alias(const _z_string_t *str); void _z_string_move_str(_z_string_t *dst, char *src); void _z_string_clear(_z_string_t *s); void _z_string_free(_z_string_t **s); diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index b3c5d3ec1..8ee4cf966 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -42,6 +42,7 @@ #define Z_FEATURE_FRAGMENTATION 1 #define Z_FEATURE_ENCODING_VALUES 1 #define Z_FEATURE_TCP_NODELAY 1 +#define Z_FEATURE_LOCAL_SUBSCRIBER 0 // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/include/zenoh-pico/config.h.in b/include/zenoh-pico/config.h.in index 40941d9fa..74ac25194 100644 --- a/include/zenoh-pico/config.h.in +++ b/include/zenoh-pico/config.h.in @@ -42,6 +42,7 @@ #define Z_FEATURE_FRAGMENTATION @Z_FEATURE_FRAGMENTATION@ #define Z_FEATURE_ENCODING_VALUES @Z_FEATURE_ENCODING_VALUES@ #define Z_FEATURE_TCP_NODELAY @Z_FEATURE_TCP_NODELAY@ +#define Z_FEATURE_LOCAL_SUBSCRIBER @Z_FEATURE_LOCAL_SUBSCRIBER@ // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/include/zenoh-pico/net/encoding.h b/include/zenoh-pico/net/encoding.h index 88ac5f0d1..969f0c34e 100644 --- a/include/zenoh-pico/net/encoding.h +++ b/include/zenoh-pico/net/encoding.h @@ -27,11 +27,14 @@ typedef struct _z_encoding_t { uint16_t id; } _z_encoding_t; -z_result_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *schema, size_t len); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_encoding_t _z_encoding_null(void) { return (_z_encoding_t){0}; } +static inline bool _z_encoding_check(const _z_encoding_t *encoding) { + return ((encoding->id != _Z_ENCODING_ID_DEFAULT) || _z_string_check(&encoding->schema)); +} _z_encoding_t _z_encoding_wrap(uint16_t id, const char *schema); -_z_encoding_t _z_encoding_null(void); +z_result_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *schema, size_t len); void _z_encoding_clear(_z_encoding_t *encoding); -bool _z_encoding_check(const _z_encoding_t *encoding); z_result_t _z_encoding_copy(_z_encoding_t *dst, const _z_encoding_t *src); void _z_encoding_move(_z_encoding_t *dst, _z_encoding_t *src); _z_encoding_t _z_encoding_steal(_z_encoding_t *val); diff --git a/include/zenoh-pico/net/publish.h b/include/zenoh-pico/net/publish.h index 21a8b500f..b3bc40891 100644 --- a/include/zenoh-pico/net/publish.h +++ b/include/zenoh-pico/net/publish.h @@ -37,10 +37,11 @@ typedef struct _z_publisher_t { } _z_publisher_t; #if Z_FEATURE_PUBLICATION == 1 +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_publisher_t _z_publisher_null(void) { return (_z_publisher_t){0}; } +static inline bool _z_publisher_check(const _z_publisher_t *publisher) { return !_Z_RC_IS_NULL(&publisher->_zn); } void _z_publisher_clear(_z_publisher_t *pub); void _z_publisher_free(_z_publisher_t **pub); -bool _z_publisher_check(const _z_publisher_t *publisher); -_z_publisher_t _z_publisher_null(void); #endif #endif /* INCLUDE_ZENOH_PICO_NET_PUBLISH_H */ diff --git a/include/zenoh-pico/net/query.h b/include/zenoh-pico/net/query.h index 5e57c1eee..703688a65 100644 --- a/include/zenoh-pico/net/query.h +++ b/include/zenoh-pico/net/query.h @@ -34,7 +34,8 @@ typedef struct _z_query_t { bool _anyke; } _z_query_t; -_z_query_t _z_query_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_query_t _z_query_null(void) { return (_z_query_t){0}; } void _z_query_clear(_z_query_t *q); z_result_t _z_query_copy(_z_query_t *dst, const _z_query_t *src); void _z_query_free(_z_query_t **query); @@ -50,12 +51,14 @@ typedef struct { } _z_queryable_t; #if Z_FEATURE_QUERYABLE == 1 +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_queryable_t _z_queryable_null(void) { return (_z_queryable_t){0}; } +static inline bool _z_queryable_check(const _z_queryable_t *queryable) { return !_Z_RC_IS_NULL(&queryable->_zn); } _z_query_t _z_query_create(_z_value_t *value, _z_keyexpr_t *key, const _z_slice_t *parameters, _z_session_rc_t *zn, uint32_t request_id, const _z_bytes_t attachment); void _z_queryable_clear(_z_queryable_t *qbl); void _z_queryable_free(_z_queryable_t **qbl); -_z_queryable_t _z_queryable_null(void); -bool _z_queryable_check(const _z_queryable_t *queryable); + #endif #endif /* ZENOH_PICO_QUERY_NETAPI_H */ diff --git a/include/zenoh-pico/net/reply.h b/include/zenoh-pico/net/reply.h index 14ef1b232..c68fcf678 100644 --- a/include/zenoh-pico/net/reply.h +++ b/include/zenoh-pico/net/reply.h @@ -57,6 +57,13 @@ typedef struct _z_reply_data_t { _z_reply_tag_t _tag; } _z_reply_data_t; +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_reply_data_t _z_reply_data_null(void) { return (_z_reply_data_t){0}; } +static inline _z_reply_data_t _z_reply_data_init(void) { + _z_reply_data_t reply_data = _z_reply_data_null(); + reply_data._tag = _Z_REPLY_TAG_NONE; + return reply_data; +} void _z_reply_data_clear(_z_reply_data_t *rd); z_result_t _z_reply_data_copy(_z_reply_data_t *dst, const _z_reply_data_t *src); @@ -76,9 +83,9 @@ typedef struct _z_reply_t { _z_reply_data_t data; } _z_reply_t; +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_reply_t _z_reply_null(void) { return (_z_reply_t){0}; } _z_reply_t _z_reply_move(_z_reply_t *src_reply); - -_z_reply_t _z_reply_null(void); void _z_reply_clear(_z_reply_t *src); void _z_reply_free(_z_reply_t **hello); z_result_t _z_reply_copy(_z_reply_t *dst, const _z_reply_t *src); diff --git a/include/zenoh-pico/net/sample.h b/include/zenoh-pico/net/sample.h index 9fadfbc76..213e1eaa1 100644 --- a/include/zenoh-pico/net/sample.h +++ b/include/zenoh-pico/net/sample.h @@ -40,8 +40,12 @@ typedef struct _z_sample_t { } _z_sample_t; void _z_sample_clear(_z_sample_t *sample); -_z_sample_t _z_sample_null(void); -bool _z_sample_check(const _z_sample_t *sample); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_sample_t _z_sample_null(void) { return (_z_sample_t){0}; } +static inline bool _z_sample_check(const _z_sample_t *sample) { + return _z_keyexpr_check(&sample->keyexpr) || _z_encoding_check(&sample->encoding) || + _z_bytes_check(&sample->payload) || _z_bytes_check(&sample->attachment); +} void _z_sample_move(_z_sample_t *dst, _z_sample_t *src); /** diff --git a/include/zenoh-pico/net/subscribe.h b/include/zenoh-pico/net/subscribe.h index 4cf0cb4d4..b8129673e 100644 --- a/include/zenoh-pico/net/subscribe.h +++ b/include/zenoh-pico/net/subscribe.h @@ -29,11 +29,12 @@ typedef struct { } _z_subscriber_t; #if Z_FEATURE_SUBSCRIPTION == 1 - +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_subscriber_t _z_subscriber_null(void) { return (_z_subscriber_t){0}; } +static inline bool _z_subscriber_check(const _z_subscriber_t *subscriber) { return !_Z_RC_IS_NULL(&subscriber->_zn); } void _z_subscriber_clear(_z_subscriber_t *sub); void _z_subscriber_free(_z_subscriber_t **sub); -bool _z_subscriber_check(const _z_subscriber_t *subscriber); -_z_subscriber_t _z_subscriber_null(void); + #endif #endif /* ZENOH_PICO_SUBSCRIBE_NETAPI_H */ diff --git a/include/zenoh-pico/protocol/core.h b/include/zenoh-pico/protocol/core.h index 7dcf49508..d5f85299a 100644 --- a/include/zenoh-pico/protocol/core.h +++ b/include/zenoh-pico/protocol/core.h @@ -66,8 +66,9 @@ typedef struct { uint64_t time; } _z_timestamp_t; +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_timestamp_t _z_timestamp_null(void) { return (_z_timestamp_t){0}; } _z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp); -_z_timestamp_t _z_timestamp_null(void); void _z_timestamp_clear(_z_timestamp_t *tstamp); bool _z_timestamp_check(const _z_timestamp_t *stamp); uint64_t _z_timestamp_ntp64_from_time(uint32_t seconds, uint32_t nanos); @@ -163,7 +164,9 @@ typedef struct { _z_bytes_t payload; _z_encoding_t encoding; } _z_value_t; -_z_value_t _z_value_null(void); + +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_value_t _z_value_null(void) { return (_z_value_t){0}; } _z_value_t _z_value_steal(_z_value_t *value); z_result_t _z_value_copy(_z_value_t *dst, const _z_value_t *src); void _z_value_move(_z_value_t *dst, _z_value_t *src); @@ -184,10 +187,13 @@ typedef struct { z_whatami_t _whatami; uint8_t _version; } _z_hello_t; + +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_hello_t _z_hello_null(void) { return (_z_hello_t){0}; } void _z_hello_clear(_z_hello_t *src); void _z_hello_free(_z_hello_t **hello); z_result_t _z_hello_copy(_z_hello_t *dst, const _z_hello_t *src); -_z_hello_t _z_hello_null(void); + bool _z_hello_check(const _z_hello_t *hello); _Z_ELEM_DEFINE(_z_hello, _z_hello_t, _z_noop_size, _z_hello_clear, _z_noop_copy) @@ -202,7 +208,9 @@ typedef struct { uint32_t _entity_id; uint32_t _source_sn; } _z_source_info_t; -_z_source_info_t _z_source_info_null(void); + +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_source_info_t _z_source_info_null(void) { return (_z_source_info_t){0}; } typedef struct { uint32_t _request_id; diff --git a/include/zenoh-pico/protocol/definitions/declarations.h b/include/zenoh-pico/protocol/definitions/declarations.h index c33cab627..cb8224239 100644 --- a/include/zenoh-pico/protocol/definitions/declarations.h +++ b/include/zenoh-pico/protocol/definitions/declarations.h @@ -24,22 +24,26 @@ typedef struct { uint16_t _id; _z_keyexpr_t _keyexpr; } _z_decl_kexpr_t; -_z_decl_kexpr_t _z_decl_kexpr_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_decl_kexpr_t _z_decl_kexpr_null(void) { return (_z_decl_kexpr_t){0}; } typedef struct { uint16_t _id; } _z_undecl_kexpr_t; -_z_undecl_kexpr_t _z_undecl_kexpr_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_undecl_kexpr_t _z_undecl_kexpr_null(void) { return (_z_undecl_kexpr_t){0}; } typedef struct { _z_keyexpr_t _keyexpr; uint32_t _id; } _z_decl_subscriber_t; -_z_decl_subscriber_t _z_decl_subscriber_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_decl_subscriber_t _z_decl_subscriber_null(void) { return (_z_decl_subscriber_t){0}; } typedef struct { uint32_t _id; _z_keyexpr_t _ext_keyexpr; } _z_undecl_subscriber_t; -_z_undecl_subscriber_t _z_undecl_subscriber_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_undecl_subscriber_t _z_undecl_subscriber_null(void) { return (_z_undecl_subscriber_t){0}; } typedef struct { _z_keyexpr_t _keyexpr; @@ -49,28 +53,33 @@ typedef struct { uint16_t _distance; } _ext_queryable_info; } _z_decl_queryable_t; -_z_decl_queryable_t _z_decl_queryable_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_decl_queryable_t _z_decl_queryable_null(void) { return (_z_decl_queryable_t){0}; } typedef struct { uint32_t _id; _z_keyexpr_t _ext_keyexpr; } _z_undecl_queryable_t; -_z_undecl_queryable_t _z_undecl_queryable_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_undecl_queryable_t _z_undecl_queryable_null(void) { return (_z_undecl_queryable_t){0}; } typedef struct { _z_keyexpr_t _keyexpr; uint32_t _id; } _z_decl_token_t; -_z_decl_token_t _z_decl_token_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_decl_token_t _z_decl_token_null(void) { return (_z_decl_token_t){0}; } typedef struct { uint32_t _id; _z_keyexpr_t _ext_keyexpr; } _z_undecl_token_t; -_z_undecl_token_t _z_undecl_token_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_undecl_token_t _z_undecl_token_null(void) { return (_z_undecl_token_t){0}; } typedef struct { bool _placeholder; // In case we add extensions } _z_decl_final_t; -_z_decl_final_t _z_decl_final_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_decl_final_t _z_decl_final_null(void) { return (_z_decl_final_t){0}; } typedef struct { enum { diff --git a/include/zenoh-pico/protocol/definitions/interest.h b/include/zenoh-pico/protocol/definitions/interest.h index ca2900874..8479f090f 100644 --- a/include/zenoh-pico/protocol/definitions/interest.h +++ b/include/zenoh-pico/protocol/definitions/interest.h @@ -36,10 +36,10 @@ typedef struct { uint32_t _id; uint8_t flags; } _z_interest_t; -_z_interest_t _z_interest_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_interest_t _z_interest_null(void) { return (_z_interest_t){0}; } void _z_interest_clear(_z_interest_t* decl); - _z_interest_t _z_make_interest(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, uint8_t flags); _z_interest_t _z_make_interest_final(uint32_t id); diff --git a/include/zenoh-pico/protocol/definitions/network.h b/include/zenoh-pico/protocol/definitions/network.h index f0cd40f01..476831765 100644 --- a/include/zenoh-pico/protocol/definitions/network.h +++ b/include/zenoh-pico/protocol/definitions/network.h @@ -149,7 +149,9 @@ _z_n_msg_request_exts_t _z_n_msg_request_needed_exts(const _z_n_msg_request_t *m void _z_n_msg_request_clear(_z_n_msg_request_t *msg); typedef _z_reply_body_t _z_push_body_t; -_z_push_body_t _z_push_body_null(void); +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_push_body_t _z_push_body_null(void) { return (_z_push_body_t){0}; } + _z_push_body_t _z_push_body_steal(_z_push_body_t *msg); void _z_push_body_clear(_z_push_body_t *msg); diff --git a/include/zenoh-pico/protocol/keyexpr.h b/include/zenoh-pico/protocol/keyexpr.h index f171ee32f..61a16e634 100644 --- a/include/zenoh-pico/protocol/keyexpr.h +++ b/include/zenoh-pico/protocol/keyexpr.h @@ -26,20 +26,25 @@ bool _z_keyexpr_suffix_intersects(const _z_keyexpr_t *left, const _z_keyexpr_t * bool _z_keyexpr_suffix_equals(const _z_keyexpr_t *left, const _z_keyexpr_t *right); /*------------------ clone/Copy/Free helpers ------------------*/ +// Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. +static inline _z_keyexpr_t _z_keyexpr_null(void) { return (_z_keyexpr_t){0}; } +static inline _z_keyexpr_t _z_keyexpr_alias(const _z_keyexpr_t src) { + return (_z_keyexpr_t){ + ._id = src._id, + ._mapping = src._mapping, + ._suffix = _z_string_alias(src._suffix), + }; +} + _z_keyexpr_t _z_keyexpr_from_string(uint16_t rid, _z_string_t *str); _z_keyexpr_t _z_keyexpr_from_substr(uint16_t rid, const char *str, size_t len); z_result_t _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src); -_z_keyexpr_t _z_keyexpr_duplicate(_z_keyexpr_t src); -_z_keyexpr_t _z_keyexpr_alias(_z_keyexpr_t src); +_z_keyexpr_t _z_keyexpr_duplicate(const _z_keyexpr_t *src); /// Returns either keyexpr defined by id + mapping with null suffix if try_declared is true and id is non-zero, /// or keyexpr defined by its suffix only, with 0 id and no mapping. This is to be used only when forwarding /// keyexpr in user api to properly separate declared keyexpr from its suffix. _z_keyexpr_t _z_keyexpr_alias_from_user_defined(_z_keyexpr_t src, bool try_declared); _z_keyexpr_t _z_keyexpr_steal(_Z_MOVE(_z_keyexpr_t) src); -static inline _z_keyexpr_t _z_keyexpr_null(void) { - _z_keyexpr_t keyexpr = {0, {0}, _z_string_null()}; - return keyexpr; -} bool _z_keyexpr_equals(const _z_keyexpr_t *left, const _z_keyexpr_t *right); void _z_keyexpr_move(_z_keyexpr_t *dst, _z_keyexpr_t *src); void _z_keyexpr_clear(_z_keyexpr_t *rk); diff --git a/src/api/api.c b/src/api/api.c index d5404d691..81f71d543 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -64,7 +64,7 @@ _z_string_svec_t _z_string_array_null(void) { return _z_string_svec_make(0); } void z_string_array_new(z_owned_string_array_t *a) { a->_val = _z_string_array_null(); } size_t z_string_array_push_by_alias(z_loaned_string_array_t *a, const z_loaned_string_t *value) { - _z_string_t str = _z_string_alias(value); + _z_string_t str = _z_string_alias(*value); _z_string_svec_append(a, &str); return _z_string_svec_len(a); @@ -130,7 +130,7 @@ void z_view_keyexpr_from_substr_unchecked(z_view_keyexpr_t *keyexpr, const char } z_result_t z_keyexpr_as_view_string(const z_loaned_keyexpr_t *keyexpr, z_view_string_t *s) { - s->_val = _z_string_alias(&keyexpr->_suffix); + s->_val = _z_string_alias(keyexpr->_suffix); return _Z_RES_OK; } @@ -829,11 +829,13 @@ z_result_t z_put(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr reliability); // Trigger local subscriptions +#if Z_FEATURE_LOCAL_SUBSCRIBER == 1 _z_trigger_local_subscriptions( _Z_RC_IN_VAL(zs), keyexpr_aliased, _z_bytes_from_owned_bytes(&payload->_this), opt.encoding == NULL ? NULL : &opt.encoding->_this._val, _z_n_qos_make(opt.is_express, opt.congestion_control == Z_CONGESTION_CONTROL_BLOCK, opt.priority), opt.timestamp, _z_bytes_from_owned_bytes(&opt.attachment->_this), reliability); +#endif // Clean-up z_encoding_drop(opt.encoding); z_bytes_drop(opt.attachment); @@ -962,10 +964,12 @@ z_result_t z_publisher_put(const z_loaned_publisher_t *pub, z_moved_bytes_t *pay _z_bytes_from_owned_bytes(&opt.attachment->_this), reliability); } // Trigger local subscriptions +#if Z_FEATURE_LOCAL_SUBSCRIBER == 1 _z_trigger_local_subscriptions( _Z_RC_IN_VAL(&sess_rc), pub_keyexpr, _z_bytes_from_owned_bytes(&payload->_this), &encoding, _z_n_qos_make(pub->_is_express, pub->_congestion_control == Z_CONGESTION_CONTROL_BLOCK, pub->_priority), opt.timestamp, _z_bytes_from_owned_bytes(&opt.attachment->_this), reliability); +#endif _z_session_rc_drop(&sess_rc); } else { diff --git a/src/collections/bytes.c b/src/collections/bytes.c index 698e4bb5a..e4328cd40 100644 --- a/src/collections/bytes.c +++ b/src/collections/bytes.c @@ -27,12 +27,6 @@ /*-------- Bytes --------*/ bool _z_bytes_check(const _z_bytes_t *bytes) { return !_z_bytes_is_empty(bytes); } -_z_bytes_t _z_bytes_null(void) { - _z_bytes_t b; - b._slices = _z_arc_slice_svec_make(0); - return b; -} - z_result_t _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src) { _z_arc_slice_svec_copy(&dst->_slices, &src->_slices); if (_z_arc_slice_svec_len(&dst->_slices) == _z_arc_slice_svec_len(&src->_slices)) { diff --git a/src/collections/slice.c b/src/collections/slice.c index c6fe1171a..76ffcf96e 100644 --- a/src/collections/slice.c +++ b/src/collections/slice.c @@ -28,14 +28,8 @@ void _z_default_deleter(void *data, void *context) { z_free(data); } -_z_delete_context_t _z_delete_context_null(void) { return _z_delete_context_create(NULL, NULL); } - bool _z_delete_context_is_null(const _z_delete_context_t *c) { return c->deleter == NULL; } -_z_delete_context_t _z_delete_context_create(void (*deleter)(void *data, void *context), void *context) { - return (_z_delete_context_t){.deleter = deleter, .context = context}; -} - _z_delete_context_t _z_delete_context_default(void) { return _z_delete_context_create(_z_default_deleter, NULL); } void _z_delete_context_delete(_z_delete_context_t *c, void *data) { @@ -45,27 +39,16 @@ void _z_delete_context_delete(_z_delete_context_t *c, void *data) { } /*-------- Slice --------*/ -_z_slice_t _z_slice_empty(void) { - return (_z_slice_t){.start = NULL, .len = 0, ._delete_context = _z_delete_context_null()}; -} - z_result_t _z_slice_init(_z_slice_t *bs, size_t capacity) { - z_result_t ret = _Z_RES_OK; - - bs->start = capacity == 0 ? NULL : (uint8_t *)z_malloc(capacity); - if (bs->start != NULL) { - bs->len = capacity; - bs->_delete_context = _z_delete_context_default(); - } else { + bs->start = (uint8_t *)z_malloc(capacity); + if (bs->start == NULL) { bs->len = 0; bs->_delete_context = _z_delete_context_null(); + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - - if (bs->len != capacity) { - ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - - return ret; + bs->len = capacity; + bs->_delete_context = _z_delete_context_default(); + return _Z_RES_OK; } _z_slice_t _z_slice_make(size_t capacity) { @@ -82,11 +65,6 @@ _z_slice_t _z_slice_from_buf_custom_deleter(const uint8_t *p, size_t len, _z_del return bs; } -_z_slice_t _z_slice_alias(const _z_slice_t *bs) { - _z_slice_t alias = {.len = bs->len, .start = bs->start, ._delete_context = _z_delete_context_null()}; - return alias; -} - _z_slice_t _z_slice_alias_buf(const uint8_t *p, size_t len) { return _z_slice_from_buf_custom_deleter(p, len, _z_delete_context_null()); } @@ -154,8 +132,6 @@ _z_slice_t _z_slice_duplicate(const _z_slice_t *src) { return dst; } -bool _z_slice_is_empty(const _z_slice_t *bs) { return bs->len == 0; } - _z_slice_t _z_slice_steal(_z_slice_t *b) { _z_slice_t ret = *b; *b = _z_slice_empty(); diff --git a/src/collections/string.c b/src/collections/string.c index 753c7cad5..a2545e767 100644 --- a/src/collections/string.c +++ b/src/collections/string.c @@ -17,16 +17,10 @@ #include #include +#include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/pointers.h" /*-------- string --------*/ -_z_string_t _z_string_null(void) { - _z_string_t s = {._slice = _z_slice_empty()}; - return s; -} - -bool _z_string_check(const _z_string_t *value) { return !_z_slice_is_empty(&value->_slice); } - _z_string_t _z_string_copy_from_str(const char *value) { _z_string_t s; s._slice = _z_slice_copy_from_buf((uint8_t *)value, strlen(value)); @@ -85,11 +79,6 @@ _z_string_t _z_string_steal(_z_string_t *str) { return ret; } -_z_string_t _z_string_alias(const _z_string_t *str) { - _z_string_t alias = {._slice = _z_slice_alias(&str->_slice)}; - return alias; -} - void _z_string_move_str(_z_string_t *dst, char *src) { *dst = _z_string_alias_str(src); } void _z_string_reset(_z_string_t *str) { _z_slice_reset(&str->_slice); } @@ -131,10 +120,10 @@ _z_string_t _z_string_convert_bytes(const _z_slice_t *bs) { } _z_string_t _z_string_preallocate(size_t len) { - _z_string_t s = _z_string_null(); - _z_slice_init(&s._slice, len); - if (_z_slice_is_empty(&s._slice)) { - return _z_string_null(); + _z_string_t s; + // As long as _z_string_t is only a slice, no need to do anything more + if (_z_slice_init(&s._slice, len) != _Z_RES_OK) { + _Z_ERROR("String allocation failed"); } return s; } diff --git a/src/net/encoding.c b/src/net/encoding.c index 5926f4657..f2fccb861 100644 --- a/src/net/encoding.c +++ b/src/net/encoding.c @@ -19,6 +19,11 @@ #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/result.h" +_z_encoding_t _z_encoding_wrap(uint16_t id, const char *schema) { + return (_z_encoding_t){.id = id, + .schema = (schema == NULL) ? _z_string_null() : _z_string_alias_str((char *)schema)}; +} + z_result_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *schema, size_t len) { encoding->id = id; // Clone schema @@ -33,19 +38,8 @@ z_result_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *sc return _Z_RES_OK; } -_z_encoding_t _z_encoding_wrap(uint16_t id, const char *schema) { - return (_z_encoding_t){.id = id, - .schema = (schema == NULL) ? _z_string_null() : _z_string_alias_str((char *)schema)}; -} - -_z_encoding_t _z_encoding_null(void) { return _z_encoding_wrap(_Z_ENCODING_ID_DEFAULT, NULL); } - void _z_encoding_clear(_z_encoding_t *encoding) { _z_string_clear(&encoding->schema); } -bool _z_encoding_check(const _z_encoding_t *encoding) { - return ((encoding->id != _Z_ENCODING_ID_DEFAULT) || _z_string_check(&encoding->schema)); -} - z_result_t _z_encoding_copy(_z_encoding_t *dst, const _z_encoding_t *src) { *dst = _z_encoding_null(); _Z_RETURN_IF_ERR(_z_string_copy(&dst->schema, &src->schema)); diff --git a/src/net/primitives.c b/src/net/primitives.c index b2b8d9d7d..96c0b919f 100644 --- a/src/net/primitives.c +++ b/src/net/primitives.c @@ -108,7 +108,7 @@ _z_publisher_t _z_declare_publisher(const _z_session_rc_t *zn, _z_keyexpr_t keye // Allocate publisher _z_publisher_t ret; // Fill publisher - ret._key = _z_keyexpr_duplicate(keyexpr); + ret._key = _z_keyexpr_duplicate(&keyexpr); ret._id = _z_get_entity_id(_Z_RC_IN_VAL(zn)); ret._congestion_control = congestion_control; ret._priority = priority; diff --git a/src/net/publish.c b/src/net/publish.c index d81893d0b..13900de39 100644 --- a/src/net/publish.c +++ b/src/net/publish.c @@ -35,17 +35,4 @@ void _z_publisher_free(_z_publisher_t **pub) { } } -bool _z_publisher_check(const _z_publisher_t *publisher) { return !_Z_RC_IS_NULL(&publisher->_zn); } -_z_publisher_t _z_publisher_null(void) { - return (_z_publisher_t){._congestion_control = Z_CONGESTION_CONTROL_DEFAULT, - ._id = 0, - ._key = _z_keyexpr_null(), - ._priority = Z_PRIORITY_DEFAULT, - ._zn = _z_session_weak_null(), - ._encoding = _z_encoding_null(), -#if Z_FEATURE_INTEREST == 1 - ._filter = (_z_write_filter_t){._interest_id = 0, .ctx = NULL} -#endif - }; -} #endif diff --git a/src/net/query.c b/src/net/query.c index 75bde3f41..9230c1dde 100644 --- a/src/net/query.c +++ b/src/net/query.c @@ -16,18 +16,6 @@ #include "zenoh-pico/session/utils.h" #include "zenoh-pico/utils/logging.h" -_z_query_t _z_query_null(void) { - return (_z_query_t){ - ._anyke = false, - ._key = _z_keyexpr_null(), - ._parameters = NULL, - ._request_id = 0, - ._value = _z_value_null(), - .attachment = _z_bytes_null(), - ._zn = _z_session_weak_null(), - }; -} - void _z_query_clear_inner(_z_query_t *q) { _z_keyexpr_clear(&q->_key); _z_value_clear(&q->_value); @@ -99,10 +87,6 @@ _z_query_t _z_query_create(_z_value_t *value, _z_keyexpr_t *key, const _z_slice_ return q; } -_z_queryable_t _z_queryable_null(void) { return (_z_queryable_t){._entity_id = 0, ._zn = _z_session_weak_null()}; } - -bool _z_queryable_check(const _z_queryable_t *queryable) { return !_Z_RC_IS_NULL(&queryable->_zn); } - void _z_queryable_clear(_z_queryable_t *qbl) { _z_session_weak_drop(&qbl->_zn); *qbl = _z_queryable_null(); diff --git a/src/net/reply.c b/src/net/reply.c index b9038af2e..a331ae6cf 100644 --- a/src/net/reply.c +++ b/src/net/reply.c @@ -17,15 +17,6 @@ #include "zenoh-pico/session/utils.h" #include "zenoh-pico/utils/logging.h" -_z_reply_data_t _z_reply_data_null(void) { - return (_z_reply_data_t){.replier_id = {.id = {0}}, ._result.sample = _z_sample_null(), ._tag = _Z_REPLY_TAG_NONE}; -} - -_z_reply_t _z_reply_null(void) { - _z_reply_t r = {.data = _z_reply_data_null()}; - return r; -} - #if Z_FEATURE_QUERY == 1 void _z_reply_data_clear(_z_reply_data_t *reply_data) { if (reply_data->_tag == _Z_REPLY_TAG_DATA) { @@ -48,14 +39,14 @@ void _z_reply_data_free(_z_reply_data_t **reply_data) { } z_result_t _z_reply_data_copy(_z_reply_data_t *dst, const _z_reply_data_t *src) { - *dst = _z_reply_data_null(); + *dst = _z_reply_data_init(); if (src->_tag == _Z_REPLY_TAG_DATA) { _Z_RETURN_IF_ERR(_z_sample_copy(&dst->_result.sample, &src->_result.sample)); } else if (src->_tag == _Z_REPLY_TAG_ERROR) { _Z_RETURN_IF_ERR(_z_value_copy(&dst->_result.error, &src->_result.error)); } - dst->replier_id = src->replier_id; dst->_tag = src->_tag; + dst->replier_id = src->replier_id; return _Z_RES_OK; } diff --git a/src/net/sample.c b/src/net/sample.c index 6248f57e5..042fbcd83 100644 --- a/src/net/sample.c +++ b/src/net/sample.c @@ -16,24 +16,6 @@ #include "zenoh-pico/session/utils.h" #include "zenoh-pico/utils/logging.h" -_z_sample_t _z_sample_null(void) { - _z_sample_t s = { - .keyexpr = _z_keyexpr_null(), - .payload = _z_bytes_null(), - .encoding = _z_encoding_null(), - .timestamp = _z_timestamp_null(), - .kind = 0, - .qos = {0}, - .attachment = _z_bytes_null(), - }; - return s; -} - -bool _z_sample_check(const _z_sample_t *sample) { - return _z_keyexpr_check(&sample->keyexpr) || _z_bytes_check(&sample->payload) || - _z_bytes_check(&sample->attachment) || _z_encoding_check(&sample->encoding); -} - void _z_sample_move(_z_sample_t *dst, _z_sample_t *src) { _z_keyexpr_move(&dst->keyexpr, &src->keyexpr); _z_bytes_move(&dst->payload, &src->payload); diff --git a/src/net/subscribe.c b/src/net/subscribe.c index 84960a0a2..12a83c6ac 100644 --- a/src/net/subscribe.c +++ b/src/net/subscribe.c @@ -31,7 +31,4 @@ void _z_subscriber_free(_z_subscriber_t **sub) { } } -bool _z_subscriber_check(const _z_subscriber_t *subscriber) { return !_Z_RC_IS_NULL(&subscriber->_zn); } -_z_subscriber_t _z_subscriber_null(void) { return (_z_subscriber_t){._entity_id = 0, ._zn = _z_session_weak_null()}; } - #endif diff --git a/src/protocol/core.c b/src/protocol/core.c index ed0479cc5..de0dbf517 100644 --- a/src/protocol/core.c +++ b/src/protocol/core.c @@ -66,11 +66,6 @@ _z_id_t _z_id_empty(void) { }}; } -_z_source_info_t _z_source_info_null(void) { - return (_z_source_info_t){._source_sn = 0, ._entity_id = 0, ._id = _z_id_empty()}; -} -_z_timestamp_t _z_timestamp_null(void) { return (_z_timestamp_t){.id = _z_id_empty(), .time = 0}; } - uint64_t _z_timestamp_ntp64_from_time(uint32_t seconds, uint32_t nanos) { const uint64_t FRAC_PER_SEC = (uint64_t)1 << 32; const uint64_t NANOS_PER_SEC = 1000000000; @@ -79,7 +74,6 @@ uint64_t _z_timestamp_ntp64_from_time(uint32_t seconds, uint32_t nanos) { return ((uint64_t)seconds << 32) | fractions; } -_z_value_t _z_value_null(void) { return (_z_value_t){.payload = _z_bytes_null(), .encoding = _z_encoding_null()}; } _z_value_t _z_value_steal(_z_value_t *value) { _z_value_t ret = *value; *value = _z_value_null(); @@ -101,10 +95,6 @@ z_result_t _z_hello_copy(_z_hello_t *dst, const _z_hello_t *src) { return _Z_RES_OK; } -_z_hello_t _z_hello_null(void) { - return (_z_hello_t){._zid = _z_id_empty(), ._version = 0, ._whatami = 0x0, ._locators = _z_string_svec_make(0)}; -} - void _z_value_move(_z_value_t *dst, _z_value_t *src) { _z_encoding_move(&dst->encoding, &src->encoding); _z_bytes_move(&dst->payload, &src->payload); diff --git a/src/protocol/definitions/declarations.c b/src/protocol/definitions/declarations.c index 878f14f6d..df693f2a1 100644 --- a/src/protocol/definitions/declarations.c +++ b/src/protocol/definitions/declarations.c @@ -71,7 +71,7 @@ _z_declaration_t _z_make_undecl_subscriber(uint32_t id, _Z_OPTIONAL const _z_key return (_z_declaration_t){ ._tag = _Z_UNDECL_SUBSCRIBER, ._body = {._undecl_subscriber = { - ._id = id, ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(*key)}}}; + ._id = id, ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(key)}}}; } _z_declaration_t _z_make_decl_queryable(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, bool complete, uint16_t distance) { @@ -85,7 +85,7 @@ _z_declaration_t _z_make_undecl_queryable(uint32_t id, _Z_OPTIONAL const _z_keye return (_z_declaration_t){ ._tag = _Z_UNDECL_QUERYABLE, ._body = {._undecl_queryable = { - ._id = id, ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(*key)}}}; + ._id = id, ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(key)}}}; } _z_declaration_t _z_make_decl_token(_Z_MOVE(_z_keyexpr_t) key, uint32_t id) { return (_z_declaration_t){._tag = _Z_DECL_TOKEN, @@ -98,22 +98,12 @@ _z_declaration_t _z_make_undecl_token(uint32_t id, _Z_OPTIONAL const _z_keyexpr_ return (_z_declaration_t){ ._tag = _Z_UNDECL_TOKEN, ._body = {._undecl_token = {._id = id, - ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(*key)}}}; + ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(key)}}}; } _z_declaration_t _z_make_decl_final(void) { return (_z_declaration_t){._tag = _Z_DECL_FINAL, ._body = {._decl_final = {0}}}; } -_z_decl_kexpr_t _z_decl_kexpr_null(void) { return (_z_decl_kexpr_t){0}; } -_z_decl_subscriber_t _z_decl_subscriber_null(void) { return (_z_decl_subscriber_t){0}; } -_z_decl_queryable_t _z_decl_queryable_null(void) { return (_z_decl_queryable_t){0}; } -_z_decl_token_t _z_decl_token_null(void) { return (_z_decl_token_t){0}; } -_z_undecl_kexpr_t _z_undecl_kexpr_null(void) { return (_z_undecl_kexpr_t){0}; } -_z_undecl_subscriber_t _z_undecl_subscriber_null(void) { return (_z_undecl_subscriber_t){0}; } -_z_undecl_queryable_t _z_undecl_queryable_null(void) { return (_z_undecl_queryable_t){0}; } -_z_undecl_token_t _z_undecl_token_null(void) { return (_z_undecl_token_t){0}; } -_z_decl_final_t _z_decl_final_null(void) { return (_z_decl_final_t){0}; } - void _z_decl_fix_mapping(_z_declaration_t *msg, uint16_t mapping) { switch (msg->_tag) { case _Z_DECL_KEXPR: { diff --git a/src/protocol/definitions/interest.c b/src/protocol/definitions/interest.c index 7c0254ee7..cfdc1795e 100644 --- a/src/protocol/definitions/interest.c +++ b/src/protocol/definitions/interest.c @@ -33,5 +33,3 @@ _z_interest_t _z_make_interest_final(uint32_t id) { .flags = 0, }; } - -_z_interest_t _z_interest_null(void) { return (_z_interest_t){0}; } diff --git a/src/protocol/definitions/network.c b/src/protocol/definitions/network.c index 177e0bc0a..10cb27cde 100644 --- a/src/protocol/definitions/network.c +++ b/src/protocol/definitions/network.c @@ -72,11 +72,6 @@ _z_push_body_t _z_push_body_steal(_z_push_body_t *msg) { *msg = _z_push_body_null(); return ret; } -_z_push_body_t _z_push_body_null(void) { - return (_z_push_body_t){ - ._is_put = false, - ._body._del._commons = {._timestamp = _z_timestamp_null(), ._source_info = _z_source_info_null()}}; -} void _z_n_msg_response_final_clear(_z_n_msg_response_final_t *msg) { (void)(msg); } diff --git a/src/protocol/keyexpr.c b/src/protocol/keyexpr.c index a097b2c40..f71e38875 100644 --- a/src/protocol/keyexpr.c +++ b/src/protocol/keyexpr.c @@ -36,7 +36,7 @@ _z_keyexpr_t _z_keyexpr_from_string(uint16_t rid, _z_string_t *str) { return (_z_keyexpr_t){ ._id = rid, ._mapping = _z_keyexpr_mapping(_Z_KEYEXPR_MAPPING_LOCAL), - ._suffix = (_z_string_check(str)) ? _z_string_alias(str) : _z_string_null(), + ._suffix = (_z_string_check(str)) ? _z_string_alias(*str) : _z_string_null(), }; } @@ -59,9 +59,9 @@ z_result_t _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src) { return _Z_RES_OK; } -_z_keyexpr_t _z_keyexpr_duplicate(_z_keyexpr_t src) { +_z_keyexpr_t _z_keyexpr_duplicate(const _z_keyexpr_t *src) { _z_keyexpr_t dst; - _z_keyexpr_copy(&dst, &src); + _z_keyexpr_copy(&dst, src); return dst; } @@ -106,15 +106,6 @@ bool _z_keyexpr_equals(const _z_keyexpr_t *left, const _z_keyexpr_t *right) { return _z_string_equals(&left->_suffix, &right->_suffix); } -_z_keyexpr_t _z_keyexpr_alias(_z_keyexpr_t src) { - _z_keyexpr_t alias = { - ._id = src._id, - ._mapping = src._mapping, - ._suffix = _z_string_alias(&src._suffix), - }; - return alias; -} - _z_keyexpr_t _z_keyexpr_alias_from_user_defined(_z_keyexpr_t src, bool try_declared) { if ((try_declared && src._id != Z_RESOURCE_ID_NONE) || !_z_keyexpr_has_suffix(&src)) { return (_z_keyexpr_t){ diff --git a/src/session/interest.c b/src/session/interest.c index a16884ee7..1467cf874 100644 --- a/src/session/interest.c +++ b/src/session/interest.c @@ -228,7 +228,7 @@ static _z_keyexpr_t _unsafe_z_get_key_from_declare(_z_session_t *zn, uint32_t id while (xs != NULL) { _z_declare_data_t *decl = _z_declare_data_list_head(xs); if (_z_declare_data_eq(&comp, decl)) { - return _z_keyexpr_duplicate(decl->_key); + return _z_keyexpr_duplicate(&decl->_key); } xs = _z_declare_data_list_tail(xs); } diff --git a/src/session/query.c b/src/session/query.c index 9515f47d3..f9546990f 100644 --- a/src/session/query.c +++ b/src/session/query.c @@ -148,7 +148,8 @@ z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, (void)memset(&partial_reply, 0, sizeof(_z_reply_t)); // Avoid warnings on uninitialized values on the reply partial_reply.data._tag = _Z_REPLY_TAG_DATA; - partial_reply.data._result.sample.keyexpr = _z_keyexpr_duplicate(reply.data._result.sample.keyexpr); + partial_reply.data._result.sample.keyexpr = + _z_keyexpr_duplicate(&reply.data._result.sample.keyexpr); pen_rep->_reply = partial_reply; } else { pen_rep->_reply = reply; // Store the whole reply in the latest mode diff --git a/src/session/resource.c b/src/session/resource.c index b573e600a..d90a53ca3 100644 --- a/src/session/resource.c +++ b/src/session/resource.c @@ -88,23 +88,28 @@ _z_resource_t *__z_get_resource_by_key(_z_resource_list_t *rl, const _z_keyexpr_ } _z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keyexpr_t *keyexpr) { - _z_keyexpr_t ret = {._id = Z_RESOURCE_ID_NONE, ._suffix = _z_string_null(), ._mapping = _z_keyexpr_mapping(0)}; + _z_zint_t id = keyexpr->_id; + + // Check if ke is already expanded + if (id == Z_RESOURCE_ID_NONE) { + if (!_z_keyexpr_has_suffix(keyexpr)) { + return _z_keyexpr_null(); + } + return _z_keyexpr_duplicate(keyexpr); + } // Need to build the complete resource name, by recursively look at RIDs // Resource names are looked up from right to left + _z_keyexpr_t ret = _z_keyexpr_null(); _z_string_list_t *strs = NULL; size_t len = 0; // Append suffix as the right-most segment if (_z_keyexpr_has_suffix(keyexpr)) { len = len + _z_string_len(&keyexpr->_suffix); - strs = _z_string_list_push(strs, (_z_string_t *)&keyexpr->_suffix); // Warning: list must be release with - // _z_list_free(&strs, _z_noop_free); - // or will release the suffix as well + strs = _z_string_list_push(strs, (_z_string_t *)&keyexpr->_suffix); } - // Recursively go through all the RIDs - _z_zint_t id = keyexpr->_id; uint16_t mapping = _z_keyexpr_mapping_id(keyexpr); while (id != Z_RESOURCE_ID_NONE) { _z_resource_t *res = __z_get_resource_by_id(xs, mapping, id); @@ -114,9 +119,7 @@ _z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keye } if (_z_keyexpr_has_suffix(&res->_key)) { len = len + _z_string_len(&res->_key._suffix); - strs = _z_string_list_push(strs, &res->_key._suffix); // Warning: list must be release with - // _z_list_free(&strs, _z_noop_free); - // or will release the suffix as well + strs = _z_string_list_push(strs, &res->_key._suffix); } id = res->_key._id; } @@ -136,6 +139,7 @@ _z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keye } } } + // Warning: list must be released with _z_list_free(&strs, _z_noop_free) or will release the suffix as well _z_list_free(&strs, _z_noop_free); return ret; } @@ -205,7 +209,6 @@ _z_keyexpr_t _z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t * /// Returns the ID of the registered keyexpr. Returns 0 if registration failed. uint16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, uint16_t register_to_mapping) { uint16_t ret = Z_RESOURCE_ID_NONE; - key = _z_keyexpr_alias(key); uint16_t mapping = register_to_mapping; uint16_t parent_mapping = _z_keyexpr_mapping_id(&key); @@ -226,7 +229,7 @@ uint16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, u ret = Z_RESOURCE_ID_NONE; } else { res->_refcount = 1; - res->_key = _z_keyexpr_duplicate(key); + res->_key = _z_keyexpr_duplicate(&key); ret = id == Z_RESOURCE_ID_NONE ? _z_get_resource_id(zn) : id; res->_id = ret; // Register the resource diff --git a/src/session/subscription.c b/src/session/subscription.c index b7bf19f26..1e0153f76 100644 --- a/src/session/subscription.c +++ b/src/session/subscription.c @@ -159,14 +159,18 @@ z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr _Z_DEBUG("Triggering subs for %d - %.*s", key._id, (int)_z_string_len(&key._suffix), _z_string_data(&key._suffix)); if (_z_keyexpr_has_suffix(&key)) { _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, &key); - _zp_session_unlock_mutex(zn); + // Check if there is subs + size_t sub_nb = _z_subscription_rc_list_len(subs); + if (sub_nb == 0) { + return _Z_RES_OK; + } // Build the sample _z_sample_t sample = _z_sample_create(&key, payload, timestamp, encoding, kind, qos, attachment, reliability); // Parse subscription list _z_subscription_rc_list_t *xs = subs; - _Z_DEBUG("Triggering %ju subs", (uintmax_t)_z_subscription_rc_list_len(xs)); + _Z_DEBUG("Triggering %ju subs", (uintmax_t)sub_nb); while (xs != NULL) { _z_subscription_rc_t *sub = _z_subscription_rc_list_head(xs); _Z_RC_IN_VAL(sub)->_callback(&sample, _Z_RC_IN_VAL(sub)->_arg); From 4bd2ca2f6fbb27704af4ffd33cadb47eb0cb8b67 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Mon, 14 Oct 2024 12:04:46 +0200 Subject: [PATCH 02/17] Improve throughput performance #2 (refcount focus) (#737) * feat: more static inline * feat: skip null string copy in encoding * feat: add no-weak refcount * feat: streamline vec_make * feat: add publisher check session config token * fix: simple rc memory leak * feat: switch arc_slice to simple rc * feat: add valid flag to timestamp * feat: add timestamp_move function * feat: switch sample_create to pass by reference * fix: missing token on publisher_delete * feat: update trigger subscription calls * fix: dummy sample_create prototype * feat: remove null timestamp value in trigger subs * feat: optimize timestamps cost * feat: check string before encoding move * feat: alias instead of copy payload on decode * doc: explicit read task errors * doc: rework transport/codec logs * feat: keep going on multicast message processing error * fix: revert payload aliasing * fix: set timestamp valid only if decode successful * fix: review comment --- CMakeLists.txt | 1 + include/zenoh-pico/collections/arc_slice.h | 12 +- include/zenoh-pico/collections/refcount.h | 98 +++++++++++++++-- include/zenoh-pico/collections/slice.h | 4 +- include/zenoh-pico/config.h | 1 + include/zenoh-pico/config.h.in | 1 + include/zenoh-pico/net/sample.h | 4 +- include/zenoh-pico/protocol/core.h | 4 +- include/zenoh-pico/session/subscription.h | 8 +- src/api/api.c | 66 +++++++---- src/collections/arc_slice.c | 22 +--- src/collections/refcount.c | 54 +++++++-- src/collections/slice.c | 8 -- src/collections/vec.c | 8 +- src/link/link.c | 13 +-- src/net/encoding.c | 11 +- src/net/sample.c | 19 ++-- src/protocol/codec.c | 12 +- src/protocol/codec/declarations.c | 3 + src/protocol/codec/message.c | 7 +- src/protocol/codec/network.c | 5 + src/protocol/codec/transport.c | 2 + src/session/push.c | 8 +- src/session/rx.c | 9 +- src/session/scout.c | 2 +- src/session/subscription.c | 18 +-- src/session/utils.c | 14 +-- src/transport/multicast/read.c | 4 +- src/transport/multicast/rx.c | 8 +- src/transport/multicast/transport.c | 2 +- src/transport/raweth/read.c | 6 +- src/transport/unicast/read.c | 3 +- src/transport/unicast/rx.c | 6 +- src/transport/unicast/transport.c | 8 +- tests/z_msgcodec_test.c | 1 + tests/z_refcount_test.c | 121 ++++++++++++++++++++- 36 files changed, 410 insertions(+), 163 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd03262b2..7949110a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,6 +205,7 @@ set(Z_FEATURE_UNICAST_TRANSPORT 1 CACHE STRING "Toggle unicast transport") set(Z_FEATURE_RAWETH_TRANSPORT 0 CACHE STRING "Toggle raw ethernet transport") set(Z_FEATURE_TCP_NODELAY 1 CACHE STRING "Toggle TCP_NODELAY") set(Z_FEATURE_LOCAL_SUBSCRIBER 0 CACHE STRING "Toggle local subscriptions") +set(Z_FEATURE_PUBLISHER_SESSION_CHECK 1 CACHE STRING "Toggle publisher session check") add_compile_definitions("Z_BUILD_DEBUG=$") message(STATUS "Building with feature confing:\n\ diff --git a/include/zenoh-pico/collections/arc_slice.h b/include/zenoh-pico/collections/arc_slice.h index ce67d2975..f74d9f969 100644 --- a/include/zenoh-pico/collections/arc_slice.h +++ b/include/zenoh-pico/collections/arc_slice.h @@ -24,29 +24,29 @@ #include "slice.h" #include "zenoh-pico/system/platform_common.h" -_Z_REFCOUNT_DEFINE(_z_slice, _z_slice) +_Z_SIMPLE_REFCOUNT_DEFINE(_z_slice, _z_slice) /*-------- ArcSlice --------*/ /** * An atomically reference counted subslice. * * Members: - * _z_slice_rc_t len: Rc counted slice. + * _z_slice_simple_rc_t len: Rc counted slice. * size_t start: Offset to the subslice start. * size_t len: Length of the subslice. */ typedef struct { - _z_slice_rc_t slice; + _z_slice_simple_rc_t slice; size_t start; size_t len; } _z_arc_slice_t; -_z_arc_slice_t _z_arc_slice_empty(void); +static inline _z_arc_slice_t _z_arc_slice_empty(void) { return (_z_arc_slice_t){0}; } +static inline size_t _z_arc_slice_len(const _z_arc_slice_t* s) { return s->len; } +static inline bool _z_arc_slice_is_empty(const _z_arc_slice_t* s) { return _z_arc_slice_len(s) == 0; } _z_arc_slice_t _z_arc_slice_wrap(_z_slice_t s, size_t offset, size_t len); _z_arc_slice_t _z_arc_slice_get_subslice(const _z_arc_slice_t* s, size_t offset, size_t len); -size_t _z_arc_slice_len(const _z_arc_slice_t* s); -bool _z_arc_slice_is_empty(const _z_arc_slice_t* s); const uint8_t* _z_arc_slice_data(const _z_arc_slice_t* s); z_result_t _z_arc_slice_copy(_z_arc_slice_t* dst, const _z_arc_slice_t* src); z_result_t _z_arc_slice_move(_z_arc_slice_t* dst, _z_arc_slice_t* src); diff --git a/include/zenoh-pico/collections/refcount.h b/include/zenoh-pico/collections/refcount.h index 099ab04ae..644d167f9 100644 --- a/include/zenoh-pico/collections/refcount.h +++ b/include/zenoh-pico/collections/refcount.h @@ -34,6 +34,12 @@ z_result_t _z_rc_weak_upgrade(void *cnt); size_t _z_rc_weak_count(void *cnt); size_t _z_rc_strong_count(void *cnt); +z_result_t _z_simple_rc_init(void **cnt); +z_result_t _z_simple_rc_increase(void *cnt); +bool _z_simple_rc_decrease(void **cnt); + +size_t _z_simple_rc_strong_count(void *cnt); + /*------------------ Internal Array Macros ------------------*/ #define _Z_REFCOUNT_DEFINE(name, type) \ typedef struct name##_rc_t { \ @@ -46,18 +52,8 @@ size_t _z_rc_strong_count(void *cnt); void *_cnt; \ } name##_weak_t; \ \ - static inline name##_rc_t name##_rc_null(void) { \ - name##_rc_t p; \ - p._val = NULL; \ - p._cnt = NULL; \ - return p; \ - } \ - static inline name##_weak_t name##_weak_null(void) { \ - name##_weak_t p; \ - p._val = NULL; \ - p._cnt = NULL; \ - return p; \ - } \ + static inline name##_rc_t name##_rc_null(void) { return (name##_rc_t){0}; } \ + static inline name##_weak_t name##_weak_null(void) { return (name##_weak_t){0}; } \ \ static inline name##_rc_t name##_rc_new(type##_t *val) { \ name##_rc_t p = name##_rc_null(); \ @@ -175,6 +171,84 @@ size_t _z_rc_strong_count(void *cnt); return sizeof(name##_rc_t); \ } +#define _Z_SIMPLE_REFCOUNT_DEFINE(name, type) \ + typedef struct name##_simple_rc_t { \ + type##_t *_val; \ + void *_cnt; \ + } name##_simple_rc_t; \ + \ + static inline name##_simple_rc_t name##_simple_rc_null(void) { return (name##_simple_rc_t){0}; } \ + \ + static inline name##_simple_rc_t name##_simple_rc_new(type##_t *val) { \ + name##_simple_rc_t p = name##_simple_rc_null(); \ + if (_z_simple_rc_init(&p._cnt) == _Z_RES_OK) { \ + p._val = val; \ + } \ + return p; \ + } \ + static inline name##_simple_rc_t name##_simple_rc_new_from_val(const type##_t *val) { \ + type##_t *v = (type##_t *)z_malloc(sizeof(type##_t)); \ + if (v == NULL) { \ + return name##_simple_rc_null(); \ + } \ + *v = *val; \ + name##_simple_rc_t p = name##_simple_rc_new(v); \ + if (p._cnt == NULL) { \ + z_free(v); \ + return name##_simple_rc_null(); \ + } \ + return p; \ + } \ + static inline name##_simple_rc_t name##_simple_rc_clone(const name##_simple_rc_t *p) { \ + name##_simple_rc_t c = name##_simple_rc_null(); \ + if (_z_simple_rc_increase(p->_cnt) == _Z_RES_OK) { \ + c = *p; \ + } \ + return c; \ + } \ + static inline name##_simple_rc_t *name##_simple_rc_clone_as_ptr(const name##_simple_rc_t *p) { \ + name##_simple_rc_t *c = (name##_simple_rc_t *)z_malloc(sizeof(name##_simple_rc_t)); \ + if (c != NULL) { \ + *c = name##_simple_rc_clone(p); \ + if (c->_cnt == NULL) { \ + z_free(c); \ + } \ + } \ + return c; \ + } \ + static inline void name##_simple_rc_copy(name##_simple_rc_t *dst, const name##_simple_rc_t *p) { \ + *dst = name##_simple_rc_clone(p); \ + } \ + static inline bool name##_simple_rc_eq(const name##_simple_rc_t *left, const name##_simple_rc_t *right) { \ + return (left->_val == right->_val); \ + } \ + static inline bool name##_simple_rc_decr(name##_simple_rc_t *p) { \ + if ((p == NULL) || (p->_cnt == NULL)) { \ + return false; \ + } \ + if (_z_simple_rc_decrease(&p->_cnt)) { \ + return true; \ + } \ + return false; \ + } \ + static inline bool name##_simple_rc_drop(name##_simple_rc_t *p) { \ + if (p == NULL) { \ + return false; \ + } \ + bool res = false; \ + if (name##_simple_rc_decr(p) && p->_val != NULL) { \ + type##_clear(p->_val); \ + z_free(p->_val); \ + res = true; \ + } \ + *p = name##_simple_rc_null(); \ + return res; \ + } \ + static inline size_t name##_simple_rc_size(name##_simple_rc_t *p) { \ + _ZP_UNUSED(p); \ + return sizeof(name##_simple_rc_t); \ + } + #ifdef __cplusplus } #endif diff --git a/include/zenoh-pico/collections/slice.h b/include/zenoh-pico/collections/slice.h index b6b6f45a5..00101c185 100644 --- a/include/zenoh-pico/collections/slice.h +++ b/include/zenoh-pico/collections/slice.h @@ -32,7 +32,7 @@ static inline _z_delete_context_t _z_delete_context_null(void) { return (_z_dele static inline _z_delete_context_t _z_delete_context_create(void (*deleter)(void *context, void *data), void *context) { return (_z_delete_context_t){.deleter = deleter, .context = context}; } -bool _z_delete_context_is_null(const _z_delete_context_t *c); +static inline bool _z_delete_context_is_null(const _z_delete_context_t *c) { return c->deleter == NULL; } _z_delete_context_t _z_delete_context_default(void); void _z_delete_context_delete(_z_delete_context_t *c, void *data); @@ -52,6 +52,7 @@ typedef struct { } _z_slice_t; static inline _z_slice_t _z_slice_empty(void) { return (_z_slice_t){0}; } +static inline void _z_slice_reset(_z_slice_t *bs) { *bs = _z_slice_empty(); } static inline bool _z_slice_is_empty(const _z_slice_t *bs) { return bs->len == 0; } static inline bool _z_slice_check(const _z_slice_t *slice) { return slice->start != NULL; } static inline _z_slice_t _z_slice_alias(const _z_slice_t bs) { @@ -67,7 +68,6 @@ z_result_t _z_slice_copy(_z_slice_t *dst, const _z_slice_t *src); z_result_t _z_slice_n_copy(_z_slice_t *dst, const _z_slice_t *src, size_t offset, size_t len); _z_slice_t _z_slice_duplicate(const _z_slice_t *src); void _z_slice_move(_z_slice_t *dst, _z_slice_t *src); -void _z_slice_reset(_z_slice_t *bs); bool _z_slice_eq(const _z_slice_t *left, const _z_slice_t *right); void _z_slice_clear(_z_slice_t *bs); void _z_slice_free(_z_slice_t **bs); diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index 8ee4cf966..aadb2aae7 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -43,6 +43,7 @@ #define Z_FEATURE_ENCODING_VALUES 1 #define Z_FEATURE_TCP_NODELAY 1 #define Z_FEATURE_LOCAL_SUBSCRIBER 0 +#define Z_FEATURE_PUBLISHER_SESSION_CHECK 1 // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/include/zenoh-pico/config.h.in b/include/zenoh-pico/config.h.in index 74ac25194..062931aad 100644 --- a/include/zenoh-pico/config.h.in +++ b/include/zenoh-pico/config.h.in @@ -43,6 +43,7 @@ #define Z_FEATURE_ENCODING_VALUES @Z_FEATURE_ENCODING_VALUES@ #define Z_FEATURE_TCP_NODELAY @Z_FEATURE_TCP_NODELAY@ #define Z_FEATURE_LOCAL_SUBSCRIBER @Z_FEATURE_LOCAL_SUBSCRIBER@ +#define Z_FEATURE_PUBLISHER_SESSION_CHECK @Z_FEATURE_PUBLISHER_SESSION_CHECK@ // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/include/zenoh-pico/net/sample.h b/include/zenoh-pico/net/sample.h index 213e1eaa1..0b7eeb43f 100644 --- a/include/zenoh-pico/net/sample.h +++ b/include/zenoh-pico/net/sample.h @@ -59,8 +59,8 @@ void _z_sample_free(_z_sample_t **sample); z_result_t _z_sample_copy(_z_sample_t *dst, const _z_sample_t *src); _z_sample_t _z_sample_duplicate(const _z_sample_t *src); -_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t payload, const _z_timestamp_t *timestamp, +_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t *payload, const _z_timestamp_t *timestamp, _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, - const _z_bytes_t attachment, z_reliability_t reliability); + const _z_bytes_t *attachment, z_reliability_t reliability); #endif /* ZENOH_PICO_SAMPLE_NETAPI_H */ diff --git a/include/zenoh-pico/protocol/core.h b/include/zenoh-pico/protocol/core.h index d5f85299a..34970275f 100644 --- a/include/zenoh-pico/protocol/core.h +++ b/include/zenoh-pico/protocol/core.h @@ -62,15 +62,17 @@ _z_id_t _z_id_empty(void); * A zenoh timestamp. */ typedef struct { + bool valid; _z_id_t id; uint64_t time; } _z_timestamp_t; // Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. static inline _z_timestamp_t _z_timestamp_null(void) { return (_z_timestamp_t){0}; } +static inline bool _z_timestamp_check(const _z_timestamp_t *stamp) { return stamp->valid; } _z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp); void _z_timestamp_clear(_z_timestamp_t *tstamp); -bool _z_timestamp_check(const _z_timestamp_t *stamp); +void _z_timestamp_move(_z_timestamp_t *dst, _z_timestamp_t *src); uint64_t _z_timestamp_ntp64_from_time(uint32_t seconds, uint32_t nanos); /** diff --git a/include/zenoh-pico/session/subscription.h b/include/zenoh-pico/session/subscription.h index dd48ecb83..f47df8c41 100644 --- a/include/zenoh-pico/session/subscription.h +++ b/include/zenoh-pico/session/subscription.h @@ -19,18 +19,18 @@ #include "zenoh-pico/net/session.h" /*------------------ Subscription ------------------*/ -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, const _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - const _z_bytes_t attachment, z_reliability_t reliability); + const _z_bytes_t *attachment, z_reliability_t reliability); #if Z_FEATURE_SUBSCRIPTION == 1 _z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id); _z_subscription_rc_list_t *_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr); _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_t *sub); -z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, +z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, const _z_bytes_t *payload, _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, - const _z_n_qos_t qos, const _z_bytes_t attachment, z_reliability_t reliability); + const _z_n_qos_t qos, const _z_bytes_t *attachment, z_reliability_t reliability); void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub); void _z_flush_subscriptions(_z_session_t *zn); #endif diff --git a/src/api/api.c b/src/api/api.c index 81f71d543..6df2c10ad 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -385,6 +385,7 @@ z_result_t z_timestamp_new(z_timestamp_t *ts, const z_loaned_session_t *zs) { *ts = _z_timestamp_null(); _z_time_since_epoch t; _Z_RETURN_IF_ERR(_z_get_time_since_epoch(&t)); + ts->valid = true; ts->time = _z_timestamp_ntp64_from_time(t.secs, t.nanos); ts->id = _Z_RC_IN_VAL(zs)->_local_zid; return _Z_RES_OK; @@ -822,19 +823,20 @@ z_result_t z_put(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr reliability = opt.reliability; #endif + _z_bytes_t payload_bytes = _z_bytes_from_owned_bytes(&payload->_this); + _z_bytes_t attachment_bytes = _z_bytes_from_owned_bytes(&opt.attachment->_this); _z_keyexpr_t keyexpr_aliased = _z_keyexpr_alias_from_user_defined(*keyexpr, true); - ret = _z_write(_Z_RC_IN_VAL(zs), keyexpr_aliased, _z_bytes_from_owned_bytes(&payload->_this), + ret = _z_write(_Z_RC_IN_VAL(zs), keyexpr_aliased, payload_bytes, opt.encoding == NULL ? NULL : &opt.encoding->_this._val, Z_SAMPLE_KIND_PUT, opt.congestion_control, - opt.priority, opt.is_express, opt.timestamp, _z_bytes_from_owned_bytes(&opt.attachment->_this), - reliability); + opt.priority, opt.is_express, opt.timestamp, attachment_bytes, reliability); // Trigger local subscriptions #if Z_FEATURE_LOCAL_SUBSCRIBER == 1 + _z_timestamp_t local_timestamp = ((opt.timestamp != NULL) ? *opt.timestamp : _z_timestamp_null()); _z_trigger_local_subscriptions( - _Z_RC_IN_VAL(zs), keyexpr_aliased, _z_bytes_from_owned_bytes(&payload->_this), - opt.encoding == NULL ? NULL : &opt.encoding->_this._val, + _Z_RC_IN_VAL(zs), &keyexpr_aliased, &payload_bytes, opt.encoding == NULL ? NULL : &opt.encoding->_this._val, _z_n_qos_make(opt.is_express, opt.congestion_control == Z_CONGESTION_CONTROL_BLOCK, opt.priority), - opt.timestamp, _z_bytes_from_owned_bytes(&opt.attachment->_this), reliability); + &local_timestamp, &attachment_bytes, reliability); #endif // Clean-up z_encoding_drop(opt.encoding); @@ -952,30 +954,43 @@ z_result_t z_publisher_put(const z_loaned_publisher_t *pub, z_moved_bytes_t *pay // Remove potentially redundant ke suffix _z_keyexpr_t pub_keyexpr = _z_keyexpr_alias_from_user_defined(pub->_key, true); + _z_session_t *session = NULL; +#if Z_FEATURE_PUBLISHER_SESSION_CHECK == 1 // Try to upgrade session rc _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&pub->_zn); - if (!_Z_RC_IS_NULL(&sess_rc)) { + session = _Z_RC_IN_VAL(&sess_rc); + } else { + ret = _Z_ERR_SESSION_CLOSED; + } +#else + session = _Z_RC_IN_VAL(&pub->_zn); +#endif + + if (session != NULL) { + _z_bytes_t payload_bytes = _z_bytes_from_owned_bytes(&payload->_this); + _z_bytes_t attachment_bytes = _z_bytes_from_owned_bytes(&opt.attachment->_this); + // Check if write filter is active before writing if (!_z_write_filter_active(pub)) { // Write value - ret = _z_write(_Z_RC_IN_VAL(&sess_rc), pub_keyexpr, _z_bytes_from_owned_bytes(&payload->_this), &encoding, - Z_SAMPLE_KIND_PUT, pub->_congestion_control, pub->_priority, pub->_is_express, opt.timestamp, - _z_bytes_from_owned_bytes(&opt.attachment->_this), reliability); + ret = _z_write(session, pub_keyexpr, payload_bytes, &encoding, Z_SAMPLE_KIND_PUT, pub->_congestion_control, + pub->_priority, pub->_is_express, opt.timestamp, attachment_bytes, reliability); } // Trigger local subscriptions #if Z_FEATURE_LOCAL_SUBSCRIBER == 1 + _z_timestamp_t local_timestamp = ((opt.timestamp != NULL) ? *opt.timestamp : _z_timestamp_null()); _z_trigger_local_subscriptions( - _Z_RC_IN_VAL(&sess_rc), pub_keyexpr, _z_bytes_from_owned_bytes(&payload->_this), &encoding, + session, &pub_keyexpr, &payload_bytes, &encoding, _z_n_qos_make(pub->_is_express, pub->_congestion_control == Z_CONGESTION_CONTROL_BLOCK, pub->_priority), - opt.timestamp, _z_bytes_from_owned_bytes(&opt.attachment->_this), reliability); + &local_timestamp, &attachment_bytes, reliability); #endif - - _z_session_rc_drop(&sess_rc); - } else { - ret = _Z_ERR_SESSION_CLOSED; } +#if Z_FEATURE_PUBLISHER_SESSION_CHECK == 1 + _z_session_rc_drop(&sess_rc); +#endif + // Clean-up _z_encoding_clear(&encoding); z_bytes_drop(opt.attachment); @@ -997,16 +1012,27 @@ z_result_t z_publisher_delete(const z_loaned_publisher_t *pub, const z_publisher // Remove potentially redundant ke suffix _z_keyexpr_t pub_keyexpr = _z_keyexpr_alias_from_user_defined(pub->_key, true); + _z_session_t *session = NULL; +#if Z_FEATURE_PUBLISHER_SESSION_CHECK == 1 // Try to upgrade session rc _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&pub->_zn); - if (_Z_RC_IS_NULL(&sess_rc)) { + if (!_Z_RC_IS_NULL(&sess_rc)) { + session = _Z_RC_IN_VAL(&sess_rc); + } else { return _Z_ERR_SESSION_CLOSED; } - z_result_t ret = _z_write(_Z_RC_IN_VAL(&sess_rc), pub_keyexpr, _z_bytes_null(), NULL, Z_SAMPLE_KIND_DELETE, - pub->_congestion_control, pub->_priority, pub->_is_express, opt.timestamp, - _z_bytes_null(), reliability); +#else + session = _Z_RC_IN_VAL(&pub->_zn); +#endif + + z_result_t ret = + _z_write(session, pub_keyexpr, _z_bytes_null(), NULL, Z_SAMPLE_KIND_DELETE, pub->_congestion_control, + pub->_priority, pub->_is_express, opt.timestamp, _z_bytes_null(), reliability); + +#if Z_FEATURE_PUBLISHER_SESSION_CHECK == 1 // Clean up _z_session_rc_drop(&sess_rc); +#endif return ret; } diff --git a/src/collections/arc_slice.c b/src/collections/arc_slice.c index 01f7d8038..9c5f6c824 100644 --- a/src/collections/arc_slice.c +++ b/src/collections/arc_slice.c @@ -19,19 +19,11 @@ #include #include -_z_arc_slice_t _z_arc_slice_empty(void) { - _z_arc_slice_t s; - s.len = 0; - s.start = 0; - s.slice = _z_slice_rc_null(); - return s; -} - _z_arc_slice_t _z_arc_slice_wrap(_z_slice_t s, size_t offset, size_t len) { assert(offset + len <= s.len); _z_arc_slice_t arc_s; - arc_s.slice = _z_slice_rc_new_from_val(&s); + arc_s.slice = _z_slice_simple_rc_new_from_val(&s); if (_Z_RC_IS_NULL(&arc_s.slice)) { return _z_arc_slice_empty(); } @@ -48,20 +40,16 @@ _z_arc_slice_t _z_arc_slice_get_subslice(const _z_arc_slice_t* s, size_t offset, return _z_arc_slice_empty(); } _z_arc_slice_t out; - out.slice = _z_slice_rc_clone(&s->slice); + out.slice = _z_slice_simple_rc_clone(&s->slice); out.len = len; out.start = s->start + offset; return out; } -size_t _z_arc_slice_len(const _z_arc_slice_t* s) { return s->len; } - -bool _z_arc_slice_is_empty(const _z_arc_slice_t* s) { return _z_arc_slice_len(s) == 0; } - const uint8_t* _z_arc_slice_data(const _z_arc_slice_t* s) { return _Z_RC_IN_VAL(&s->slice)->start + s->start; } z_result_t _z_arc_slice_copy(_z_arc_slice_t* dst, const _z_arc_slice_t* src) { - _z_slice_rc_copy(&dst->slice, &src->slice); + _z_slice_simple_rc_copy(&dst->slice, &src->slice); dst->len = src->len; dst->start = src->start; return _Z_RES_OK; @@ -73,12 +61,12 @@ z_result_t _z_arc_slice_move(_z_arc_slice_t* dst, _z_arc_slice_t* src) { dst->start = src->start; src->len = 0; src->start = 0; - src->slice = _z_slice_rc_null(); + src->slice = _z_slice_simple_rc_null(); return _Z_RES_OK; } z_result_t _z_arc_slice_drop(_z_arc_slice_t* s) { - _z_slice_rc_drop(&s->slice); + _z_slice_simple_rc_drop(&s->slice); *s = _z_arc_slice_empty(); return _Z_RES_OK; } diff --git a/src/collections/refcount.c b/src/collections/refcount.c index 608548fae..be417fe02 100644 --- a/src/collections/refcount.c +++ b/src/collections/refcount.c @@ -49,9 +49,9 @@ // c11 atomic variant #define _ZP_RC_CNT_TYPE _z_atomic(unsigned int) -#define _ZP_RC_OP_INIT_CNT(p) \ - _z_atomic_store_explicit(&(p)->_strong_cnt, (unsigned int)1, _z_memory_order_relaxed); \ - _z_atomic_store_explicit(&(p)->_weak_cnt, (unsigned int)1, _z_memory_order_relaxed); +#define _ZP_RC_OP_INIT_STRONG_CNT(p) \ + _z_atomic_store_explicit(&(p)->_strong_cnt, (unsigned int)1, _z_memory_order_relaxed); +#define _ZP_RC_OP_INIT_WEAK_CNT(p) _z_atomic_store_explicit(&(p)->_weak_cnt, (unsigned int)1, _z_memory_order_relaxed); #define _ZP_RC_OP_INCR_STRONG_CNT(p) \ _z_atomic_fetch_add_explicit(&(p)->_strong_cnt, (unsigned int)1, _z_memory_order_relaxed); #define _ZP_RC_OP_INCR_AND_CMP_WEAK(p, x) \ @@ -83,10 +83,11 @@ // c99 gcc sync builtin variant #define _ZP_RC_CNT_TYPE unsigned int -#define _ZP_RC_OP_INIT_CNT(p) \ +#define _ZP_RC_OP_INIT_STRONG_CNT(p) \ __sync_fetch_and_and(&(p)->_strong_cnt, (unsigned int)0); \ - __sync_fetch_and_add(&(p)->_strong_cnt, (unsigned int)1); \ - __sync_fetch_and_and(&(p)->_weak_cnt, (unsigned int)0); \ + __sync_fetch_and_add(&(p)->_strong_cnt, (unsigned int)1); +#define _ZP_RC_OP_INIT_WEAK_CNT(p) \ + __sync_fetch_and_and(&(p)->_weak_cnt, (unsigned int)0); \ __sync_fetch_and_add(&(p)->_weak_cnt, (unsigned int)1); #define _ZP_RC_OP_INCR_STRONG_CNT(p) __sync_fetch_and_add(&(p)->_strong_cnt, (unsigned int)1); #define _ZP_RC_OP_INCR_AND_CMP_WEAK(p, x) __sync_fetch_and_add(&(p)->_weak_cnt, (unsigned int)1) >= x @@ -117,7 +118,8 @@ // None variant #error "Multi-thread refcount in C99 only exists for GCC, use GCC or C11 or deactivate multi-thread" #define _ZP_RC_CNT_TYPE unsigned int -#define _ZP_RC_OP_INIT_CNT(p) +#define _ZP_RC_OP_INIT_STRONG_CNT(p) +#define _ZP_RC_OP_INIT_WEAK_CNT(p) #define _ZP_RC_OP_INCR_STRONG_CNT(p) #define _ZP_RC_OP_INCR_AND_CMP_WEAK(p, x) (x == 0) #define _ZP_RC_OP_DECR_AND_CMP_STRONG(p, x) (x == 0) @@ -136,9 +138,8 @@ // Single thread variant #define _ZP_RC_CNT_TYPE unsigned int -#define _ZP_RC_OP_INIT_CNT(p) \ - (p)->_strong_cnt = (unsigned int)1; \ - (p)->_weak_cnt = (unsigned int)1; +#define _ZP_RC_OP_INIT_STRONG_CNT(p) (p)->_strong_cnt = (unsigned int)1; +#define _ZP_RC_OP_INIT_WEAK_CNT(p) (p)->_weak_cnt = (unsigned int)1; #define _ZP_RC_OP_INCR_STRONG_CNT(p) p->_strong_cnt++; #define _ZP_RC_OP_INCR_AND_CMP_WEAK(p, x) p->_weak_cnt++ >= x #define _ZP_RC_OP_DECR_AND_CMP_STRONG(p, x) p->_strong_cnt-- > (unsigned int)x @@ -170,7 +171,8 @@ z_result_t _z_rc_init(void** cnt) { if ((*cnt) == NULL) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - _ZP_RC_OP_INIT_CNT((_z_inner_rc_t*)*cnt) + _ZP_RC_OP_INIT_STRONG_CNT((_z_inner_rc_t*)*cnt) + _ZP_RC_OP_INIT_WEAK_CNT((_z_inner_rc_t*)*cnt) return _Z_RES_OK; } @@ -219,3 +221,33 @@ z_result_t _z_rc_weak_upgrade(void* cnt) { return _upgrade((_z_inner_rc_t*)cnt); size_t _z_rc_weak_count(void* cnt) { return ((_z_inner_rc_t*)cnt)->_weak_cnt; } size_t _z_rc_strong_count(void* cnt) { return ((_z_inner_rc_t*)cnt)->_strong_cnt; } + +typedef struct { + _ZP_RC_CNT_TYPE _strong_cnt; +} _z_inner_simple_rc_t; + +z_result_t _z_simple_rc_init(void** cnt) { + *cnt = z_malloc(sizeof(_z_inner_simple_rc_t)); + if ((*cnt) == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + _ZP_RC_OP_INIT_STRONG_CNT((_z_inner_simple_rc_t*)*cnt) + return _Z_RES_OK; +} + +z_result_t _z_simple_rc_increase(void* cnt) { + _z_inner_simple_rc_t* c = (_z_inner_simple_rc_t*)cnt; + _ZP_RC_OP_INCR_STRONG_CNT(c); + return _Z_RES_OK; +} + +bool _z_simple_rc_decrease(void** cnt) { + _z_inner_simple_rc_t* c = (_z_inner_simple_rc_t*)*cnt; + if (_ZP_RC_OP_DECR_AND_CMP_STRONG(c, 1)) { + return false; + } + z_free(*cnt); + return true; +} + +size_t _z_simple_rc_strong_count(void* cnt) { return ((_z_inner_simple_rc_t*)cnt)->_strong_cnt; } diff --git a/src/collections/slice.c b/src/collections/slice.c index 76ffcf96e..5c9116ea7 100644 --- a/src/collections/slice.c +++ b/src/collections/slice.c @@ -28,8 +28,6 @@ void _z_default_deleter(void *data, void *context) { z_free(data); } -bool _z_delete_context_is_null(const _z_delete_context_t *c) { return c->deleter == NULL; } - _z_delete_context_t _z_delete_context_default(void) { return _z_delete_context_create(_z_default_deleter, NULL); } void _z_delete_context_delete(_z_delete_context_t *c, void *data) { @@ -74,12 +72,6 @@ _z_slice_t _z_slice_copy_from_buf(const uint8_t *p, size_t len) { return _z_slice_duplicate(&bs); } -void _z_slice_reset(_z_slice_t *bs) { - bs->start = NULL; - bs->len = 0; - bs->_delete_context = _z_delete_context_null(); -} - void _z_slice_clear(_z_slice_t *bs) { if ((bs->start != NULL)) { _z_delete_context_delete(&bs->_delete_context, (void *)bs->start); diff --git a/src/collections/vec.c b/src/collections/vec.c index 6556d6b88..da5fca7f0 100644 --- a/src/collections/vec.c +++ b/src/collections/vec.c @@ -20,12 +20,12 @@ /*-------- vec --------*/ _z_vec_t _z_vec_make(size_t capacity) { - _z_vec_t v = {._capacity = capacity, ._len = 0, ._val = NULL}; + _z_vec_t v = {0}; if (capacity != 0) { v._val = (void **)z_malloc(sizeof(void *) * capacity); - } - if (v._val != NULL) { - v._capacity = capacity; + if (v._val != NULL) { + v._capacity = capacity; + } } return v; } diff --git a/src/link/link.c b/src/link/link.c index 197d68212..9f725ee9c 100644 --- a/src/link/link.c +++ b/src/link/link.c @@ -153,17 +153,8 @@ size_t _z_link_recv_exact_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, size_t len z_result_t _z_link_send_wbuf(const _z_link_t *link, const _z_wbuf_t *wbf) { z_result_t ret = _Z_RES_OK; - bool link_is_streamed = false; - - switch (link->_cap._flow) { - case Z_LINK_CAP_FLOW_STREAM: - link_is_streamed = true; - break; - case Z_LINK_CAP_FLOW_DATAGRAM: - default: - link_is_streamed = false; - break; - } + bool link_is_streamed = link->_cap._flow == Z_LINK_CAP_FLOW_STREAM; + for (size_t i = 0; (i < _z_wbuf_len_iosli(wbf)) && (ret == _Z_RES_OK); i++) { _z_slice_t bs = _z_iosli_to_bytes(_z_wbuf_get_iosli(wbf, i)); size_t n = bs.len; diff --git a/src/net/encoding.c b/src/net/encoding.c index f2fccb861..8bd1ec256 100644 --- a/src/net/encoding.c +++ b/src/net/encoding.c @@ -41,16 +41,21 @@ z_result_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *sc void _z_encoding_clear(_z_encoding_t *encoding) { _z_string_clear(&encoding->schema); } z_result_t _z_encoding_copy(_z_encoding_t *dst, const _z_encoding_t *src) { - *dst = _z_encoding_null(); - _Z_RETURN_IF_ERR(_z_string_copy(&dst->schema, &src->schema)); dst->id = src->id; + if (_z_string_check(&src->schema)) { + _Z_RETURN_IF_ERR(_z_string_copy(&dst->schema, &src->schema)); + } else { + dst->schema = _z_string_null(); + } return _Z_RES_OK; } void _z_encoding_move(_z_encoding_t *dst, _z_encoding_t *src) { dst->id = src->id; src->id = _Z_ENCODING_ID_DEFAULT; - _z_string_move(&dst->schema, &src->schema); + if (_z_string_check(&src->schema)) { + _z_string_move(&dst->schema, &src->schema); + } } _z_encoding_t _z_encoding_steal(_z_encoding_t *val) { diff --git a/src/net/sample.c b/src/net/sample.c index 042fbcd83..0921a3fc2 100644 --- a/src/net/sample.c +++ b/src/net/sample.c @@ -20,17 +20,14 @@ void _z_sample_move(_z_sample_t *dst, _z_sample_t *src) { _z_keyexpr_move(&dst->keyexpr, &src->keyexpr); _z_bytes_move(&dst->payload, &src->payload); _z_encoding_move(&dst->encoding, &src->encoding); + _z_timestamp_move(&dst->timestamp, &src->timestamp); _z_bytes_move(&dst->attachment, &src->attachment); - - dst->timestamp.time = src->timestamp.time; // FIXME: call the z_timestamp_move - dst->timestamp.id = src->timestamp.id; // FIXME: call the z_timestamp_move } void _z_sample_clear(_z_sample_t *sample) { _z_keyexpr_clear(&sample->keyexpr); _z_bytes_drop(&sample->payload); _z_encoding_clear(&sample->encoding); - _z_timestamp_clear(&sample->timestamp); _z_bytes_drop(&sample->attachment); } @@ -61,28 +58,28 @@ _z_sample_t _z_sample_duplicate(const _z_sample_t *src) { } #if Z_FEATURE_SUBSCRIPTION == 1 -_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t payload, const _z_timestamp_t *timestamp, +_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t *payload, const _z_timestamp_t *timestamp, _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, - const _z_bytes_t attachment, z_reliability_t reliability) { + const _z_bytes_t *attachment, z_reliability_t reliability) { _z_sample_t s = _z_sample_null(); s.keyexpr = _z_keyexpr_steal(key); s.kind = kind; - if (timestamp != NULL) { + if (_z_timestamp_check(timestamp)) { s.timestamp = _z_timestamp_duplicate(timestamp); } s.qos = qos; s.reliability = reliability; - _z_bytes_copy(&s.payload, &payload); - _z_bytes_copy(&s.attachment, &attachment); + _z_bytes_copy(&s.payload, payload); + _z_bytes_copy(&s.attachment, attachment); if (encoding != NULL) { _z_encoding_move(&s.encoding, encoding); } return s; } #else -_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t payload, const _z_timestamp_t *timestamp, +_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t *payload, const _z_timestamp_t *timestamp, _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, - const _z_bytes_t attachment, z_reliability_t reliability) { + const _z_bytes_t *attachment, z_reliability_t reliability) { _ZP_UNUSED(key); _ZP_UNUSED(payload); _ZP_UNUSED(timestamp); diff --git a/src/protocol/codec.c b/src/protocol/codec.c index 7564ef782..0d6656327 100644 --- a/src/protocol/codec.c +++ b/src/protocol/codec.c @@ -67,7 +67,7 @@ z_result_t _z_uint8_decode(uint8_t *u8, _z_zbuf_t *zbf) { if (_z_zbuf_can_read(zbf) == true) { *u8 = _z_zbuf_read(zbf); } else { - _Z_DEBUG("WARNING: Not enough bytes to read"); + _Z_INFO("Not enough bytes to read"); ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } @@ -182,6 +182,7 @@ z_result_t _z_zsize_decode_with_reader(_z_zint_t *zint, __z_single_byte_reader_t uint64_t i = 0; z_result_t res = _z_zint64_decode_with_reader(&i, reader, context); if (res != _Z_RES_OK || i > SIZE_MAX) { + _Z_INFO("Reader decode failed"); res = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } else { *zint = (_z_zint_t)i; @@ -202,6 +203,7 @@ z_result_t _z_zint16_decode(uint16_t *zint, _z_zbuf_t *zbf) { if (buf <= UINT16_MAX) { *zint = (uint16_t)buf; } else { + _Z_INFO("Invalid zint16 value decoded"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } return ret; @@ -214,6 +216,7 @@ z_result_t _z_zint32_decode(uint32_t *zint, _z_zbuf_t *zbf) { if (buf <= UINT32_MAX) { *zint = (uint32_t)buf; } else { + _Z_INFO("Invalid zint32 value decoded"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } return ret; @@ -255,7 +258,7 @@ z_result_t _z_slice_val_decode_na(_z_slice_t *bs, _z_zbuf_t *zbf) { *bs = _z_slice_alias_buf(_z_zbuf_get_rptr(zbf), bs->len); // Decode without allocating _z_zbuf_set_rpos(zbf, _z_zbuf_get_rpos(zbf) + bs->len); // Move the read position } else { - _Z_DEBUG("WARNING: Not enough bytes to read"); + _Z_INFO("Not enough bytes to read"); bs->len = 0; bs->start = NULL; ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; @@ -326,11 +329,12 @@ z_result_t _z_str_decode(char **str, _z_zbuf_t *zbf) { } *str = tmp; } else { - _Z_DEBUG("WARNING: Not enough bytes to read"); + _Z_INFO("Not enough bytes to read"); *str = NULL; ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } else { + _Z_INFO("Size decode failed"); *str = NULL; ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } @@ -350,7 +354,7 @@ z_result_t _z_string_decode(_z_string_t *str, _z_zbuf_t *zbf) { _Z_RETURN_IF_ERR(_z_zsize_decode(&len, zbf)); // Check if we have enough bytes to read if (_z_zbuf_len(zbf) < len) { - _Z_DEBUG("WARNING: Not enough bytes to read"); + _Z_INFO("Not enough bytes to read"); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } // Allocate space for the string terminator diff --git a/src/protocol/codec/declarations.c b/src/protocol/codec/declarations.c index be68a2f81..76db9dea0 100644 --- a/src/protocol/codec/declarations.c +++ b/src/protocol/codec/declarations.c @@ -32,6 +32,7 @@ #include "zenoh-pico/protocol/keyexpr.h" #include "zenoh-pico/session/session.h" #include "zenoh-pico/system/platform.h" +#include "zenoh-pico/utils/logging.h" z_result_t _z_decl_ext_keyexpr_encode(_z_wbuf_t *wbf, _z_keyexpr_t ke, bool has_next_ext) { uint8_t header = _Z_MSG_EXT_ENC_ZBUF | _Z_MSG_EXT_FLAG_M | 0x0f | (has_next_ext ? _Z_FLAG_Z_Z : 0); @@ -234,6 +235,7 @@ z_result_t _z_decl_commons_decode(_z_zbuf_t *zbf, uint8_t header, bool *has_exte _z_zint_t len; _Z_RETURN_IF_ERR(_z_zsize_decode(&len, zbf)); if (_z_zbuf_len(zbf) < len) { + _Z_INFO("Not enough bytes to read"); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } ke->_suffix = _z_string_preallocate(len); @@ -364,6 +366,7 @@ z_result_t _z_declaration_decode(_z_declaration_t *decl, _z_zbuf_t *zbf) { ret = _z_decl_final_decode(&decl->_body._decl_final, zbf, header); } break; default: { + _Z_INFO("Unknown token type"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } diff --git a/src/protocol/codec/message.c b/src/protocol/codec/message.c index f2bdf6bfb..b46dcaca0 100644 --- a/src/protocol/codec/message.c +++ b/src/protocol/codec/message.c @@ -104,7 +104,9 @@ z_result_t _z_timestamp_decode(_z_timestamp_t *ts, _z_zbuf_t *zbf) { ret |= _z_zint64_decode(&ts->time, zbf); ret |= _z_id_decode_as_slice(&ts->id, zbf); - + if (ret == _Z_RES_OK) { + ts->valid = true; + } return ret; } @@ -200,6 +202,7 @@ z_result_t _z_source_info_decode(_z_source_info_t *info, _z_zbuf_t *zbf) { if (_z_zbuf_len(zbf) >= zidlen) { _z_zbuf_read_bytes(zbf, info->_id.id, 0, zidlen); } else { + _Z_INFO("Not enough bytes to read"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } @@ -208,6 +211,7 @@ z_result_t _z_source_info_decode(_z_source_info_t *info, _z_zbuf_t *zbf) { if (intbuf <= UINT32_MAX) { info->_entity_id = (uint32_t)intbuf; } else { + _Z_INFO("Invalid value decoded"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } @@ -216,6 +220,7 @@ z_result_t _z_source_info_decode(_z_source_info_t *info, _z_zbuf_t *zbf) { if (intbuf <= UINT32_MAX) { info->_source_sn = (uint32_t)intbuf; } else { + _Z_INFO("Invalid value decoded"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } diff --git a/src/protocol/codec/network.c b/src/protocol/codec/network.c index 426c6d150..374db4564 100644 --- a/src/protocol/codec/network.c +++ b/src/protocol/codec/network.c @@ -73,6 +73,7 @@ z_result_t _z_push_decode_ext_cb(_z_msg_ext_t *extension, void *ctx) { switch (_Z_EXT_FULL_ID(extension->_header)) { case _Z_MSG_EXT_ENC_ZINT | 0x01: { // QOS ext if (extension->_body._zint._val > UINT32_MAX) { + _Z_INFO("Invalid value decoded"); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } msg->_qos = (_z_n_qos_t){._val = (uint8_t)extension->_body._zint._val}; @@ -172,6 +173,7 @@ z_result_t _z_request_decode_extensions(_z_msg_ext_t *extension, void *ctx) { switch (_Z_EXT_FULL_ID(extension->_header)) { case 0x01 | _Z_MSG_EXT_ENC_ZINT: { // QOS ext if (extension->_body._zint._val > UINT8_MAX) { + _Z_INFO("Invalid value decoded"); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } msg->_ext_qos = (_z_n_qos_t){._val = (uint8_t)extension->_body._zint._val}; @@ -185,6 +187,7 @@ z_result_t _z_request_decode_extensions(_z_msg_ext_t *extension, void *ctx) { case 0x04 | _Z_MSG_EXT_ENC_ZINT | _Z_MSG_EXT_FLAG_M: { msg->_ext_target = (uint8_t)extension->_body._zint._val; if (msg->_ext_target > 2) { + _Z_INFO("Invalid value decoded"); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } break; @@ -230,6 +233,7 @@ z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, const uint _Z_RETURN_IF_ERR(_z_del_decode(&msg->_body._del, zbf, zheader)); } break; default: + _Z_INFO("Unknown request type received: %d", _Z_MID(zheader)); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } return _Z_RES_OK; @@ -544,6 +548,7 @@ z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf) return _z_n_interest_decode(&msg->_body._interest, zbf, header); } break; default: + _Z_INFO("Unknown message type received: %d", _Z_MID(header)); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } diff --git a/src/protocol/codec/transport.c b/src/protocol/codec/transport.c index 7eff8715b..959d38dc5 100644 --- a/src/protocol/codec/transport.c +++ b/src/protocol/codec/transport.c @@ -120,6 +120,7 @@ z_result_t _z_join_decode(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header) if (_z_zbuf_len(zbf) >= zidlen) { _z_zbuf_read_bytes(zbf, msg->_zid.id, 0, zidlen); } else { + _Z_INFO("Invalid zid length received"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } @@ -200,6 +201,7 @@ z_result_t _z_init_decode(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header) if (_z_zbuf_len(zbf) >= zidlen) { _z_zbuf_read_bytes(zbf, msg->_zid.id, 0, zidlen); } else { + _Z_INFO("Invalid zid length received"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } } diff --git a/src/session/push.c b/src/session/push.c index 6b45de25b..a9537be38 100644 --- a/src/session/push.c +++ b/src/session/push.c @@ -30,14 +30,14 @@ z_result_t _z_trigger_push(_z_session_t *zn, _z_n_msg_push_t *push, z_reliabilit size_t kind = push->_body._is_put ? Z_SAMPLE_KIND_PUT : Z_SAMPLE_KIND_DELETE; if (push->_body._is_put) { _z_msg_put_t *put = &push->_body._body._put; - ret = _z_trigger_subscriptions(zn, push->_key, put->_payload, &put->_encoding, kind, &put->_commons._timestamp, - push->_qos, put->_attachment, reliability); + ret = _z_trigger_subscriptions(zn, &push->_key, &put->_payload, &put->_encoding, kind, + &put->_commons._timestamp, push->_qos, &put->_attachment, reliability); } else { _z_encoding_t encoding = _z_encoding_null(); _z_bytes_t payload = _z_bytes_null(); _z_msg_del_t *del = &push->_body._body._del; - ret = _z_trigger_subscriptions(zn, push->_key, payload, &encoding, kind, &del->_commons._timestamp, push->_qos, - del->_attachment, reliability); + ret = _z_trigger_subscriptions(zn, &push->_key, &payload, &encoding, kind, &del->_commons._timestamp, + push->_qos, &del->_attachment, reliability); } return ret; } diff --git a/src/session/rx.c b/src/session/rx.c index afacc75d7..800f795e3 100644 --- a/src/session/rx.c +++ b/src/session/rx.c @@ -101,8 +101,8 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * case _Z_REQUEST_PUT: { #if Z_FEATURE_SUBSCRIPTION == 1 _z_msg_put_t put = req->_body._put; - ret = _z_trigger_subscriptions(zn, req->_key, put._payload, &put._encoding, Z_SAMPLE_KIND_PUT, - &put._commons._timestamp, req->_ext_qos, put._attachment, + ret = _z_trigger_subscriptions(zn, &req->_key, &put._payload, &put._encoding, Z_SAMPLE_KIND_PUT, + &put._commons._timestamp, req->_ext_qos, &put._attachment, msg->_reliability); #endif if (ret == _Z_RES_OK) { @@ -114,8 +114,9 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * #if Z_FEATURE_SUBSCRIPTION == 1 _z_msg_del_t del = req->_body._del; _z_encoding_t encoding = _z_encoding_null(); - ret = _z_trigger_subscriptions(zn, req->_key, _z_bytes_null(), &encoding, Z_SAMPLE_KIND_DELETE, - &del._commons._timestamp, req->_ext_qos, del._attachment, + _z_bytes_t empty_payload = _z_bytes_null(); + ret = _z_trigger_subscriptions(zn, &req->_key, &empty_payload, &encoding, Z_SAMPLE_KIND_DELETE, + &del._commons._timestamp, req->_ext_qos, &del._attachment, msg->_reliability); #endif if (ret == _Z_RES_OK) { diff --git a/src/session/scout.c b/src/session/scout.c index 7c35d1e21..28244f08f 100644 --- a/src/session/scout.c +++ b/src/session/scout.c @@ -76,7 +76,7 @@ _z_hello_list_t *__z_scout_loop(const _z_wbuf_t *wbf, _z_string_t *locator, unsi switch (_Z_MID(s_msg._header)) { case _Z_MID_HELLO: { - _Z_INFO("Received _Z_HELLO message"); + _Z_DEBUG("Received _Z_HELLO message"); _z_hello_t *hello = (_z_hello_t *)z_malloc(sizeof(_z_hello_t)); if (hello != NULL) { hello->_version = s_msg._body._hello._version; diff --git a/src/session/subscription.c b/src/session/subscription.c index 1e0153f76..7d8117101 100644 --- a/src/session/subscription.c +++ b/src/session/subscription.c @@ -138,24 +138,24 @@ _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_loca return ret; } -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, const _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - const _z_bytes_t attachment, z_reliability_t reliability) { + const _z_bytes_t *attachment, z_reliability_t reliability) { z_result_t ret = _z_trigger_subscriptions(zn, keyexpr, payload, encoding, Z_SAMPLE_KIND_PUT, timestamp, qos, attachment, reliability); (void)ret; } -z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, +z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, const _z_bytes_t *payload, _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, - const _z_n_qos_t qos, const _z_bytes_t attachment, z_reliability_t reliability) { + const _z_n_qos_t qos, const _z_bytes_t *attachment, z_reliability_t reliability) { z_result_t ret = _Z_RES_OK; _zp_session_lock_mutex(zn); - _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr._id, (int)_z_string_len(&keyexpr._suffix), - _z_string_data(&keyexpr._suffix), _z_keyexpr_mapping_id(&keyexpr)); - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, &keyexpr); + _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr->_id, (int)_z_string_len(&keyexpr->_suffix), + _z_string_data(&keyexpr->_suffix), _z_keyexpr_mapping_id(keyexpr)); + _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr); _Z_DEBUG("Triggering subs for %d - %.*s", key._id, (int)_z_string_len(&key._suffix), _z_string_data(&key._suffix)); if (_z_keyexpr_has_suffix(&key)) { _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, &key); @@ -211,9 +211,9 @@ void _z_flush_subscriptions(_z_session_t *zn) { } #else // Z_FEATURE_SUBSCRIPTION == 0 -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, const _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - const _z_bytes_t attachment, z_reliability_t reliability) { + const _z_bytes_t *attachment, z_reliability_t reliability) { _ZP_UNUSED(zn); _ZP_UNUSED(keyexpr); _ZP_UNUSED(payload); diff --git a/src/session/utils.c b/src/session/utils.c index d82f9d84c..05d8da358 100644 --- a/src/session/utils.c +++ b/src/session/utils.c @@ -26,20 +26,18 @@ #include "zenoh-pico/utils/logging.h" /*------------------ clone helpers ------------------*/ -_z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp) { - _z_timestamp_t ts; - ts.id = tstamp->id; - ts.time = tstamp->time; - return ts; +_z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp) { return *tstamp; } + +void _z_timestamp_move(_z_timestamp_t *dst, _z_timestamp_t *src) { + *dst = *src; + _z_timestamp_clear(src); } void _z_timestamp_clear(_z_timestamp_t *tstamp) { - memset(&tstamp->id, 0, sizeof(_z_id_t)); + tstamp->valid = false; tstamp->time = 0; } -bool _z_timestamp_check(const _z_timestamp_t *stamp) { return _z_id_check(stamp->id); } - z_result_t _z_session_generate_zid(_z_id_t *bs, uint8_t size) { z_result_t ret = _Z_RES_OK; z_random_fill((uint8_t *)bs->id, size); diff --git a/src/transport/multicast/read.c b/src/transport/multicast/read.c index 965f11a32..66e177597 100644 --- a/src/transport/multicast/read.c +++ b/src/transport/multicast/read.c @@ -110,11 +110,11 @@ void *_zp_multicast_read_task(void *ztm_arg) { _z_t_msg_clear(&t_msg); _z_slice_clear(&addr); } else { - ztm->_read_task_running = false; + _Z_ERROR("Dropping message due to processing error: %d", ret); continue; } } else { - _Z_ERROR("Connection closed due to malformed message"); + _Z_ERROR("Connection closed due to malformed message: %d", ret); ztm->_read_task_running = false; continue; } diff --git a/src/transport/multicast/rx.c b/src/transport/multicast/rx.c index d531c6199..7ab3ad542 100644 --- a/src/transport/multicast/rx.c +++ b/src/transport/multicast/rx.c @@ -133,7 +133,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_transport_peer_entry_t *entry = _z_find_peer_entry(ztm->_peers, addr); switch (_Z_MID(t_msg->_header)) { case _Z_MID_T_FRAME: { - _Z_INFO("Received _Z_FRAME message"); + _Z_DEBUG("Received _Z_FRAME message"); if (entry == NULL) { break; } @@ -181,7 +181,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, } case _Z_MID_T_FRAGMENT: { - _Z_INFO("Received Z_FRAGMENT message"); + _Z_DEBUG("Received Z_FRAGMENT message"); #if Z_FEATURE_FRAGMENTATION == 1 if (entry == NULL) { break; @@ -234,7 +234,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, } case _Z_MID_T_KEEP_ALIVE: { - _Z_INFO("Received _Z_KEEP_ALIVE message"); + _Z_DEBUG("Received _Z_KEEP_ALIVE message"); if (entry == NULL) { break; } @@ -254,7 +254,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, } case _Z_MID_T_JOIN: { - _Z_INFO("Received _Z_JOIN message"); + _Z_DEBUG("Received _Z_JOIN message"); if (t_msg->_body._join._version != Z_PROTO_VERSION) { break; } diff --git a/src/transport/multicast/transport.c b/src/transport/multicast/transport.c index d0f6abb3a..b190bb468 100644 --- a/src/transport/multicast/transport.c +++ b/src/transport/multicast/transport.c @@ -136,7 +136,7 @@ z_result_t _z_multicast_open_peer(_z_transport_multicast_establish_param_t *para _z_transport_message_t jsm = _z_t_msg_make_join(Z_WHATAMI_PEER, Z_TRANSPORT_LEASE, zid, next_sn); // Encode and send the message - _Z_INFO("Sending Z_JOIN message"); + _Z_DEBUG("Sending Z_JOIN message"); switch (zl->_cap._transport) { case Z_LINK_CAP_TRANSPORT_MULTICAST: ret = _z_link_send_t_msg(zl, &jsm); diff --git a/src/transport/raweth/read.c b/src/transport/raweth/read.c index a2f080e7b..b5062ebab 100644 --- a/src/transport/raweth/read.c +++ b/src/transport/raweth/read.c @@ -69,14 +69,16 @@ void *_zp_raweth_read_task(void *ztm_arg) { break; default: // Drop message & stop task - _Z_ERROR("Connection closed due to malformed message"); + _Z_ERROR("Connection closed due to malformed message: %d", ret); ztm->_read_task_running = false; _z_slice_clear(&addr); continue; break; } // Process message - if (_z_multicast_handle_transport_message(ztm, &t_msg, &addr) != _Z_RES_OK) { + ret = _z_multicast_handle_transport_message(ztm, &t_msg, &addr); + if (ret != _Z_RES_OK) { + _Z_ERROR("Connection closed due to message processing error: %d", ret); ztm->_read_task_running = false; _z_slice_clear(&addr); continue; diff --git a/src/transport/unicast/read.c b/src/transport/unicast/read.c index a43f1404c..922b59667 100644 --- a/src/transport/unicast/read.c +++ b/src/transport/unicast/read.c @@ -104,11 +104,12 @@ void *_zp_unicast_read_task(void *ztu_arg) { if (ret == _Z_RES_OK) { _z_t_msg_clear(&t_msg); } else { + _Z_ERROR("Connection closed due to message processing error: %d", ret); ztu->_read_task_running = false; continue; } } else { - _Z_ERROR("Connection closed due to malformed message"); + _Z_ERROR("Connection closed due to malformed message: %d", ret); ztu->_read_task_running = false; continue; } diff --git a/src/transport/unicast/rx.c b/src/transport/unicast/rx.c index 23c6859b9..b500f55c9 100644 --- a/src/transport/unicast/rx.c +++ b/src/transport/unicast/rx.c @@ -101,7 +101,7 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t switch (_Z_MID(t_msg->_header)) { case _Z_MID_T_FRAME: { - _Z_INFO("Received Z_FRAME message"); + _Z_DEBUG("Received Z_FRAME message"); // Check if the SN is correct if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAME_R) == true) { // @TODO: amend once reliability is in place. For the time being only @@ -139,7 +139,7 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t } case _Z_MID_T_FRAGMENT: { - _Z_INFO("Received Z_FRAGMENT message"); + _Z_DEBUG("Received Z_FRAGMENT message"); #if Z_FEATURE_FRAGMENTATION == 1 _z_wbuf_t *dbuf = _Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R) ? &ztu->_dbuf_reliable @@ -187,7 +187,7 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t } case _Z_MID_T_KEEP_ALIVE: { - _Z_INFO("Received Z_KEEP_ALIVE message"); + _Z_DEBUG("Received Z_KEEP_ALIVE message"); break; } diff --git a/src/transport/unicast/transport.c b/src/transport/unicast/transport.c index c4433ac1a..2109eff54 100644 --- a/src/transport/unicast/transport.c +++ b/src/transport/unicast/transport.c @@ -169,7 +169,7 @@ z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, param->_batch_size = ism._body._init._batch_size; // The announced batch size // Encode and send the message - _Z_INFO("Sending Z_INIT(Syn)"); + _Z_DEBUG("Sending Z_INIT(Syn)"); ret = _z_link_send_t_msg(zl, &ism); _z_t_msg_clear(&ism); if (ret == _Z_RES_OK) { @@ -177,7 +177,7 @@ z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, ret = _z_link_recv_t_msg(&iam, zl); if (ret == _Z_RES_OK) { if ((_Z_MID(iam._header) == _Z_MID_T_INIT) && (_Z_HAS_FLAG(iam._header, _Z_FLAG_T_INIT_A) == true)) { - _Z_INFO("Received Z_INIT(Ack)"); + _Z_DEBUG("Received Z_INIT(Ack)"); // Any of the size parameters in the InitAck must be less or equal than the one in the InitSyn, // otherwise the InitAck message is considered invalid and it should be treated as a @@ -220,7 +220,7 @@ z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, _z_transport_message_t osm = _z_t_msg_make_open_syn(lease, initial_sn, cookie); // Encode and send the message - _Z_INFO("Sending Z_OPEN(Syn)"); + _Z_DEBUG("Sending Z_OPEN(Syn)"); ret = _z_link_send_t_msg(zl, &osm); if (ret == _Z_RES_OK) { _z_transport_message_t oam; @@ -228,7 +228,7 @@ z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, if (ret == _Z_RES_OK) { if ((_Z_MID(oam._header) == _Z_MID_T_OPEN) && (_Z_HAS_FLAG(oam._header, _Z_FLAG_T_OPEN_A) == true)) { - _Z_INFO("Received Z_OPEN(Ack)"); + _Z_DEBUG("Received Z_OPEN(Ack)"); param->_lease = oam._body._open._lease; // The session lease // The initial SN at RX side. Initialize the session as we had already received diff --git a/tests/z_msgcodec_test.c b/tests/z_msgcodec_test.c index 81f16f50c..1db9f5885 100644 --- a/tests/z_msgcodec_test.c +++ b/tests/z_msgcodec_test.c @@ -589,6 +589,7 @@ void assert_eq_value(const _z_value_t *left, const _z_value_t *right) { /*------------------ Timestamp field ------------------*/ _z_timestamp_t gen_timestamp(void) { _z_timestamp_t ts; + ts.valid = true; ts.time = gen_uint64(); for (size_t i = 0; i < 16; i++) { ts.id.id[i] = gen_uint8() & 0x7f; // 0b01111111 diff --git a/tests/z_refcount_test.c b/tests/z_refcount_test.c index 27cb84d9a..31a8faf71 100644 --- a/tests/z_refcount_test.c +++ b/tests/z_refcount_test.c @@ -36,6 +36,11 @@ void _dummy_clear(_dummy_t *val) { _Z_REFCOUNT_DEFINE(_dummy, _dummy) +typedef struct { + unsigned int _strong_cnt; + unsigned int _weak_cnt; +} _dummy_inner_rc_t; + void test_rc_null(void) { _dummy_rc_t drc = _dummy_rc_null(); assert(drc._cnt == NULL); @@ -231,9 +236,9 @@ void test_overflow(void) { _dummy_t val = {.foo = 42}; _dummy_rc_t drc1 = _dummy_rc_new_from_val(&val); // Artificially set weak count to max value - for (size_t i = 0; i < INT32_MAX; i++) { - _z_rc_increase_strong(drc1._cnt); - } + _dummy_inner_rc_t *dcnt = (_dummy_inner_rc_t *)drc1._cnt; + dcnt->_strong_cnt = INT32_MAX; + dcnt->_weak_cnt = INT32_MAX; _dummy_rc_t drc2 = _dummy_rc_clone(&drc1); assert(_Z_RC_IS_NULL(&drc2)); @@ -250,6 +255,104 @@ void test_decr(void) { assert(_dummy_rc_decr(&drc1)); } +_Z_SIMPLE_REFCOUNT_DEFINE(_dummy, _dummy) + +void test_simple_rc_null(void) { + _dummy_simple_rc_t drc = _dummy_simple_rc_null(); + assert(drc._cnt == NULL); + assert(drc._val == NULL); +} + +void test_simple_rc_size(void) { assert(_dummy_simple_rc_size(NULL) == sizeof(_dummy_simple_rc_t)); } + +void test_simple_rc_drop(void) { + _dummy_simple_rc_t drc = _dummy_simple_rc_null(); + assert(!_dummy_simple_rc_drop(NULL)); + assert(!_dummy_simple_rc_drop(&drc)); +} + +void test_simple_rc_new(void) { + _dummy_t *val = z_malloc(sizeof(_dummy_t)); + val->foo = 42; + _dummy_simple_rc_t drc = _dummy_simple_rc_new(val); + assert(!_Z_RC_IS_NULL(&drc)); + assert(_z_simple_rc_strong_count(drc._cnt) == 1); + assert(drc._val->foo == 42); + drc._val->foo = 0; + assert(val->foo == 0); + assert(_dummy_simple_rc_drop(&drc)); +} + +void test_simple_rc_new_from_val(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc = _dummy_simple_rc_new_from_val(&val); + assert(!_Z_RC_IS_NULL(&drc)); + assert(_z_simple_rc_strong_count(drc._cnt) == 1); + assert(drc._val->foo == 42); + drc._val->foo = 0; + assert(val.foo == 42); + assert(_dummy_simple_rc_drop(&drc)); +} + +void test_simple_rc_clone(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc1 = _dummy_simple_rc_new_from_val(&val); + assert(_z_simple_rc_strong_count(drc1._cnt) == 1); + + _dummy_simple_rc_t drc2 = _dummy_simple_rc_clone(&drc1); + assert(!_Z_RC_IS_NULL(&drc2)); + assert(_z_simple_rc_strong_count(drc2._cnt) == 2); + assert(_z_simple_rc_strong_count(drc2._cnt) == _z_simple_rc_strong_count(drc1._cnt)); + assert(drc2._val->foo == drc1._val->foo); + + assert(!_dummy_simple_rc_drop(&drc1)); + assert(_z_simple_rc_strong_count(drc2._cnt) == 1); + assert(drc2._val->foo == 42); + assert(_dummy_simple_rc_drop(&drc2)); +} + +void test_simple_rc_eq(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc1 = _dummy_simple_rc_new_from_val(&val); + _dummy_simple_rc_t drc2 = _dummy_simple_rc_clone(&drc1); + assert(_dummy_simple_rc_eq(&drc1, &drc2)); + assert(!_dummy_simple_rc_drop(&drc1)); + assert(_dummy_simple_rc_drop(&drc2)); +} + +void test_simple_rc_clone_as_ptr(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc1 = _dummy_simple_rc_new_from_val(&val); + _dummy_simple_rc_t *drc2 = _dummy_simple_rc_clone_as_ptr(&drc1); + assert(drc2->_val != NULL); + assert(!_Z_RC_IS_NULL(drc2)); + assert(_z_simple_rc_strong_count(drc2->_cnt) == 2); + assert(_dummy_simple_rc_eq(&drc1, drc2)); + assert(!_dummy_simple_rc_drop(&drc1)); + assert(_dummy_simple_rc_drop(drc2)); + z_free(drc2); +} + +void test_simple_rc_copy(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc1 = _dummy_simple_rc_new_from_val(&val); + _dummy_simple_rc_t drc2 = _dummy_simple_rc_null(); + assert(!_dummy_simple_rc_eq(&drc1, &drc2)); + _dummy_simple_rc_copy(&drc2, &drc1); + assert(_z_simple_rc_strong_count(drc2._cnt) == 2); + assert(_dummy_simple_rc_eq(&drc1, &drc2)); + assert(!_dummy_simple_rc_drop(&drc2)); + assert(_dummy_simple_rc_drop(&drc1)); +} + +void test_simple_rc_decr(void) { + _dummy_t val = {.foo = 42}; + _dummy_simple_rc_t drc1 = _dummy_simple_rc_new_from_val(&val); + _dummy_simple_rc_t drc2 = _dummy_simple_rc_clone(&drc1); + assert(!_dummy_simple_rc_decr(&drc2)); + assert(_dummy_simple_rc_decr(&drc1)); +} + int main(void) { test_rc_null(); test_rc_size(); @@ -268,5 +371,17 @@ int main(void) { test_weak_upgrade(); test_overflow(); test_decr(); + + test_simple_rc_null(); + test_simple_rc_size(); + test_simple_rc_drop(); + test_simple_rc_new(); + test_simple_rc_new_from_val(); + test_simple_rc_clone(); + test_simple_rc_eq(); + test_simple_rc_clone_as_ptr(); + test_simple_rc_copy(); + test_simple_rc_decr(); + return 0; } From 3fea89c4d5633a0c1c3dfd18f34540dcab3dd69c Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Mon, 21 Oct 2024 12:08:37 +0200 Subject: [PATCH 03/17] Improve throughput performance #3 (rx buffer focus) (#749) * feat: add refcount to z_buf * feat: wrap payload instead of copy * fix: segfaults on tests and examples * feat: pass arg by reference in reply_create * feat: add zbuf copy bytes * fix: zbuf clear memory leak * feat: improve read task buffer realloc logic * doc: update read task comment * feat: add raweth read task buffer allocation * feat: move rx buffer logic to function * fix: zbuf init code * feat: add rc count function --- examples/unix/c11/z_get_attachment.c | 2 +- include/zenoh-pico/collections/arc_slice.h | 1 + include/zenoh-pico/collections/refcount.h | 3 ++ include/zenoh-pico/net/reply.h | 5 +-- include/zenoh-pico/protocol/iobuf.h | 5 +++ include/zenoh-pico/transport/multicast/rx.h | 1 + include/zenoh-pico/transport/raweth/rx.h | 1 + include/zenoh-pico/transport/unicast/rx.h | 1 + src/collections/arc_slice.c | 12 +++++++ src/net/reply.c | 16 +++++----- src/protocol/codec.c | 13 +++++--- src/protocol/iobuf.c | 28 +++++++++++++++-- src/session/query.c | 4 +-- src/transport/multicast/read.c | 20 +++++++----- src/transport/multicast/rx.c | 21 +++++++++++++ src/transport/raweth/read.c | 8 +++++ src/transport/raweth/rx.c | 20 ++++++++++++ src/transport/unicast/read.c | 35 +++++++++++++-------- src/transport/unicast/rx.c | 22 +++++++++++++ tests/z_client_test.c | 4 +-- tests/z_peer_multicast_test.c | 4 +-- tests/z_refcount_test.c | 5 +-- 22 files changed, 185 insertions(+), 46 deletions(-) diff --git a/examples/unix/c11/z_get_attachment.c b/examples/unix/c11/z_get_attachment.c index 842273fc2..65404138b 100644 --- a/examples/unix/c11/z_get_attachment.c +++ b/examples/unix/c11/z_get_attachment.c @@ -178,7 +178,7 @@ int main(int argc, char **argv) { ze_owned_serializer_t serializer; ze_serializer_empty(&serializer); - ze_serializer_serialize_sequence_length(z_loan_mut(serializer), 2); + ze_serializer_serialize_sequence_length(z_loan_mut(serializer), 1); for (size_t i = 0; i < 1; ++i) { ze_serializer_serialize_string(z_loan_mut(serializer), z_loan(kvs[i].key)); ze_serializer_serialize_string(z_loan_mut(serializer), z_loan(kvs[i].value)); diff --git a/include/zenoh-pico/collections/arc_slice.h b/include/zenoh-pico/collections/arc_slice.h index f74d9f969..ebc21bb56 100644 --- a/include/zenoh-pico/collections/arc_slice.h +++ b/include/zenoh-pico/collections/arc_slice.h @@ -46,6 +46,7 @@ static inline _z_arc_slice_t _z_arc_slice_empty(void) { return (_z_arc_slice_t){ static inline size_t _z_arc_slice_len(const _z_arc_slice_t* s) { return s->len; } static inline bool _z_arc_slice_is_empty(const _z_arc_slice_t* s) { return _z_arc_slice_len(s) == 0; } _z_arc_slice_t _z_arc_slice_wrap(_z_slice_t s, size_t offset, size_t len); +_z_arc_slice_t _z_arc_slice_wrap_slice_rc(_z_slice_simple_rc_t* slice_rc, size_t offset, size_t len); _z_arc_slice_t _z_arc_slice_get_subslice(const _z_arc_slice_t* s, size_t offset, size_t len); const uint8_t* _z_arc_slice_data(const _z_arc_slice_t* s); z_result_t _z_arc_slice_copy(_z_arc_slice_t* dst, const _z_arc_slice_t* src); diff --git a/include/zenoh-pico/collections/refcount.h b/include/zenoh-pico/collections/refcount.h index 644d167f9..bcbd8f411 100644 --- a/include/zenoh-pico/collections/refcount.h +++ b/include/zenoh-pico/collections/refcount.h @@ -244,6 +244,9 @@ size_t _z_simple_rc_strong_count(void *cnt); *p = name##_simple_rc_null(); \ return res; \ } \ + static inline size_t name##_simple_rc_count(const name##_simple_rc_t *p) { \ + return _z_simple_rc_strong_count(p->_cnt); \ + } \ static inline size_t name##_simple_rc_size(name##_simple_rc_t *p) { \ _ZP_UNUSED(p); \ return sizeof(name##_simple_rc_t); \ diff --git a/include/zenoh-pico/net/reply.h b/include/zenoh-pico/net/reply.h index c68fcf678..3e1a1994b 100644 --- a/include/zenoh-pico/net/reply.h +++ b/include/zenoh-pico/net/reply.h @@ -89,8 +89,9 @@ _z_reply_t _z_reply_move(_z_reply_t *src_reply); void _z_reply_clear(_z_reply_t *src); void _z_reply_free(_z_reply_t **hello); z_result_t _z_reply_copy(_z_reply_t *dst, const _z_reply_t *src); -_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, _z_id_t id, const _z_bytes_t payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, z_sample_kind_t kind, const _z_bytes_t attachment); +_z_reply_t _z_reply_create(_z_keyexpr_t *keyexpr, _z_id_t id, const _z_bytes_t *payload, + const _z_timestamp_t *timestamp, _z_encoding_t *encoding, z_sample_kind_t kind, + const _z_bytes_t *attachment); _z_reply_t _z_reply_err_create(const _z_bytes_t payload, _z_encoding_t *encoding); typedef struct _z_pending_reply_t { diff --git a/include/zenoh-pico/protocol/iobuf.h b/include/zenoh-pico/protocol/iobuf.h index 888b69d46..7f1ebf722 100644 --- a/include/zenoh-pico/protocol/iobuf.h +++ b/include/zenoh-pico/protocol/iobuf.h @@ -19,6 +19,7 @@ #include #include +#include "zenoh-pico/collections/arc_slice.h" #include "zenoh-pico/collections/element.h" #include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/vec.h" @@ -40,6 +41,7 @@ _z_iosli_t _z_iosli_wrap(const uint8_t *buf, size_t length, size_t r_pos, size_t size_t _z_iosli_readable(const _z_iosli_t *ios); uint8_t _z_iosli_read(_z_iosli_t *ios); void _z_iosli_read_bytes(_z_iosli_t *ios, uint8_t *dest, size_t offset, size_t length); +void _z_iosli_copy_bytes(_z_iosli_t *dst, const _z_iosli_t *src); uint8_t _z_iosli_get(const _z_iosli_t *ios, size_t pos); size_t _z_iosli_writable(const _z_iosli_t *ios); @@ -62,8 +64,10 @@ _Z_VEC_DEFINE(_z_iosli, _z_iosli_t) /*------------------ ZBuf ------------------*/ typedef struct { _z_iosli_t _ios; + _z_slice_simple_rc_t _slice; } _z_zbuf_t; +static inline size_t _z_zbuf_get_ref_count(const _z_zbuf_t *zbf) { return _z_slice_simple_rc_count(&zbf->_slice); } _z_zbuf_t _z_zbuf_make(size_t capacity); _z_zbuf_t _z_zbuf_view(_z_zbuf_t *zbf, size_t length); /// Constructs a _borrowing_ reader on `slice` @@ -72,6 +76,7 @@ _z_zbuf_t _z_slice_as_zbuf(_z_slice_t slice); size_t _z_zbuf_capacity(const _z_zbuf_t *zbf); uint8_t const *_z_zbuf_start(const _z_zbuf_t *zbf); size_t _z_zbuf_len(const _z_zbuf_t *zbf); +void _z_zbuf_copy_bytes(_z_zbuf_t *dst, const _z_zbuf_t *src); bool _z_zbuf_can_read(const _z_zbuf_t *zbf); size_t _z_zbuf_space_left(const _z_zbuf_t *zbf); diff --git a/include/zenoh-pico/transport/multicast/rx.h b/include/zenoh-pico/transport/multicast/rx.h index 31a10e64a..97b1e8960 100644 --- a/include/zenoh-pico/transport/multicast/rx.h +++ b/include/zenoh-pico/transport/multicast/rx.h @@ -20,5 +20,6 @@ z_result_t _z_multicast_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); +z_result_t _z_multicast_update_rx_buffer(_z_transport_multicast_t *ztm); #endif /* ZENOH_PICO_TRANSPORT_LINK_RX_H */ diff --git a/include/zenoh-pico/transport/raweth/rx.h b/include/zenoh-pico/transport/raweth/rx.h index 81874d633..4607dd6b2 100644 --- a/include/zenoh-pico/transport/raweth/rx.h +++ b/include/zenoh-pico/transport/raweth/rx.h @@ -19,5 +19,6 @@ z_result_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); z_result_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); +z_result_t _z_raweth_update_rx_buff(_z_transport_multicast_t *ztm); #endif /* ZENOH_PICO_RAWETH_RX_H */ diff --git a/include/zenoh-pico/transport/unicast/rx.h b/include/zenoh-pico/transport/unicast/rx.h index f36cb592c..1fa5b60d7 100644 --- a/include/zenoh-pico/transport/unicast/rx.h +++ b/include/zenoh-pico/transport/unicast/rx.h @@ -20,5 +20,6 @@ z_result_t _z_unicast_recv_t_msg(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg); z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg); z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg); +z_result_t _z_unicast_update_rx_buffer(_z_transport_unicast_t *ztu); #endif /* ZENOH_PICO_UNICAST_RX_H */ diff --git a/src/collections/arc_slice.c b/src/collections/arc_slice.c index 9c5f6c824..17d17a8eb 100644 --- a/src/collections/arc_slice.c +++ b/src/collections/arc_slice.c @@ -32,6 +32,18 @@ _z_arc_slice_t _z_arc_slice_wrap(_z_slice_t s, size_t offset, size_t len) { return arc_s; } +_z_arc_slice_t _z_arc_slice_wrap_slice_rc(_z_slice_simple_rc_t* slice_rc, size_t offset, size_t len) { + assert(offset + len <= _Z_RC_IN_VAL(slice_rc)->len); + _z_arc_slice_t arc_s; + arc_s.slice = _z_slice_simple_rc_clone(slice_rc); + if (_Z_RC_IS_NULL(&arc_s.slice)) { + return _z_arc_slice_empty(); + } + arc_s.len = len; + arc_s.start = offset; + return arc_s; +} + _z_arc_slice_t _z_arc_slice_get_subslice(const _z_arc_slice_t* s, size_t offset, size_t len) { assert(offset + len <= s->len); assert(!_Z_RC_IS_NULL(&s->slice) || (len == 0 && offset == 0)); diff --git a/src/net/reply.c b/src/net/reply.c index a331ae6cf..67987cb35 100644 --- a/src/net/reply.c +++ b/src/net/reply.c @@ -87,18 +87,19 @@ void _z_pending_reply_clear(_z_pending_reply_t *pr) { _z_timestamp_clear(&pr->_tstamp); } -_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, _z_id_t id, const _z_bytes_t payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, z_sample_kind_t kind, const _z_bytes_t attachment) { +_z_reply_t _z_reply_create(_z_keyexpr_t *keyexpr, _z_id_t id, const _z_bytes_t *payload, + const _z_timestamp_t *timestamp, _z_encoding_t *encoding, z_sample_kind_t kind, + const _z_bytes_t *attachment) { _z_reply_t reply = _z_reply_null(); reply.data._tag = _Z_REPLY_TAG_DATA; reply.data.replier_id = id; // Create reply sample - reply.data._result.sample.keyexpr = _z_keyexpr_steal(&keyexpr); + reply.data._result.sample.keyexpr = _z_keyexpr_steal(keyexpr); reply.data._result.sample.kind = kind; reply.data._result.sample.timestamp = _z_timestamp_duplicate(timestamp); - _z_bytes_copy(&reply.data._result.sample.payload, &payload); - _z_bytes_copy(&reply.data._result.sample.attachment, &attachment); + _z_bytes_copy(&reply.data._result.sample.payload, payload); + _z_bytes_copy(&reply.data._result.sample.attachment, attachment); _z_encoding_move(&reply.data._result.sample.encoding, encoding); return reply; @@ -112,8 +113,9 @@ _z_reply_t _z_reply_err_create(const _z_bytes_t payload, _z_encoding_t *encoding return reply; } #else -_z_reply_t _z_reply_create(_z_keyexpr_t keyexpr, _z_id_t id, const _z_bytes_t payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, z_sample_kind_t kind, const _z_bytes_t attachment) { +_z_reply_t _z_reply_create(_z_keyexpr_t *keyexpr, _z_id_t id, const _z_bytes_t *payload, + const _z_timestamp_t *timestamp, _z_encoding_t *encoding, z_sample_kind_t kind, + const _z_bytes_t *attachment) { _ZP_UNUSED(keyexpr); _ZP_UNUSED(id); _ZP_UNUSED(payload); diff --git a/src/protocol/codec.c b/src/protocol/codec.c index 0d6656327..8574d2d89 100644 --- a/src/protocol/codec.c +++ b/src/protocol/codec.c @@ -19,6 +19,7 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/utils/endianness.h" #include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/pointers.h" #include "zenoh-pico/utils/result.h" /*------------------ uint8 -------------------*/ @@ -281,13 +282,15 @@ z_result_t _z_slice_val_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice z_result_t _z_slice_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice_decode_na(bs, zbf); } z_result_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf) { + *bs = _z_bytes_null(); + // Decode slice _z_slice_t s; _Z_RETURN_IF_ERR(_z_slice_decode(&s, zbf)); - if (_z_slice_is_alloced(&s)) { - return _z_bytes_from_slice(bs, s); - } else { - return _z_bytes_from_buf(bs, s.start, s.len); - } + // Calc offset + size_t offset = _z_ptr_u8_diff(s.start, _Z_RC_IN_VAL(&zbf->_slice)->start); + // Get ownership of subslice + _z_arc_slice_t arcs = _z_arc_slice_wrap_slice_rc(&zbf->_slice, offset, s.len); + return _z_bytes_append_slice(bs, &arcs); } z_result_t _z_bytes_encode_val(_z_wbuf_t *wbf, const _z_bytes_t *bs) { diff --git a/src/protocol/iobuf.c b/src/protocol/iobuf.c index c398bc766..7b4b361dc 100644 --- a/src/protocol/iobuf.c +++ b/src/protocol/iobuf.c @@ -20,6 +20,7 @@ #include #include "zenoh-pico/config.h" +#include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/pointers.h" #include "zenoh-pico/utils/result.h" @@ -75,6 +76,13 @@ void _z_iosli_read_bytes(_z_iosli_t *ios, uint8_t *dst, size_t offset, size_t le ios->_r_pos = ios->_r_pos + length; } +void _z_iosli_copy_bytes(_z_iosli_t *dst, const _z_iosli_t *src) { + size_t length = _z_iosli_readable(src); + assert(_z_iosli_readable(dst) >= length); + (void)memcpy(dst->_buf + dst->_w_pos, src->_buf + src->_r_pos, length); + dst->_w_pos += length; +} + uint8_t _z_iosli_get(const _z_iosli_t *ios, size_t pos) { assert(pos < ios->_capacity); return ios->_buf[pos]; @@ -160,8 +168,18 @@ _z_iosli_t *_z_iosli_clone(const _z_iosli_t *src) { /*------------------ ZBuf ------------------*/ _z_zbuf_t _z_zbuf_make(size_t capacity) { - _z_zbuf_t zbf; + _z_zbuf_t zbf = {0}; zbf._ios = _z_iosli_make(capacity); + if (_z_zbuf_capacity(&zbf) == 0) { + return zbf; + } + _z_slice_t s = _z_slice_from_buf_custom_deleter(zbf._ios._buf, zbf._ios._capacity, _z_delete_context_default()); + zbf._slice = _z_slice_simple_rc_new_from_val(&s); + if (_Z_RC_IS_NULL(&zbf._slice)) { + _Z_ERROR("slice rc creation failed"); + _z_iosli_clear(&zbf._ios); + } + zbf._ios._is_alloc = false; return zbf; } @@ -169,6 +187,7 @@ _z_zbuf_t _z_zbuf_view(_z_zbuf_t *zbf, size_t length) { assert(_z_iosli_readable(&zbf->_ios) >= length); _z_zbuf_t v; v._ios = _z_iosli_wrap(_z_zbuf_get_rptr(zbf), length, 0, length); + v._slice = zbf->_slice; return v; } _z_zbuf_t _z_slice_as_zbuf(_z_slice_t slice) { @@ -188,6 +207,8 @@ uint8_t const *_z_zbuf_start(const _z_zbuf_t *zbf) { } size_t _z_zbuf_len(const _z_zbuf_t *zbf) { return _z_iosli_readable(&zbf->_ios); } +void _z_zbuf_copy_bytes(_z_zbuf_t *dst, const _z_zbuf_t *src) { _z_iosli_copy_bytes(&dst->_ios, &src->_ios); } + bool _z_zbuf_can_read(const _z_zbuf_t *zbf) { return _z_zbuf_len(zbf) > (size_t)0; } uint8_t _z_zbuf_read(_z_zbuf_t *zbf) { return _z_iosli_read(&zbf->_ios); } @@ -218,7 +239,10 @@ uint8_t *_z_zbuf_get_wptr(const _z_zbuf_t *zbf) { return zbf->_ios._buf + zbf->_ void _z_zbuf_reset(_z_zbuf_t *zbf) { _z_iosli_reset(&zbf->_ios); } -void _z_zbuf_clear(_z_zbuf_t *zbf) { _z_iosli_clear(&zbf->_ios); } +void _z_zbuf_clear(_z_zbuf_t *zbf) { + _z_iosli_clear(&zbf->_ios); + _z_slice_simple_rc_drop(&zbf->_slice); +} void _z_zbuf_compact(_z_zbuf_t *zbf) { if ((zbf->_ios._r_pos != 0) || (zbf->_ios._w_pos != 0)) { diff --git a/src/session/query.c b/src/session/query.c index f9546990f..f3401dace 100644 --- a/src/session/query.c +++ b/src/session/query.c @@ -112,8 +112,8 @@ z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, } // Build the reply - _z_reply_t reply = _z_reply_create(expanded_ke, zn->_local_zid, msg->_payload, &msg->_commons._timestamp, - &msg->_encoding, kind, msg->_attachment); + _z_reply_t reply = _z_reply_create(&expanded_ke, zn->_local_zid, &msg->_payload, &msg->_commons._timestamp, + &msg->_encoding, kind, &msg->_attachment); bool drop = false; // Verify if this is a newer reply, free the old one in case it is diff --git a/src/transport/multicast/read.c b/src/transport/multicast/read.c index 66e177597..0a39fe4e1 100644 --- a/src/transport/multicast/read.c +++ b/src/transport/multicast/read.c @@ -36,7 +36,10 @@ z_result_t _zp_multicast_read(_z_transport_multicast_t *ztm) { ret = _z_multicast_handle_transport_message(ztm, &t_msg, &addr); _z_t_msg_clear(&t_msg); } - + ret = _z_multicast_update_rx_buffer(ztm); + if (ret != _Z_RES_OK) { + _Z_ERROR("Failed to allocate rx buffer"); + } return ret; } #else @@ -57,11 +60,11 @@ void *_zp_multicast_read_task(void *ztm_arg) { // Prepare the buffer _z_zbuf_reset(&ztm->_zbuf); - _z_slice_t addr = _z_slice_alias_buf(NULL, 0); + _z_slice_t addr = _z_slice_empty(); while (ztm->_read_task_running == true) { - // Read bytes from socket to the main buffer size_t to_read = 0; + // Read bytes from socket to the main buffer switch (ztm->_link._cap._flow) { case Z_LINK_CAP_FLOW_STREAM: if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { @@ -94,15 +97,13 @@ void *_zp_multicast_read_task(void *ztm_arg) { default: break; } - // Wrap the main buffer for to_read bytes + // Wrap the main buffer to_read bytes _z_zbuf_t zbuf = _z_zbuf_view(&ztm->_zbuf, to_read); while (_z_zbuf_len(&zbuf) > 0) { - z_result_t ret = _Z_RES_OK; - // Decode one session message _z_transport_message_t t_msg; - ret = _z_transport_message_decode(&t_msg, &zbuf); + z_result_t ret = _z_transport_message_decode(&t_msg, &zbuf); if (ret == _Z_RES_OK) { ret = _z_multicast_handle_transport_message(ztm, &t_msg, &addr); @@ -119,9 +120,12 @@ void *_zp_multicast_read_task(void *ztm_arg) { continue; } } - // Move the read position of the read buffer _z_zbuf_set_rpos(&ztm->_zbuf, _z_zbuf_get_rpos(&ztm->_zbuf) + to_read); + if (_z_multicast_update_rx_buffer(ztm) != _Z_RES_OK) { + _Z_ERROR("Connection closed due to lack of memory to allocate rx buffer"); + ztm->_read_task_running = false; + } } _z_mutex_unlock(&ztm->_mutex_rx); return NULL; diff --git a/src/transport/multicast/rx.c b/src/transport/multicast/rx.c index 7ab3ad542..2832d2053 100644 --- a/src/transport/multicast/rx.c +++ b/src/transport/multicast/rx.c @@ -350,6 +350,27 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, return ret; } + +z_result_t _z_multicast_update_rx_buffer(_z_transport_multicast_t *ztm) { + // Check if user or defragment buffer took ownership of buffer + if (_z_zbuf_get_ref_count(&ztm->_zbuf) != 1) { + // Allocate a new buffer + _z_zbuf_t new_zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); + if (_z_zbuf_capacity(&new_zbuf) != Z_BATCH_MULTICAST_SIZE) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Recopy leftover bytes + size_t leftovers = _z_zbuf_len(&ztm->_zbuf); + if (leftovers > 0) { + _z_zbuf_copy_bytes(&new_zbuf, &ztm->_zbuf); + } + // Drop buffer & update + _z_zbuf_clear(&ztm->_zbuf); + ztm->_zbuf = new_zbuf; + } + return _Z_RES_OK; +} + #else z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr) { diff --git a/src/transport/raweth/read.c b/src/transport/raweth/read.c index b5062ebab..4c49d7b64 100644 --- a/src/transport/raweth/read.c +++ b/src/transport/raweth/read.c @@ -37,6 +37,10 @@ z_result_t _zp_raweth_read(_z_transport_multicast_t *ztm) { _z_t_msg_clear(&t_msg); } _z_slice_clear(&addr); + ret = _z_raweth_update_rx_buff(ztm); + if (ret != _Z_RES_OK) { + _Z_ERROR("Failed to allocate rx buffer"); + } return ret; } #else @@ -85,6 +89,10 @@ void *_zp_raweth_read_task(void *ztm_arg) { } _z_t_msg_clear(&t_msg); _z_slice_clear(&addr); + if (_z_raweth_update_rx_buff(ztm) != _Z_RES_OK) { + _Z_ERROR("Connection closed due to lack of memory to allocate rx buffer"); + ztm->_read_task_running = false; + } } return NULL; } diff --git a/src/transport/raweth/rx.c b/src/transport/raweth/rx.c index 59b57e512..660f49293 100644 --- a/src/transport/raweth/rx.c +++ b/src/transport/raweth/rx.c @@ -117,6 +117,26 @@ z_result_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_mess return _z_raweth_recv_t_msg_na(ztm, t_msg, addr); } +z_result_t _z_raweth_update_rx_buff(_z_transport_multicast_t *ztm) { + // Check if user or defragment buffer took ownership of buffer + if (_z_zbuf_get_ref_count(&ztm->_zbuf) != 1) { + // Allocate a new buffer + _z_zbuf_t new_zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); + if (_z_zbuf_capacity(&new_zbuf) != Z_BATCH_MULTICAST_SIZE) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Recopy leftover bytes + size_t leftovers = _z_zbuf_len(&ztm->_zbuf); + if (leftovers > 0) { + _z_zbuf_copy_bytes(&new_zbuf, &ztm->_zbuf); + } + // Drop buffer & update + _z_zbuf_clear(&ztm->_zbuf); + ztm->_zbuf = new_zbuf; + } + return _Z_RES_OK; +} + #else z_result_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr) { _ZP_UNUSED(ztm); diff --git a/src/transport/unicast/read.c b/src/transport/unicast/read.c index 922b59667..d6520b6c3 100644 --- a/src/transport/unicast/read.c +++ b/src/transport/unicast/read.c @@ -33,7 +33,10 @@ z_result_t _zp_unicast_read(_z_transport_unicast_t *ztu) { ret = _z_unicast_handle_transport_message(ztu, &t_msg); _z_t_msg_clear(&t_msg); } - + ret = _z_unicast_update_rx_buffer(ztu); + if (ret != _Z_RES_OK) { + _Z_ERROR("Failed to allocate rx buffer"); + } return ret; } #else @@ -95,27 +98,33 @@ void *_zp_unicast_read_task(void *ztu_arg) { // Mark the session that we have received data ztu->_received = true; - // Decode one session message - _z_transport_message_t t_msg; - z_result_t ret = _z_transport_message_decode(&t_msg, &zbuf); + while (_z_zbuf_len(&zbuf) > 0) { + // Decode one session message + _z_transport_message_t t_msg; + z_result_t ret = _z_transport_message_decode(&t_msg, &zbuf); - if (ret == _Z_RES_OK) { - ret = _z_unicast_handle_transport_message(ztu, &t_msg); if (ret == _Z_RES_OK) { - _z_t_msg_clear(&t_msg); + ret = _z_unicast_handle_transport_message(ztu, &t_msg); + if (ret == _Z_RES_OK) { + _z_t_msg_clear(&t_msg); + } else { + _Z_ERROR("Connection closed due to message processing error: %d", ret); + ztu->_read_task_running = false; + continue; + } } else { - _Z_ERROR("Connection closed due to message processing error: %d", ret); + _Z_ERROR("Connection closed due to malformed message: %d", ret); ztu->_read_task_running = false; continue; } - } else { - _Z_ERROR("Connection closed due to malformed message: %d", ret); - ztu->_read_task_running = false; - continue; } - // Move the read position of the read buffer _z_zbuf_set_rpos(&ztu->_zbuf, _z_zbuf_get_rpos(&ztu->_zbuf) + to_read); + + if (_z_unicast_update_rx_buffer(ztu) != _Z_RES_OK) { + _Z_ERROR("Connection closed due to lack of memory to allocate rx buffer"); + ztu->_read_task_running = false; + } } _z_mutex_unlock(&ztu->_mutex_rx); return NULL; diff --git a/src/transport/unicast/rx.c b/src/transport/unicast/rx.c index b500f55c9..be7d55446 100644 --- a/src/transport/unicast/rx.c +++ b/src/transport/unicast/rx.c @@ -215,6 +215,28 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t return ret; } + +z_result_t _z_unicast_update_rx_buffer(_z_transport_unicast_t *ztu) { + // Check if user or defragment buffer took ownership of buffer + if (_z_zbuf_get_ref_count(&ztu->_zbuf) != 1) { + // Allocate a new buffer + size_t buff_capacity = _z_zbuf_capacity(&ztu->_zbuf); + _z_zbuf_t new_zbuf = _z_zbuf_make(buff_capacity); + if (_z_zbuf_capacity(&new_zbuf) != buff_capacity) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Recopy leftover bytes + size_t leftovers = _z_zbuf_len(&ztu->_zbuf); + if (leftovers > 0) { + _z_zbuf_copy_bytes(&new_zbuf, &ztu->_zbuf); + } + // Drop buffer & update + _z_zbuf_clear(&ztu->_zbuf); + ztu->_zbuf = new_zbuf; + } + return _Z_RES_OK; +} + #else z_result_t _z_unicast_recv_t_msg(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg) { _ZP_UNUSED(ztu); diff --git a/tests/z_client_test.c b/tests/z_client_test.c index d073bc554..229722a48 100644 --- a/tests/z_client_test.c +++ b/tests/z_client_test.c @@ -138,7 +138,7 @@ int main(int argc, char **argv) { z_owned_session_t s1; assert(z_open(&s1, z_move(config), NULL) == Z_OK); _z_string_t zid1 = format_id(&(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); - printf("Session 1 with PID: %s\n", _z_string_data(&zid1)); + printf("Session 1 with PID: %.*s\n", (int)z_string_len(&zid1), _z_string_data(&zid1)); _z_string_clear(&zid1); // Start the read session session lease loops @@ -154,7 +154,7 @@ int main(int argc, char **argv) { assert(z_open(&s2, z_move(config), NULL) == Z_OK); assert(z_internal_check(s2)); _z_string_t zid2 = format_id(&(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); - printf("Session 2 with PID: %s\n", _z_string_data(&zid2)); + printf("Session 2 with PID: %.*s\n", (int)z_string_len(&zid2), _z_string_data(&zid2)); _z_string_clear(&zid2); // Start the read session session lease loops diff --git a/tests/z_peer_multicast_test.c b/tests/z_peer_multicast_test.c index 383ba799d..9cbd017b5 100644 --- a/tests/z_peer_multicast_test.c +++ b/tests/z_peer_multicast_test.c @@ -79,7 +79,7 @@ int main(int argc, char **argv) { _z_slice_t id_as_bytes = _z_slice_alias_buf(_Z_RC_IN_VAL(z_loan(s1))->_local_zid.id, _z_id_len(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); _z_string_t zid1 = _z_string_convert_bytes(&id_as_bytes); - printf("Session 1 with PID: %s\n", z_string_data(&zid1)); + printf("Session 1 with PID: %.*s\n", (int)z_string_len(&zid1), z_string_data(&zid1)); _z_string_clear(&zid1); // Start the read session session lease loops @@ -98,7 +98,7 @@ int main(int argc, char **argv) { id_as_bytes = _z_slice_alias_buf(_Z_RC_IN_VAL(z_loan(s2))->_local_zid.id, _z_id_len(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); _z_string_t zid2 = _z_string_convert_bytes(&id_as_bytes); - printf("Session 2 with PID: %s\n", z_string_data(&zid2)); + printf("Session 2 with PID: %.*s\n", (int)z_string_len(&zid2), z_string_data(&zid2)); _z_string_clear(&zid2); // Start the read session session lease loops diff --git a/tests/z_refcount_test.c b/tests/z_refcount_test.c index 31a8faf71..7935b6c63 100644 --- a/tests/z_refcount_test.c +++ b/tests/z_refcount_test.c @@ -326,9 +326,10 @@ void test_simple_rc_clone_as_ptr(void) { _dummy_simple_rc_t *drc2 = _dummy_simple_rc_clone_as_ptr(&drc1); assert(drc2->_val != NULL); assert(!_Z_RC_IS_NULL(drc2)); - assert(_z_simple_rc_strong_count(drc2->_cnt) == 2); + assert(_dummy_simple_rc_count(drc2) == 2); assert(_dummy_simple_rc_eq(&drc1, drc2)); assert(!_dummy_simple_rc_drop(&drc1)); + assert(_dummy_simple_rc_count(drc2) == 1); assert(_dummy_simple_rc_drop(drc2)); z_free(drc2); } @@ -339,7 +340,7 @@ void test_simple_rc_copy(void) { _dummy_simple_rc_t drc2 = _dummy_simple_rc_null(); assert(!_dummy_simple_rc_eq(&drc1, &drc2)); _dummy_simple_rc_copy(&drc2, &drc1); - assert(_z_simple_rc_strong_count(drc2._cnt) == 2); + assert(_dummy_simple_rc_count(&drc2) == 2); assert(_dummy_simple_rc_eq(&drc1, &drc2)); assert(!_dummy_simple_rc_drop(&drc2)); assert(_dummy_simple_rc_drop(&drc1)); From b6a4599fed922893bc5c7a69d9371ddef3a46bc1 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Tue, 22 Oct 2024 09:27:17 +0200 Subject: [PATCH 04/17] Improve throughput performance #4 (rx defragmentation focus) (#754) * fix: bad nt string access in msgcodec test * feat: wrap fragment instead of copy * feat: remove extra wbuf init allocation * feat: add iobuf null functions * feat: add wbuf moved as zbuf function * feat: add defrag buff state and allocate only as needed * feat: move defrag buffer instead of copy * fix: wbuf moved memory leak * fix: memory leak on write filter * feat: add defrag buffer changes to multicast * fix: transport memory leak --- include/zenoh-pico/protocol/iobuf.h | 5 ++ include/zenoh-pico/transport/transport.h | 10 +++ src/net/filtering.c | 3 +- src/protocol/codec/transport.c | 4 +- src/protocol/iobuf.c | 41 +++++++--- src/transport/multicast/read.c | 1 + src/transport/multicast/rx.c | 96 +++++++++++++++--------- src/transport/peer_entry.c | 2 + src/transport/unicast/rx.c | 76 +++++++++++++------ src/transport/unicast/transport.c | 44 +---------- tests/z_msgcodec_test.c | 2 +- 11 files changed, 169 insertions(+), 115 deletions(-) diff --git a/include/zenoh-pico/protocol/iobuf.h b/include/zenoh-pico/protocol/iobuf.h index 7f1ebf722..44cace0d7 100644 --- a/include/zenoh-pico/protocol/iobuf.h +++ b/include/zenoh-pico/protocol/iobuf.h @@ -34,9 +34,11 @@ typedef struct { bool _is_alloc; } _z_iosli_t; +static inline _z_iosli_t _z_iosli_null(void) { return (_z_iosli_t){0}; } _z_iosli_t _z_iosli_make(size_t capacity); _z_iosli_t *_z_iosli_new(size_t capacity); _z_iosli_t _z_iosli_wrap(const uint8_t *buf, size_t length, size_t r_pos, size_t w_pos); +_z_iosli_t _z_iosli_steal(_z_iosli_t *ios); size_t _z_iosli_readable(const _z_iosli_t *ios); uint8_t _z_iosli_read(_z_iosli_t *ios); @@ -68,6 +70,7 @@ typedef struct { } _z_zbuf_t; static inline size_t _z_zbuf_get_ref_count(const _z_zbuf_t *zbf) { return _z_slice_simple_rc_count(&zbf->_slice); } +static inline _z_zbuf_t _z_zbuf_null(void) { return (_z_zbuf_t){0}; } _z_zbuf_t _z_zbuf_make(size_t capacity); _z_zbuf_t _z_zbuf_view(_z_zbuf_t *zbf, size_t length); /// Constructs a _borrowing_ reader on `slice` @@ -106,6 +109,7 @@ typedef struct { size_t _expansion_step; } _z_wbuf_t; +static inline _z_wbuf_t _z_wbuf_null(void) { return (_z_wbuf_t){0}; } _z_wbuf_t _z_wbuf_make(size_t capacity, bool is_expandable); size_t _z_wbuf_capacity(const _z_wbuf_t *wbf); @@ -127,6 +131,7 @@ _z_iosli_t *_z_wbuf_get_iosli(const _z_wbuf_t *wbf, size_t idx); size_t _z_wbuf_len_iosli(const _z_wbuf_t *wbf); _z_zbuf_t _z_wbuf_to_zbuf(const _z_wbuf_t *wbf); +_z_zbuf_t _z_wbuf_moved_as_zbuf(_z_wbuf_t *wbf); z_result_t _z_wbuf_siphon(_z_wbuf_t *dst, _z_wbuf_t *src, size_t length); void _z_wbuf_copy(_z_wbuf_t *dst, const _z_wbuf_t *src); diff --git a/include/zenoh-pico/transport/transport.h b/include/zenoh-pico/transport/transport.h index 4e013594e..5075b39b7 100644 --- a/include/zenoh-pico/transport/transport.h +++ b/include/zenoh-pico/transport/transport.h @@ -25,9 +25,17 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/transport.h" +enum _z_dbuf_state_e { + _Z_DBUF_STATE_NULL = 0, + _Z_DBUF_STATE_INIT = 1, + _Z_DBUF_STATE_OVERFLOW = 2, +}; + typedef struct { #if Z_FEATURE_FRAGMENTATION == 1 // Defragmentation buffers + uint8_t _state_reliable; + uint8_t _state_best_effort; _z_wbuf_t _dbuf_reliable; _z_wbuf_t _dbuf_best_effort; #endif @@ -77,6 +85,8 @@ typedef struct { #if Z_FEATURE_FRAGMENTATION == 1 // Defragmentation buffer + uint8_t _state_reliable; + uint8_t _state_best_effort; _z_wbuf_t _dbuf_reliable; _z_wbuf_t _dbuf_best_effort; #endif diff --git a/src/net/filtering.c b/src/net/filtering.c index d3be65236..022c6c798 100644 --- a/src/net/filtering.c +++ b/src/net/filtering.c @@ -96,9 +96,10 @@ z_result_t _z_write_filter_create(_z_publisher_t *pub) { z_result_t _z_write_filter_destroy(_z_publisher_t *pub) { if (pub->_filter.ctx != NULL) { - _Z_RETURN_IF_ERR(_z_remove_interest(_Z_RC_IN_VAL(&pub->_zn), pub->_filter._interest_id)); + z_result_t res = _z_remove_interest(_Z_RC_IN_VAL(&pub->_zn), pub->_filter._interest_id); z_free(pub->_filter.ctx); pub->_filter.ctx = NULL; + return res; } return _Z_RES_OK; } diff --git a/src/protocol/codec/transport.c b/src/protocol/codec/transport.c index 959d38dc5..1208e3fee 100644 --- a/src/protocol/codec/transport.c +++ b/src/protocol/codec/transport.c @@ -410,9 +410,7 @@ z_result_t _z_fragment_decode(_z_t_msg_fragment_t *msg, _z_zbuf_t *zbf, uint8_t if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x05); } - - _z_slice_t slice = _z_slice_alias_buf((uint8_t *)_z_zbuf_start(zbf), _z_zbuf_len(zbf)); - _z_slice_copy(&msg->_payload, &slice); + msg->_payload = _z_slice_alias_buf((uint8_t *)_z_zbuf_start(zbf), _z_zbuf_len(zbf)); zbf->_ios._r_pos = zbf->_ios._w_pos; return ret; diff --git a/src/protocol/iobuf.c b/src/protocol/iobuf.c index 7b4b361dc..8c6f6d39d 100644 --- a/src/protocol/iobuf.c +++ b/src/protocol/iobuf.c @@ -36,6 +36,12 @@ _z_iosli_t _z_iosli_wrap(const uint8_t *buf, size_t length, size_t r_pos, size_t return ios; } +_z_iosli_t _z_iosli_steal(_z_iosli_t *ios) { + _z_iosli_t new_ios = *ios; + *ios = _z_iosli_null(); + return new_ios; +} + void __z_iosli_init(_z_iosli_t *ios, size_t capacity) { ios->_r_pos = 0; ios->_w_pos = 0; @@ -168,7 +174,7 @@ _z_iosli_t *_z_iosli_clone(const _z_iosli_t *src) { /*------------------ ZBuf ------------------*/ _z_zbuf_t _z_zbuf_make(size_t capacity) { - _z_zbuf_t zbf = {0}; + _z_zbuf_t zbf = _z_zbuf_null(); zbf._ios = _z_iosli_make(capacity); if (_z_zbuf_capacity(&zbf) == 0) { return zbf; @@ -284,15 +290,8 @@ size_t _z_wbuf_len_iosli(const _z_wbuf_t *wbf) { return _z_iosli_vec_len(&wbf->_ _z_wbuf_t _z_wbuf_make(size_t capacity, bool is_expandable) { _z_wbuf_t wbf; - if (is_expandable == true) { - // Preallocate 4 slots, this is usually what we expect - // when fragmenting a zenoh data message with attachment - wbf._ioss = _z_iosli_vec_make(4); - _z_wbuf_add_iosli(&wbf, __z_wbuf_new_iosli(capacity)); - } else { - wbf._ioss = _z_iosli_vec_make(1); - _z_wbuf_add_iosli(&wbf, __z_wbuf_new_iosli(capacity)); - } + wbf._ioss = _z_iosli_vec_make(1); + _z_wbuf_add_iosli(&wbf, __z_wbuf_new_iosli(capacity)); wbf._w_idx = 0; // This __must__ come after adding ioslices to reset w_idx wbf._r_idx = 0; wbf._expansion_step = is_expandable ? capacity : 0; @@ -541,6 +540,23 @@ _z_zbuf_t _z_wbuf_to_zbuf(const _z_wbuf_t *wbf) { return zbf; } +_z_zbuf_t _z_wbuf_moved_as_zbuf(_z_wbuf_t *wbf) { + // Can only move single buffer wbuf + assert(_z_iosli_vec_len(&wbf->_ioss) == 1); + + _z_zbuf_t zbf = _z_zbuf_null(); + _z_iosli_t *ios = _z_wbuf_get_iosli(wbf, 0); + zbf._ios = _z_iosli_steal(ios); + _z_slice_t s = _z_slice_from_buf_custom_deleter(zbf._ios._buf, zbf._ios._capacity, _z_delete_context_default()); + zbf._slice = _z_slice_simple_rc_new_from_val(&s); + if (_Z_RC_IS_NULL(&zbf._slice)) { + _Z_ERROR("slice rc creation failed"); + } + zbf._ios._is_alloc = false; + _z_wbuf_clear(wbf); + return zbf; +} + z_result_t _z_wbuf_siphon(_z_wbuf_t *dst, _z_wbuf_t *src, size_t length) { z_result_t ret = _Z_RES_OK; size_t llength = length; @@ -593,7 +609,10 @@ void _z_wbuf_reset(_z_wbuf_t *wbf) { } } -void _z_wbuf_clear(_z_wbuf_t *wbf) { _z_iosli_vec_clear(&wbf->_ioss); } +void _z_wbuf_clear(_z_wbuf_t *wbf) { + _z_iosli_vec_clear(&wbf->_ioss); + *wbf = _z_wbuf_null(); +} void _z_wbuf_free(_z_wbuf_t **wbf) { _z_wbuf_t *ptr = *wbf; diff --git a/src/transport/multicast/read.c b/src/transport/multicast/read.c index 0a39fe4e1..e3036af31 100644 --- a/src/transport/multicast/read.c +++ b/src/transport/multicast/read.c @@ -112,6 +112,7 @@ void *_zp_multicast_read_task(void *ztm_arg) { _z_slice_clear(&addr); } else { _Z_ERROR("Dropping message due to processing error: %d", ret); + _z_slice_clear(&addr); continue; } } else { diff --git a/src/transport/multicast/rx.c b/src/transport/multicast/rx.c index 2832d2053..32bc570fb 100644 --- a/src/transport/multicast/rx.c +++ b/src/transport/multicast/rx.c @@ -135,8 +135,10 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, case _Z_MID_T_FRAME: { _Z_DEBUG("Received _Z_FRAME message"); if (entry == NULL) { + _Z_INFO("Dropping _Z_FRAME from unknown peer"); break; } + // Note that we receive data from peer entry->_received = true; // Check if the SN is correct @@ -148,6 +150,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, entry->_sn_rx_sns._val._plain._reliable = t_msg->_body._frame._sn; } else { #if Z_FEATURE_FRAGMENTATION == 1 + entry->_state_reliable = _Z_DBUF_STATE_NULL; _z_wbuf_clear(&entry->_dbuf_reliable); #endif _Z_INFO("Reliable message dropped because it is out of order"); @@ -159,6 +162,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, entry->_sn_rx_sns._val._plain._best_effort = t_msg->_body._frame._sn; } else { #if Z_FEATURE_FRAGMENTATION == 1 + entry->_state_best_effort = _Z_DBUF_STATE_NULL; _z_wbuf_clear(&entry->_dbuf_best_effort); #endif _Z_INFO("Best effort message dropped because it is out of order"); @@ -184,33 +188,62 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _Z_DEBUG("Received Z_FRAGMENT message"); #if Z_FEATURE_FRAGMENTATION == 1 if (entry == NULL) { + _Z_INFO("Dropping Z_FRAGMENT from unknown peer"); break; } + // Note that we receive data from the peer entry->_received = true; - _z_wbuf_t *dbuf = _Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R) - ? &entry->_dbuf_reliable - : &entry->_dbuf_best_effort; // Select the right defragmentation buffer - - bool drop = false; - if ((_z_wbuf_len(dbuf) + t_msg->_body._fragment._payload.len) > Z_FRAG_MAX_SIZE) { - // Filling the wbuf capacity as a way to signaling the last fragment to reset the dbuf - // Otherwise, last (smaller) fragments can be understood as a complete message - _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, _z_wbuf_space_left(dbuf)); - drop = true; + _z_wbuf_t *dbuf; + uint8_t *dbuf_state; + // Select the right defragmentation buffer + if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R)) { + dbuf = &entry->_dbuf_reliable; + dbuf_state = &entry->_state_reliable; } else { - _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, - t_msg->_body._fragment._payload.len); + dbuf = &entry->_dbuf_best_effort; + dbuf_state = &entry->_state_best_effort; } - + // Allocate buffer if needed + if (*dbuf_state == _Z_DBUF_STATE_NULL) { + *dbuf = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); + if (_z_wbuf_capacity(dbuf) != Z_FRAG_MAX_SIZE) { + _Z_ERROR("Not enough memory to allocate peer defragmentation buffer"); + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + break; + } + *dbuf_state = _Z_DBUF_STATE_INIT; + } + // Process fragment data + if (*dbuf_state == _Z_DBUF_STATE_INIT) { + // Check overflow + if ((_z_wbuf_len(dbuf) + t_msg->_body._fragment._payload.len) > Z_FRAG_MAX_SIZE) { + *dbuf_state = _Z_DBUF_STATE_OVERFLOW; + } else { + // Fill buffer + _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, + t_msg->_body._fragment._payload.len); + } + } + // Process final fragment if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_M) == false) { - if (drop == true) { // Drop message if it exceeds the fragmentation size - _z_wbuf_reset(dbuf); + // Drop message if it exceeds the fragmentation size + if (*dbuf_state == _Z_DBUF_STATE_OVERFLOW) { + _Z_INFO("Fragment dropped because defragmentation buffer has overflown"); + _z_wbuf_clear(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; break; } - - _z_zbuf_t zbf = _z_wbuf_to_zbuf(dbuf); // Convert the defragmentation buffer into a decoding buffer - + // Convert the defragmentation buffer into a decoding buffer + _z_zbuf_t zbf = _z_wbuf_moved_as_zbuf(dbuf); + if (_z_zbuf_capacity(&zbf) == 0) { + _Z_ERROR("Failed to convert defragmentation buffer into a decoding buffer!"); + _z_wbuf_clear(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + break; + } + // Decode message _z_zenoh_message_t zm; ret = _z_network_message_decode(&zm, &zbf); zm._reliability = _z_t_msg_get_reliability(t_msg); @@ -218,14 +251,15 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, uint16_t mapping = entry->_peer_id; _z_msg_fix_mapping(&zm, mapping); _z_handle_network_message(ztm->_session, &zm, mapping); - _z_msg_clear(&zm); // Clear must be explicitly called for fragmented zenoh messages. Non-fragmented - // zenoh messages are released when their transport message is released. + } else { + _Z_INFO("Failed to decode defragmented message"); + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - + // Fragmented messages must be cleared. Non-fragmented messages are released with their transport. + _z_msg_clear(&zm); // Free the decoding buffer _z_zbuf_clear(&zbf); - // Reset the defragmentation buffer - _z_wbuf_reset(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; } #else _Z_INFO("Fragment dropped because fragmentation feature is deactivated"); @@ -280,18 +314,10 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_conduit_sn_list_decrement(entry->_sn_res, &entry->_sn_rx_sns); #if Z_FEATURE_FRAGMENTATION == 1 -#if Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION == 1 - entry->_dbuf_reliable = _z_wbuf_make(0, true); - entry->_dbuf_best_effort = _z_wbuf_make(0, true); -#else - entry->_dbuf_reliable = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); - entry->_dbuf_best_effort = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); - - if ((_z_wbuf_capacity(&entry->_dbuf_reliable) != Z_FRAG_MAX_SIZE) || - (_z_wbuf_capacity(&entry->_dbuf_best_effort) != Z_FRAG_MAX_SIZE)) { - _Z_ERROR("Not enough memory to allocate peer defragmentation buffers!"); - } -#endif + entry->_state_reliable = _Z_DBUF_STATE_NULL; + entry->_state_best_effort = _Z_DBUF_STATE_NULL; + entry->_dbuf_reliable = _z_wbuf_null(); + entry->_dbuf_best_effort = _z_wbuf_null(); #endif // Update lease time (set as ms during) entry->_lease = t_msg->_body._join._lease; diff --git a/src/transport/peer_entry.c b/src/transport/peer_entry.c index 7d72604e3..b5feffcdb 100644 --- a/src/transport/peer_entry.c +++ b/src/transport/peer_entry.c @@ -28,6 +28,8 @@ void _z_transport_peer_entry_clear(_z_transport_peer_entry_t *src) { void _z_transport_peer_entry_copy(_z_transport_peer_entry_t *dst, const _z_transport_peer_entry_t *src) { #if Z_FEATURE_FRAGMENTATION == 1 + dst->_state_reliable = src->_state_reliable; + dst->_state_best_effort = src->_state_best_effort; _z_wbuf_copy(&dst->_dbuf_reliable, &src->_dbuf_reliable); _z_wbuf_copy(&dst->_dbuf_best_effort, &src->_dbuf_best_effort); #endif diff --git a/src/transport/unicast/rx.c b/src/transport/unicast/rx.c index be7d55446..01c5e2014 100644 --- a/src/transport/unicast/rx.c +++ b/src/transport/unicast/rx.c @@ -111,6 +111,7 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t } else { #if Z_FEATURE_FRAGMENTATION == 1 _z_wbuf_clear(&ztu->_dbuf_reliable); + ztu->_state_reliable = _Z_DBUF_STATE_NULL; #endif _Z_INFO("Reliable message dropped because it is out of order"); break; @@ -121,6 +122,7 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t } else { #if Z_FEATURE_FRAGMENTATION == 1 _z_wbuf_clear(&ztu->_dbuf_best_effort); + ztu->_state_best_effort = _Z_DBUF_STATE_NULL; #endif _Z_INFO("Best effort message dropped because it is out of order"); break; @@ -141,44 +143,70 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t case _Z_MID_T_FRAGMENT: { _Z_DEBUG("Received Z_FRAGMENT message"); #if Z_FEATURE_FRAGMENTATION == 1 - _z_wbuf_t *dbuf = _Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R) - ? &ztu->_dbuf_reliable - : &ztu->_dbuf_best_effort; // Select the right defragmentation buffer - - bool drop = false; - if ((_z_wbuf_len(dbuf) + t_msg->_body._fragment._payload.len) > Z_FRAG_MAX_SIZE) { - // Filling the wbuf capacity as a way to signal the last fragment to reset the dbuf - // Otherwise, last (smaller) fragments can be understood as a complete message - _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, _z_wbuf_space_left(dbuf)); - drop = true; + _z_wbuf_t *dbuf; + uint8_t *dbuf_state; + // Select the right defragmentation buffer + if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R)) { + dbuf = &ztu->_dbuf_reliable; + dbuf_state = &ztu->_state_reliable; } else { - _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, - t_msg->_body._fragment._payload.len); + dbuf = &ztu->_dbuf_best_effort; + dbuf_state = &ztu->_state_best_effort; } - + // Allocate buffer if needed + if (*dbuf_state == _Z_DBUF_STATE_NULL) { + *dbuf = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); + if (_z_wbuf_capacity(dbuf) != Z_FRAG_MAX_SIZE) { + _Z_ERROR("Not enough memory to allocate transport defragmentation buffer"); + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + break; + } + *dbuf_state = _Z_DBUF_STATE_INIT; + } + // Process fragment data + if (*dbuf_state == _Z_DBUF_STATE_INIT) { + // Check overflow + if ((_z_wbuf_len(dbuf) + t_msg->_body._fragment._payload.len) > Z_FRAG_MAX_SIZE) { + *dbuf_state = _Z_DBUF_STATE_OVERFLOW; + } else { + // Fill buffer + _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, + t_msg->_body._fragment._payload.len); + } + } + // Process final fragment if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_M) == false) { - if (drop == true) { // Drop message if it exceeds the fragmentation size - _z_wbuf_reset(dbuf); + // Drop message if it exceeds the fragmentation size + if (*dbuf_state == _Z_DBUF_STATE_OVERFLOW) { + _Z_INFO("Fragment dropped because defragmentation buffer has overflown"); + _z_wbuf_clear(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; break; } - - _z_zbuf_t zbf = _z_wbuf_to_zbuf(dbuf); // Convert the defragmentation buffer into a decoding buffer - + // Convert the defragmentation buffer into a decoding buffer + _z_zbuf_t zbf = _z_wbuf_moved_as_zbuf(dbuf); + if (_z_zbuf_capacity(&zbf) == 0) { + _Z_ERROR("Failed to convert defragmentation buffer into a decoding buffer!"); + _z_wbuf_clear(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + break; + } + // Decode message _z_zenoh_message_t zm; ret = _z_network_message_decode(&zm, &zbf); zm._reliability = _z_t_msg_get_reliability(t_msg); if (ret == _Z_RES_OK) { _z_handle_network_message(ztu->_session, &zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); - _z_msg_clear(&zm); // Clear must be explicitly called for fragmented zenoh messages. Non-fragmented - // zenoh messages are released when their transport message is released. } else { - _Z_DEBUG("Failed to decode defragmented message"); + _Z_INFO("Failed to decode defragmented message"); + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - + // Fragmented messages must be cleared. Non-fragmented messages are released with their transport. + _z_msg_clear(&zm); // Free the decoding buffer _z_zbuf_clear(&zbf); - // Reset the defragmentation buffer - _z_wbuf_reset(dbuf); + *dbuf_state = _Z_DBUF_STATE_NULL; } #else _Z_INFO("Fragment dropped because fragmentation feature is deactivated"); diff --git a/src/transport/unicast/transport.c b/src/transport/unicast/transport.c index 2109eff54..fae652567 100644 --- a/src/transport/unicast/transport.c +++ b/src/transport/unicast/transport.c @@ -51,19 +51,8 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, // Initialize the read and write buffers if (ret == _Z_RES_OK) { uint16_t mtu = (zl->_mtu < param->_batch_size) ? zl->_mtu : param->_batch_size; - size_t dbuf_size = 0; size_t wbuf_size = mtu; size_t zbuf_size = param->_batch_size; - bool expandable = false; - - // Set expandable on stream link - if (zl->_cap._flow == Z_LINK_CAP_FLOW_STREAM) { - expandable = true; - } -#if Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION == 0 - expandable = false; - dbuf_size = Z_FRAG_MAX_SIZE; -#endif // Initialize tx rx buffers zt->_transport._unicast._wbuf = _z_wbuf_make(wbuf_size, false); @@ -86,35 +75,10 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, #if Z_FEATURE_FRAGMENTATION == 1 // Initialize the defragmentation buffers - zt->_transport._unicast._dbuf_reliable = _z_wbuf_make(dbuf_size, expandable); - zt->_transport._unicast._dbuf_best_effort = _z_wbuf_make(dbuf_size, expandable); - - // Clean up the buffers if one of them failed to be allocated - if ( -#if Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION == 0 - (_z_wbuf_capacity(&zt->_transport._unicast._dbuf_reliable) != dbuf_size) || - (_z_wbuf_capacity(&zt->_transport._unicast._dbuf_best_effort) != dbuf_size)) { -#else - (_z_wbuf_capacity(&zt->_transport._unicast._dbuf_reliable) != Z_IOSLICE_SIZE) || - (_z_wbuf_capacity(&zt->_transport._unicast._dbuf_best_effort) != Z_IOSLICE_SIZE)) { -#endif - ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; - _Z_ERROR("Not enough memory to allocate transport defragmentation buffers!"); - - _z_wbuf_clear(&zt->_transport._unicast._dbuf_reliable); - _z_wbuf_clear(&zt->_transport._unicast._dbuf_best_effort); - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_drop(&zt->_transport._unicast._mutex_tx); - _z_mutex_drop(&zt->_transport._unicast._mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - - _z_wbuf_clear(&zt->_transport._unicast._wbuf); - _z_zbuf_clear(&zt->_transport._unicast._zbuf); - } -#else - _ZP_UNUSED(dbuf_size); - _ZP_UNUSED(expandable); + zt->_transport._unicast._state_reliable = _Z_DBUF_STATE_NULL; + zt->_transport._unicast._state_best_effort = _Z_DBUF_STATE_NULL; + zt->_transport._unicast._dbuf_reliable = _z_wbuf_null(); + zt->_transport._unicast._dbuf_best_effort = _z_wbuf_null(); #endif // Z_FEATURE_FRAGMENTATION == 1 } diff --git a/tests/z_msgcodec_test.c b/tests/z_msgcodec_test.c index 1db9f5885..c881f8f4e 100644 --- a/tests/z_msgcodec_test.c +++ b/tests/z_msgcodec_test.c @@ -341,7 +341,7 @@ void assert_eq_locator_array(const _z_locator_array_t *left, const _z_locator_ar _z_string_t ls = _z_locator_to_string(l); _z_string_t rs = _z_locator_to_string(r); - printf("%s:%s", _z_string_data(&ls), _z_string_data(&rs)); + printf("%.*s:%.*s", (int)_z_string_len(&ls), _z_string_data(&ls), (int)_z_string_len(&rs), _z_string_data(&rs)); if (i < left->_len - 1) printf(" "); _z_string_clear(&ls); From ae30a6088ad5e9b1cb7d36b1fb5e051b7500d466 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Thu, 24 Oct 2024 14:39:23 +0200 Subject: [PATCH 05/17] Add manual batching mechanism (#758) * feat: add _vec_steal and _vec_null * chore: remove stray ; * feat: add network message copy function * fix: memory leak * feat: abstract transport mutex * build: add batching config token * feat: add transport batching state functions * feat: add multicast batching * refactor: unicast tx function * feat: add unicast tx batching * feat: add batching api * fix: multicast peer mutex * fix: single thread compilation * feat: restore wbuf if batch if too full * fix: redundant buf reset * feat: pass sn by value * feat: send fragment with batching if needed * feat: rename batch api functions * feat: switch transport mutex functions to static inline * doc: add batching api doc * fix: boolean condition --- CMakeLists.txt | 1 + include/zenoh-pico/api/primitives.h | 26 ++ include/zenoh-pico/collections/vec.h | 3 + include/zenoh-pico/config.h | 1 + include/zenoh-pico/config.h.in | 1 + .../zenoh-pico/protocol/definitions/network.h | 1 + include/zenoh-pico/session/utils.h | 1 + .../transport/multicast/transport.h | 31 +- include/zenoh-pico/transport/multicast/tx.h | 1 + include/zenoh-pico/transport/transport.h | 22 ++ .../zenoh-pico/transport/unicast/transport.h | 26 +- include/zenoh-pico/transport/unicast/tx.h | 1 + src/api/api.c | 19 ++ src/collections/vec.c | 5 + src/protocol/codec/declarations.c | 1 - src/protocol/codec/transport.c | 1 + src/protocol/definitions/network.c | 128 ++++++++ src/session/tx.c | 22 +- src/transport/multicast/rx.c | 25 +- src/transport/multicast/transport.c | 14 +- src/transport/multicast/tx.c | 295 +++++++++++------ src/transport/raweth/rx.c | 13 +- src/transport/raweth/tx.c | 59 ++-- src/transport/transport.c | 42 +++ src/transport/unicast/rx.c | 13 +- src/transport/unicast/transport.c | 70 ++-- src/transport/unicast/tx.c | 302 ++++++++++++------ 27 files changed, 815 insertions(+), 309 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7949110a3..7ab40bf08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,6 +206,7 @@ set(Z_FEATURE_RAWETH_TRANSPORT 0 CACHE STRING "Toggle raw ethernet transport") set(Z_FEATURE_TCP_NODELAY 1 CACHE STRING "Toggle TCP_NODELAY") set(Z_FEATURE_LOCAL_SUBSCRIBER 0 CACHE STRING "Toggle local subscriptions") set(Z_FEATURE_PUBLISHER_SESSION_CHECK 1 CACHE STRING "Toggle publisher session check") +set(Z_FEATURE_BATCHING 1 CACHE STRING "Toggle batching") add_compile_definitions("Z_BUILD_DEBUG=$") message(STATUS "Building with feature confing:\n\ diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index 79a01f8c8..07c1e4e35 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -2056,6 +2056,32 @@ z_result_t z_declare_background_subscriber(const z_loaned_session_t *zs, const z const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *subscriber); #endif +#if Z_FEATURE_BATCHING == 1 +/** + * Activate the batching mechanism. + * Any message that would have been sent on the network by a subsequent api call (e.g z_put, z_get) + * will be instead stored until the batch is flushed with :c:func:`zp_batch_flush`. + * + * Parameters: + * zs: Pointer to a :c:type:`z_loaned_session_t` that will start batching messages. + * + * Return: + * ``0`` if batching started, ``negative value`` otherwise. + */ +z_result_t zp_batch_start(const z_loaned_session_t *zs); + +/** + * Deactivate the batching mechanism and flush the messages that were stored. + * + * Parameters: + * zs: Pointer to a :c:type:`z_loaned_session_t` that will stop batching messages. + * + * Return: + * ``0`` if batching stopped and batch successfully sent, ``negative value`` otherwise. + */ +z_result_t zp_batch_flush(const z_loaned_session_t *zs); +#endif + /************* Multi Thread Tasks helpers **************/ /** * Builds a :c:type:`zp_task_read_options_t` with default value. diff --git a/include/zenoh-pico/collections/vec.h b/include/zenoh-pico/collections/vec.h index d1c12ec6b..36af17dcc 100644 --- a/include/zenoh-pico/collections/vec.h +++ b/include/zenoh-pico/collections/vec.h @@ -29,8 +29,10 @@ typedef struct { void **_val; } _z_vec_t; +static inline _z_vec_t _z_vec_null(void) { return (_z_vec_t){0}; } _z_vec_t _z_vec_make(size_t capacity); void _z_vec_copy(_z_vec_t *dst, const _z_vec_t *src, z_element_clone_f f); +void _z_vec_steal(_z_vec_t *dst, _z_vec_t *src); size_t _z_vec_len(const _z_vec_t *v); bool _z_vec_is_empty(const _z_vec_t *v); @@ -59,6 +61,7 @@ void _z_vec_release(_z_vec_t *v); static inline void name##_vec_copy(name##_vec_t *dst, const name##_vec_t *src) { \ _z_vec_copy(dst, src, name##_elem_clone); \ } \ + static inline void name##_vec_steal(name##_vec_t *dst, name##_vec_t *src) { _z_vec_steal(dst, src); } \ static inline void name##_vec_reset(name##_vec_t *v) { _z_vec_reset(v, name##_elem_free); } \ static inline void name##_vec_clear(name##_vec_t *v) { _z_vec_clear(v, name##_elem_free); } \ static inline void name##_vec_free(name##_vec_t **v) { _z_vec_free(v, name##_elem_free); } \ diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index aadb2aae7..e3a76d963 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -44,6 +44,7 @@ #define Z_FEATURE_TCP_NODELAY 1 #define Z_FEATURE_LOCAL_SUBSCRIBER 0 #define Z_FEATURE_PUBLISHER_SESSION_CHECK 1 +#define Z_FEATURE_BATCHING 1 // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/include/zenoh-pico/config.h.in b/include/zenoh-pico/config.h.in index 062931aad..a8738d6a4 100644 --- a/include/zenoh-pico/config.h.in +++ b/include/zenoh-pico/config.h.in @@ -44,6 +44,7 @@ #define Z_FEATURE_TCP_NODELAY @Z_FEATURE_TCP_NODELAY@ #define Z_FEATURE_LOCAL_SUBSCRIBER @Z_FEATURE_LOCAL_SUBSCRIBER@ #define Z_FEATURE_PUBLISHER_SESSION_CHECK @Z_FEATURE_PUBLISHER_SESSION_CHECK@ +#define Z_FEATURE_BATCHING @Z_FEATURE_BATCHING@ // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/include/zenoh-pico/protocol/definitions/network.h b/include/zenoh-pico/protocol/definitions/network.h index 476831765..de203eb7e 100644 --- a/include/zenoh-pico/protocol/definitions/network.h +++ b/include/zenoh-pico/protocol/definitions/network.h @@ -302,5 +302,6 @@ _z_network_message_t _z_n_msg_make_response_final(_z_zint_t rid); _z_network_message_t _z_n_msg_make_declare(_z_declaration_t declaration, bool has_interest_id, uint32_t interest_id); _z_network_message_t _z_n_msg_make_push(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_push_body_t) body); _z_network_message_t _z_n_msg_make_interest(_z_interest_t interest); +z_result_t _z_n_msg_copy(_z_network_message_t *dst, const _z_network_message_t *src); #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_NETWORK_H */ diff --git a/include/zenoh-pico/session/utils.h b/include/zenoh-pico/session/utils.h index 75eaac2e8..db7969a3c 100644 --- a/include/zenoh-pico/session/utils.h +++ b/include/zenoh-pico/session/utils.h @@ -33,6 +33,7 @@ z_result_t _z_session_close(_z_session_t *zn, uint8_t reason); z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t *z_msg, uint16_t local_peer_id); z_result_t _z_send_n_msg(_z_session_t *zn, _z_network_message_t *n_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl); +z_result_t _z_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl); void _zp_session_lock_mutex(_z_session_t *zn); void _zp_session_unlock_mutex(_z_session_t *zn); diff --git a/include/zenoh-pico/transport/multicast/transport.h b/include/zenoh-pico/transport/multicast/transport.h index fa9cd085c..802393e53 100644 --- a/include/zenoh-pico/transport/multicast/transport.h +++ b/include/zenoh-pico/transport/multicast/transport.h @@ -26,4 +26,33 @@ z_result_t _z_multicast_open_client(_z_transport_multicast_establish_param_t *pa z_result_t _z_multicast_send_close(_z_transport_multicast_t *ztm, uint8_t reason, bool link_only); z_result_t _z_multicast_transport_close(_z_transport_multicast_t *ztm, uint8_t reason); void _z_multicast_transport_clear(_z_transport_t *zt); -#endif /* ZENOH_PICO_MULTICAST_TRANSPORT_H */ + +#if (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) && Z_FEATURE_MULTI_THREAD == 1 +static inline z_result_t _z_multicast_tx_mutex_lock(_z_transport_multicast_t *ztm, bool block) { + if (block) { + _z_mutex_lock(&ztm->_mutex_tx); + return _Z_RES_OK; + } else { + return _z_mutex_try_lock(&ztm->_mutex_tx); + } +} +static inline void _z_multicast_tx_mutex_unlock(_z_transport_multicast_t *ztm) { _z_mutex_unlock(&ztm->_mutex_tx); } +static inline void _z_multicast_rx_mutex_lock(_z_transport_multicast_t *ztm) { _z_mutex_lock(&ztm->_mutex_rx); } +static inline void _z_multicast_rx_mutex_unlock(_z_transport_multicast_t *ztm) { _z_mutex_unlock(&ztm->_mutex_rx); } +static inline void _z_multicast_peer_mutex_lock(_z_transport_multicast_t *ztm) { _z_mutex_lock(&ztm->_mutex_peer); } +static inline void _z_multicast_peer_mutex_unlock(_z_transport_multicast_t *ztm) { _z_mutex_unlock(&ztm->_mutex_peer); } + +#else +static inline z_result_t _z_multicast_tx_mutex_lock(_z_transport_multicast_t *ztm, bool block) { + _ZP_UNUSED(ztm); + _ZP_UNUSED(block); + return _Z_RES_OK; +} +static inline void _z_multicast_tx_mutex_unlock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } +static inline void _z_multicast_rx_mutex_lock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } +static inline void _z_multicast_rx_mutex_unlock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } +static inline void _z_multicast_peer_mutex_lock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } +static inline void _z_multicast_peer_mutex_unlock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } + +#endif // (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) && Z_FEATURE_MULTI_THREAD == 1 +#endif /* ZENOH_PICO_MULTICAST_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/multicast/tx.h b/include/zenoh-pico/transport/multicast/tx.h index c9721523a..836b441b6 100644 --- a/include/zenoh-pico/transport/multicast/tx.h +++ b/include/zenoh-pico/transport/multicast/tx.h @@ -21,5 +21,6 @@ z_result_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl); z_result_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg); +z_result_t _z_multicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl); #endif /* ZENOH_PICO_MULTICAST_TX_H */ diff --git a/include/zenoh-pico/transport/transport.h b/include/zenoh-pico/transport/transport.h index 5075b39b7..1efc9ccd0 100644 --- a/include/zenoh-pico/transport/transport.h +++ b/include/zenoh-pico/transport/transport.h @@ -31,6 +31,11 @@ enum _z_dbuf_state_e { _Z_DBUF_STATE_OVERFLOW = 2, }; +enum _z_batching_state_e { + _Z_BATCHING_IDLE = 0, + _Z_BATCHING_ACTIVE = 1, +}; + typedef struct { #if Z_FEATURE_FRAGMENTATION == 1 // Defragmentation buffers @@ -105,6 +110,12 @@ typedef struct { _z_zint_t _sn_rx_best_effort; volatile _z_zint_t _lease; +// Transport batching +#if Z_FEATURE_BATCHING == 1 + uint8_t _batch_state; + _z_network_message_vec_t _batch; +#endif + #if Z_FEATURE_MULTI_THREAD == 1 _z_task_t *_read_task; _z_task_t *_lease_task; @@ -129,6 +140,12 @@ typedef struct _z_transport_multicast_t { _z_mutex_t _mutex_peer; #endif // Z_FEATURE_MULTI_THREAD == 1 +// Transport batching +#if Z_FEATURE_BATCHING == 1 + uint8_t _batch_state; + _z_network_message_vec_t _batch; +#endif + _z_link_t _link; // TX and RX buffers @@ -192,4 +209,9 @@ z_result_t _z_transport_close(_z_transport_t *zt, uint8_t reason); void _z_transport_clear(_z_transport_t *zt); void _z_transport_free(_z_transport_t **zt); +#if Z_FEATURE_BATCHING == 1 +bool _z_transport_start_batching(_z_transport_t *zt); +void _z_transport_stop_batching(_z_transport_t *zt); +#endif + #endif /* INCLUDE_ZENOH_PICO_TRANSPORT_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/unicast/transport.h b/include/zenoh-pico/transport/unicast/transport.h index 4b60b7c70..df0ca1ff8 100644 --- a/include/zenoh-pico/transport/unicast/transport.h +++ b/include/zenoh-pico/transport/unicast/transport.h @@ -26,4 +26,28 @@ z_result_t _z_unicast_open_peer(_z_transport_unicast_establish_param_t *param, c z_result_t _z_unicast_send_close(_z_transport_unicast_t *ztu, uint8_t reason, bool link_only); z_result_t _z_unicast_transport_close(_z_transport_unicast_t *ztu, uint8_t reason); void _z_unicast_transport_clear(_z_transport_t *zt); -#endif /* ZENOH_PICO_UNICAST_TRANSPORT_H */ + +#if Z_FEATURE_UNICAST_TRANSPORT == 1 && Z_FEATURE_MULTI_THREAD == 1 +static inline z_result_t _z_unicast_tx_mutex_lock(_z_transport_unicast_t *ztu, bool block) { + if (block) { + _z_mutex_lock(&ztu->_mutex_tx); + return _Z_RES_OK; + } else { + return _z_mutex_try_lock(&ztu->_mutex_tx); + } +} +static inline void _z_unicast_tx_mutex_unlock(_z_transport_unicast_t *ztu) { _z_mutex_unlock(&ztu->_mutex_tx); } +static inline void _z_unicast_rx_mutex_lock(_z_transport_unicast_t *ztu) { _z_mutex_lock(&ztu->_mutex_rx); } +static inline void _z_unicast_rx_mutex_unlock(_z_transport_unicast_t *ztu) { _z_mutex_unlock(&ztu->_mutex_rx); } + +#else +static inline z_result_t _z_unicast_tx_mutex_lock(_z_transport_unicast_t *ztu, bool block) { + _ZP_UNUSED(ztu); + _ZP_UNUSED(block); + return _Z_RES_OK; +} +static inline void _z_unicast_tx_mutex_unlock(_z_transport_unicast_t *ztu) { _ZP_UNUSED(ztu); } +static inline void _z_unicast_rx_mutex_lock(_z_transport_unicast_t *ztu) { _ZP_UNUSED(ztu); } +static inline void _z_unicast_rx_mutex_unlock(_z_transport_unicast_t *ztu) { _ZP_UNUSED(ztu); } +#endif // Z_FEATURE_UNICAST_TRANSPORT == 1 && Z_FEATURE_MULTI_THREAD == 1 +#endif /* ZENOH_PICO_UNICAST_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/unicast/tx.h b/include/zenoh-pico/transport/unicast/tx.h index 56a33bfdd..41c991596 100644 --- a/include/zenoh-pico/transport/unicast/tx.h +++ b/include/zenoh-pico/transport/unicast/tx.h @@ -21,5 +21,6 @@ z_result_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl); z_result_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_message_t *t_msg); +z_result_t _z_unicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl); #endif /* ZENOH_PICO_TRANSPORT_LINK_TX_H */ diff --git a/src/api/api.c b/src/api/api.c index 6df2c10ad..3e1149a42 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -1438,6 +1438,25 @@ const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *sub) } #endif +#if Z_FEATURE_BATCHING == 1 +z_result_t zp_batch_start(const z_loaned_session_t *zs) { + if (_Z_RC_IS_NULL(zs)) { + return _Z_ERR_SESSION_CLOSED; + } + _z_session_t *session = _Z_RC_IN_VAL(zs); + return _z_transport_start_batching(&session->_tp) ? _Z_RES_OK : _Z_ERR_GENERIC; +} + +z_result_t zp_batch_flush(const z_loaned_session_t *zs) { + _z_session_t *session = _Z_RC_IN_VAL(zs); + if (_Z_RC_IS_NULL(zs)) { + return _Z_ERR_SESSION_CLOSED; + } + _z_transport_stop_batching(&session->_tp); + return _z_send_n_batch(session, Z_RELIABILITY_DEFAULT, Z_CONGESTION_CONTROL_DEFAULT); +} +#endif + /**************** Tasks ****************/ void zp_task_read_options_default(zp_task_read_options_t *options) { #if Z_FEATURE_MULTI_THREAD == 1 diff --git a/src/collections/vec.c b/src/collections/vec.c index da5fca7f0..d0f1a5c92 100644 --- a/src/collections/vec.c +++ b/src/collections/vec.c @@ -41,6 +41,11 @@ void _z_vec_copy(_z_vec_t *dst, const _z_vec_t *src, z_element_clone_f d_f) { } } +void _z_vec_steal(_z_vec_t *dst, _z_vec_t *src) { + *dst = *src; + *src = _z_vec_null(); +} + void _z_vec_reset(_z_vec_t *v, z_element_free_f free_f) { for (size_t i = 0; i < v->_len; i++) { free_f(&v->_val[i]); diff --git a/src/protocol/codec/declarations.c b/src/protocol/codec/declarations.c index 76db9dea0..905aad397 100644 --- a/src/protocol/codec/declarations.c +++ b/src/protocol/codec/declarations.c @@ -163,7 +163,6 @@ z_result_t _z_declaration_encode(_z_wbuf_t *wbf, const _z_declaration_t *decl) { case _Z_DECL_FINAL: { ret = _z_decl_final_encode(wbf); } break; - ; } return ret; } diff --git a/src/protocol/codec/transport.c b/src/protocol/codec/transport.c index 1208e3fee..e77e62f88 100644 --- a/src/protocol/codec/transport.c +++ b/src/protocol/codec/transport.c @@ -368,6 +368,7 @@ z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header _z_network_message_vec_append(&msg->_messages, nm); } else { _z_n_msg_free(&nm); + _z_network_message_vec_clear(&msg->_messages); _z_zbuf_set_rpos(zbf, r_pos); // Restore the reading position of the iobfer diff --git a/src/protocol/definitions/network.c b/src/protocol/definitions/network.c index 10cb27cde..1364ac039 100644 --- a/src/protocol/definitions/network.c +++ b/src/protocol/definitions/network.c @@ -73,6 +73,16 @@ _z_push_body_t _z_push_body_steal(_z_push_body_t *msg) { return ret; } +static z_result_t _z_push_body_copy(_z_push_body_t *dst, const _z_push_body_t *src) { + if (src->_is_put) { + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._put._attachment, &src->_body._put._attachment)); + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._put._payload, &src->_body._put._payload)); + } else { + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._del._attachment, &src->_body._del._attachment)); + } + return _Z_RES_OK; +} + void _z_n_msg_response_final_clear(_z_n_msg_response_final_t *msg) { (void)(msg); } void _z_n_msg_push_clear(_z_n_msg_push_t *msg) { @@ -224,6 +234,124 @@ _z_network_message_t _z_n_msg_make_interest(_z_interest_t interest) { }; } +static z_result_t _z_n_msg_push_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst->_body._push._key, &src->_body._push._key)); + return _z_push_body_copy(&dst->_body._push._body, &src->_body._push._body); +} + +static z_result_t _z_n_msg_request_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst->_body._request._key, &src->_body._request._key)); + switch (src->_body._request._tag) { + case _Z_REQUEST_QUERY: + _Z_RETURN_IF_ERR(_z_slice_copy(&dst->_body._request._body._query._parameters, + &src->_body._request._body._query._parameters)); + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._request._body._query._ext_attachment, + &src->_body._request._body._query._ext_attachment)); + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._request._body._query._ext_value.payload, + &src->_body._request._body._query._ext_value.payload)); + break; + case _Z_REQUEST_PUT: + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._request._body._put._attachment, + &src->_body._request._body._put._attachment)); + _Z_RETURN_IF_ERR( + _z_bytes_copy(&dst->_body._request._body._put._payload, &src->_body._request._body._put._payload)); + break; + case _Z_REQUEST_DEL: + _Z_RETURN_IF_ERR(_z_bytes_copy(&dst->_body._request._body._del._attachment, + &src->_body._request._body._del._attachment)); + break; + } + return _Z_RES_OK; +} + +static z_result_t _z_n_msg_response_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst->_body._response._key, &src->_body._response._key)); + switch (src->_body._response._tag) { + case _Z_RESPONSE_BODY_REPLY: + _Z_RETURN_IF_ERR( + _z_push_body_copy(&dst->_body._response._body._reply._body, &src->_body._response._body._reply._body)); + break; + case _Z_RESPONSE_BODY_ERR: + _Z_RETURN_IF_ERR( + _z_bytes_copy(&dst->_body._response._body._err._payload, &src->_body._response._body._err._payload)); + break; + } + return _Z_RES_OK; +} + +static z_result_t _z_n_msg_response_final_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + return _Z_RES_OK; +} + +static z_result_t _z_n_msg_declare_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + const _z_declaration_t *src_decl = &src->_body._declare._decl; + _z_declaration_t *dst_decl = &dst->_body._declare._decl; + switch (src_decl->_tag) { + case _Z_DECL_KEXPR: { + _Z_RETURN_IF_ERR( + _z_keyexpr_copy(&dst_decl->_body._decl_kexpr._keyexpr, &src_decl->_body._decl_kexpr._keyexpr)); + } break; + case _Z_DECL_SUBSCRIBER: { + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst_decl->_body._decl_subscriber._keyexpr, + &src_decl->_body._decl_subscriber._keyexpr)); + } break; + case _Z_UNDECL_SUBSCRIBER: { + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst_decl->_body._undecl_subscriber._ext_keyexpr, + &src_decl->_body._undecl_subscriber._ext_keyexpr)); + } break; + case _Z_DECL_QUERYABLE: { + _Z_RETURN_IF_ERR( + _z_keyexpr_copy(&dst_decl->_body._decl_queryable._keyexpr, &src_decl->_body._decl_queryable._keyexpr)); + } break; + case _Z_UNDECL_QUERYABLE: { + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst_decl->_body._undecl_queryable._ext_keyexpr, + &src_decl->_body._undecl_queryable._ext_keyexpr)); + } break; + case _Z_DECL_TOKEN: { + _Z_RETURN_IF_ERR( + _z_keyexpr_copy(&dst_decl->_body._decl_token._keyexpr, &src_decl->_body._decl_token._keyexpr)); + } break; + case _Z_UNDECL_TOKEN: { + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst_decl->_body._undecl_token._ext_keyexpr, + &src_decl->_body._undecl_token._ext_keyexpr)); + } break; + default: + break; + } + return _Z_RES_OK; +} + +static z_result_t _z_n_msg_interest_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + memcpy(dst, src, sizeof(_z_network_message_t)); + _Z_RETURN_IF_ERR( + _z_keyexpr_copy(&dst->_body._interest._interest._keyexpr, &src->_body._interest._interest._keyexpr)); + return _Z_RES_OK; +} + +z_result_t _z_n_msg_copy(_z_network_message_t *dst, const _z_network_message_t *src) { + switch (src->_tag) { + case _Z_N_PUSH: + return _z_n_msg_push_copy(dst, src); + case _Z_N_REQUEST: + return _z_n_msg_request_copy(dst, src); + case _Z_N_RESPONSE: + return _z_n_msg_response_copy(dst, src); + case _Z_N_RESPONSE_FINAL: + return _z_n_msg_response_final_copy(dst, src); + case _Z_N_DECLARE: + return _z_n_msg_declare_copy(dst, src); + case _Z_N_INTEREST: + return _z_n_msg_interest_copy(dst, src); + default: + return _Z_ERR_ENTITY_UNKNOWN; + } +} + void _z_msg_fix_mapping(_z_zenoh_message_t *msg, uint16_t mapping) { switch (msg->_tag) { case _Z_N_DECLARE: { diff --git a/src/session/tx.c b/src/session/tx.c index 64746930e..6401fb623 100644 --- a/src/session/tx.c +++ b/src/session/tx.c @@ -21,7 +21,6 @@ z_result_t _z_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { z_result_t ret = _Z_RES_OK; - _Z_DEBUG(">> send network message"); // Call transport function switch (zn->_tp._type) { case _Z_TRANSPORT_UNICAST_TYPE: @@ -39,3 +38,24 @@ z_result_t _z_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_ } return ret; } + +z_result_t _z_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { + z_result_t ret = _Z_RES_OK; + // Call transport function + switch (zn->_tp._type) { + case _Z_TRANSPORT_UNICAST_TYPE: + ret = _z_unicast_send_n_batch(zn, reliability, cong_ctrl); + break; + case _Z_TRANSPORT_MULTICAST_TYPE: + ret = _z_multicast_send_n_batch(zn, reliability, cong_ctrl); + break; + case _Z_TRANSPORT_RAWETH_TYPE: + _Z_INFO("Batching not yet supported on raweth transport"); + ret = _Z_ERR_TRANSPORT_TX_FAILED; + break; + default: + ret = _Z_ERR_TRANSPORT_NOT_AVAILABLE; + break; + } + return ret; +} diff --git a/src/transport/multicast/rx.c b/src/transport/multicast/rx.c index 32bc570fb..4fb823e46 100644 --- a/src/transport/multicast/rx.c +++ b/src/transport/multicast/rx.c @@ -25,6 +25,7 @@ #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/multicast/rx.h" +#include "zenoh-pico/transport/multicast/transport.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -34,11 +35,7 @@ static z_result_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_t _Z_DEBUG(">> recv session msg"); z_result_t ret = _Z_RES_OK; -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire the lock - _z_mutex_lock(&ztm->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_multicast_rx_mutex_lock(ztm); size_t to_read = 0; do { switch (ztm->_link._cap._flow) { @@ -81,11 +78,7 @@ static z_result_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_t _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_zbuf)); ret = _z_transport_message_decode(t_msg, &ztm->_zbuf); } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_multicast_rx_mutex_unlock(ztm); return ret; } @@ -124,11 +117,7 @@ static _z_transport_peer_entry_t *_z_find_peer_entry(_z_transport_peer_entry_lis z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr) { z_result_t ret = _Z_RES_OK; -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire and keep the lock - _z_mutex_lock(&ztm->_mutex_peer); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_multicast_peer_mutex_lock(ztm); // Mark the session that we have received data from this peer _z_transport_peer_entry_t *entry = _z_find_peer_entry(ztm->_peers, addr); switch (_Z_MID(t_msg->_header)) { @@ -369,11 +358,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, break; } } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_peer); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_multicast_peer_mutex_unlock(ztm); return ret; } diff --git a/src/transport/multicast/transport.c b/src/transport/multicast/transport.c index b190bb468..4ff1f3717 100644 --- a/src/transport/multicast/transport.c +++ b/src/transport/multicast/transport.c @@ -11,6 +11,8 @@ // Contributors: // ZettaScale Zenoh Team, +#include "zenoh-pico/transport/multicast/transport.h" + #include #include #include @@ -50,6 +52,13 @@ z_result_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, default: return _Z_ERR_GENERIC; } + +// Initialize batching data +#if Z_FEATURE_BATCHING == 1 + ztm->_batch_state = _Z_BATCHING_IDLE; + ztm->_batch = _z_network_message_vec_make(0); +#endif + #if Z_FEATURE_MULTI_THREAD == 1 // Initialize the mutexes ret = _z_mutex_init(&ztm->_mutex_tx); @@ -197,6 +206,10 @@ void _z_multicast_transport_clear(_z_transport_t *zt) { _z_mutex_drop(&ztm->_mutex_peer); #endif // Z_FEATURE_MULTI_THREAD == 1 +#if Z_FEATURE_BATCHING == 1 + _z_network_message_vec_clear(&ztm->_batch); +#endif + // Clean up the buffers _z_wbuf_clear(&ztm->_wbuf); _z_zbuf_clear(&ztm->_zbuf); @@ -243,7 +256,6 @@ z_result_t _z_multicast_transport_close(_z_transport_multicast_t *ztm, uint8_t r _ZP_UNUSED(ztm); _ZP_UNUSED(reason); return _Z_ERR_TRANSPORT_NOT_AVAILABLE; - ; } void _z_multicast_transport_clear(_z_transport_t *zt) { _ZP_UNUSED(zt); } diff --git a/src/transport/multicast/tx.c b/src/transport/multicast/tx.c index df5b3bcdc..572134c11 100644 --- a/src/transport/multicast/tx.c +++ b/src/transport/multicast/tx.c @@ -17,6 +17,7 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/protocol/codec/network.h" #include "zenoh-pico/protocol/codec/transport.h" +#include "zenoh-pico/transport/multicast/transport.h" #include "zenoh-pico/transport/multicast/tx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -28,7 +29,7 @@ * Make sure that the following mutexes are locked before calling this function: * - ztm->_mutex_inner */ -_z_zint_t __unsafe_z_multicast_get_sn(_z_transport_multicast_t *ztm, z_reliability_t reliability) { +static _z_zint_t __unsafe_z_multicast_get_sn(_z_transport_multicast_t *ztm, z_reliability_t reliability) { _z_zint_t sn; if (reliability == Z_RELIABILITY_RELIABLE) { sn = ztm->_sn_tx_reliable; @@ -40,126 +41,224 @@ _z_zint_t __unsafe_z_multicast_get_sn(_z_transport_multicast_t *ztm, z_reliabili return sn; } -z_result_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg) { - z_result_t ret = _Z_RES_OK; - _Z_DEBUG(">> send session message"); +#if Z_FEATURE_FRAGMENTATION == 1 +static z_result_t __unsafe_z_multicast_send_fragment(_z_transport_multicast_t *ztm, _z_wbuf_t *fbf, + const _z_network_message_t *n_msg, z_reliability_t reliability, + _z_zint_t first_sn) { + bool is_first = true; + _z_zint_t sn = first_sn; + // Encode message on temp buffer + _Z_RETURN_IF_ERR(_z_network_message_encode(fbf, n_msg)); + // Fragment message + while (_z_wbuf_len(fbf) > 0) { + // Get fragment sequence number + if (!is_first) { + sn = __unsafe_z_multicast_get_sn(ztm, reliability); + } + is_first = false; + // Serialize fragment + __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); + z_result_t ret = __unsafe_z_serialize_zenoh_fragment(&ztm->_wbuf, fbf, reliability, sn); + if (ret != _Z_RES_OK) { + _Z_ERROR("Fragment serialization failed with err %d", ret); + return ret; + } + // Send fragment + __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztm->_link, &ztm->_wbuf)); + ztm->_transmitted = true; // Tell session we have transmitted data + } + return _Z_RES_OK; +} +#else +static z_result_t __unsafe_z_multicast_send_fragment(_z_transport_multicast_t *ztm, _z_wbuf_t *fbf, + const _z_network_message_t *n_msg, z_reliability_t reliability, + _z_zint_t first_sn) { + _ZP_UNUSED(ztm); + _ZP_UNUSED(fbf); + _ZP_UNUSED(n_msg); + _ZP_UNUSED(reliability); + _ZP_UNUSED(first_sn); + _Z_INFO("Sending the message required fragmentation feature that is deactivated."); + return _Z_RES_OK; +} +#endif // Z_FEATURE_FRAGMENTATION == 1 -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire the lock - _z_mutex_lock(&ztm->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 +static z_result_t __unsafe_z_multicast_message_send(_z_transport_multicast_t *ztm, const _z_network_message_t *n_msg, + z_reliability_t reliability) { + _Z_DEBUG("Send network message"); + // Encode frame header + __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); + _z_zint_t sn = __unsafe_z_multicast_get_sn(ztm, reliability); + _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); + _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, &t_msg)); + // Encode network message + z_result_t ret = _z_network_message_encode(&ztm->_wbuf, n_msg); + // The message does not fit in the current batch, let's fragment it + if (ret != _Z_RES_OK) { + // Create an expandable wbuf for fragmentation + _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); + // Send message as fragments + ret = __unsafe_z_multicast_send_fragment(ztm, &fbf, n_msg, reliability, sn); + // Clear the buffer as it's no longer required + _z_wbuf_clear(&fbf); + return ret; + } + // Send network message + __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztm->_link, &ztm->_wbuf)); + ztm->_transmitted = true; // Tell session we transmitted data + return _Z_RES_OK; +} - // Prepare the buffer eventually reserving space for the message length +#if Z_FEATURE_BATCHING == 1 +static z_result_t __unsafe_z_multicast_message_batch(_z_transport_multicast_t *ztm, const _z_network_message_t *n_msg) { + _Z_DEBUG("Batching network message"); + // Copy network message + _z_network_message_t *batch_msg = z_malloc(sizeof(_z_network_message_t)); + if (batch_msg == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + if (_z_n_msg_copy(batch_msg, n_msg) != _Z_RES_OK) { + z_free(batch_msg); + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + _z_network_message_vec_append(&ztm->_batch, batch_msg); + return _Z_RES_OK; +} + +static z_result_t __unsafe_multicast_batch_send(_z_transport_multicast_t *ztm, z_reliability_t reliability) { + z_result_t ret = _Z_RES_OK; + // Get network message number + size_t msg_nb = _z_network_message_vec_len(&ztm->_batch); + size_t msg_idx = 0; + size_t curr_msg_nb = 0; + if (msg_nb == 0) { + return _Z_RES_OK; + } + // Encode the frame header __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); + _z_zint_t sn = __unsafe_z_multicast_get_sn(ztm, reliability); + _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); + _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, &t_msg)); + size_t curr_wpos = _z_wbuf_get_wpos(&ztm->_wbuf); + // Process batch + while (msg_idx < msg_nb) { + // Encode a network message + _z_network_message_t *n_msg = _z_network_message_vec_get(&ztm->_batch, msg_idx); + assert(n_msg != NULL); + if (_z_network_message_encode(&ztm->_wbuf, n_msg) != _Z_RES_OK) { + // Remove partially encoded data + _z_wbuf_set_wpos(&ztm->_wbuf, curr_wpos); + // Handle case where one message is too big to fit in frame + if (curr_msg_nb == 0) { + _Z_INFO("Batch sending interrupted by a message needing to be fragmented."); + // Create an expandable wbuf for fragmentation + _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); + // Send message as fragments + ret = __unsafe_z_multicast_send_fragment(ztm, &fbf, n_msg, reliability, sn); + // Clear the buffer as it's no longer required + _z_wbuf_clear(&fbf); + if (ret != _Z_RES_OK) { + _Z_ERROR("Send fragmented message failed with err %d.", ret); + } + // Message is sent or skipped + msg_idx++; + } else { // Frame has messages but is full + _Z_INFO("Sending batch in multiple frames because it is too big for one"); + // Send frame + __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztm->_link, &ztm->_wbuf)); + ztm->_transmitted = true; + curr_msg_nb = 0; + } + // Reset frame + __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); + sn = __unsafe_z_multicast_get_sn(ztm, reliability); + t_msg = _z_t_msg_make_frame_header(sn, reliability); + _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, &t_msg)); + } else { + curr_wpos = _z_wbuf_get_wpos(&ztm->_wbuf); + msg_idx++; + curr_msg_nb++; + } + } + // Send frame + __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztm->_link, &ztm->_wbuf)); + ztm->_transmitted = true; // Tell session we transmitted data + return ret; +} +#endif - // Encode the session message +z_result_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg) { + z_result_t ret = _Z_RES_OK; + _Z_DEBUG("Send session message"); + _z_multicast_tx_mutex_lock(ztm, true); + + // Encode transport message + __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); ret = _z_transport_message_encode(&ztm->_wbuf, t_msg); if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed + // Send message __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - // Send the wbuf on the socket ret = _z_link_send_wbuf(&ztm->_link, &ztm->_wbuf); if (ret == _Z_RES_OK) { - ztm->_transmitted = true; // Mark the session that we have transmitted data + ztm->_transmitted = true; // Tell session we transmitted data } } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_multicast_tx_mutex_unlock(ztm); return ret; } z_result_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { z_result_t ret = _Z_RES_OK; - _Z_DEBUG(">> send network message"); - _z_transport_multicast_t *ztm = &zn->_tp._transport._multicast; // Acquire the lock and drop the message if needed - bool drop = false; - if (cong_ctrl == Z_CONGESTION_CONTROL_BLOCK) { -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_lock(&ztm->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 + ret = _z_multicast_tx_mutex_lock(ztm, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); + if (ret != _Z_RES_OK) { + _Z_INFO("Dropping zenoh message because of congestion control"); + return ret; + } + // Process batching +#if Z_FEATURE_BATCHING == 1 + if (ztm->_batch_state == _Z_BATCHING_ACTIVE) { + ret = __unsafe_z_multicast_message_batch(ztm, n_msg); } else { -#if Z_FEATURE_MULTI_THREAD == 1 - z_result_t locked = _z_mutex_try_lock(&ztm->_mutex_tx); - if (locked != 0) { - _Z_INFO("Dropping zenoh message because of congestion control"); - // We failed to acquire the lock, drop the message - drop = true; - } -#endif // Z_FEATURE_MULTI_THREAD == 1 + ret = __unsafe_z_multicast_message_send(ztm, n_msg, reliability); } - - if (drop == false) { - // Prepare the buffer eventually reserving space for the message length - __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - - _z_zint_t sn = __unsafe_z_multicast_get_sn(ztm, reliability); // Get the next sequence number - - _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); - ret = _z_transport_message_encode(&ztm->_wbuf, &t_msg); // Encode the frame header - if (ret == _Z_RES_OK) { - ret = _z_network_message_encode(&ztm->_wbuf, n_msg); // Encode the network message - if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed - __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - - ret = _z_link_send_wbuf(&ztm->_link, &ztm->_wbuf); // Send the wbuf on the socket - if (ret == _Z_RES_OK) { - ztm->_transmitted = true; // Mark the session that we have transmitted data - } - } else { -#if Z_FEATURE_FRAGMENTATION == 1 - // The message does not fit in the current batch, let's fragment it - // Create an expandable wbuf for fragmentation - _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); - - ret = _z_network_message_encode(&fbf, n_msg); // Encode the message on the expandable wbuf - if (ret == _Z_RES_OK) { - bool is_first = true; // Fragment and send the message - while (_z_wbuf_len(&fbf) > 0) { - if (is_first == false) { // Get the fragment sequence number - sn = __unsafe_z_multicast_get_sn(ztm, reliability); - } - is_first = false; - - // Clear the buffer for serialization - __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - - // Serialize one fragment - ret = __unsafe_z_serialize_zenoh_fragment(&ztm->_wbuf, &fbf, reliability, sn); - if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed - __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - - ret = _z_link_send_wbuf(&ztm->_link, &ztm->_wbuf); // Send the wbuf on the socket - if (ret == _Z_RES_OK) { - ztm->_transmitted = true; // Mark the session that we have transmitted data - } - } else { - _Z_ERROR("Fragment serialization failed with err %d", ret); - } - } - } - // Clear the buffer as it's no longer required - _z_wbuf_clear(&fbf); #else - _Z_INFO("Sending the message required fragmentation feature that is deactivated."); + ret = __unsafe_z_multicast_message_send(ztm, n_msg, reliability); #endif - } - } + _z_multicast_tx_mutex_unlock(ztm); + return ret; +} -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 +z_result_t _z_multicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { +#if Z_FEATURE_BATCHING == 1 + _Z_DEBUG("Send network batch"); + _z_transport_multicast_t *ztm = &zn->_tp._transport._multicast; + // Acquire the lock and drop the message if needed + z_result_t ret = _z_multicast_tx_mutex_lock(ztm, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); + if (ret != _Z_RES_OK) { + _Z_INFO("Dropping zenoh batch because of congestion control"); + return ret; } - + // Send batch + ret = __unsafe_multicast_batch_send(ztm, reliability); + // Clean up + _z_network_message_vec_clear(&ztm->_batch); + _z_multicast_tx_mutex_unlock(ztm); return ret; +#else + _ZP_UNUSED(zn); + _ZP_UNUSED(reliability); + _ZP_UNUSED(cong_ctrl); + _Z_ERROR("Tried to send batch but batching feature is deactivated."); + return _Z_ERR_TRANSPORT_TX_FAILED; +#endif } #else @@ -177,4 +276,12 @@ z_result_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t _ZP_UNUSED(cong_ctrl); return _Z_ERR_TRANSPORT_NOT_AVAILABLE; } + +z_result_t _z_multicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { + _ZP_UNUSED(zn); + _ZP_UNUSED(reliability); + _ZP_UNUSED(cong_ctrl); + return _Z_ERR_TRANSPORT_NOT_AVAILABLE; +} + #endif // Z_FEATURE_MULTICAST_TRANSPORT == 1 diff --git a/src/transport/raweth/rx.c b/src/transport/raweth/rx.c index 660f49293..296bbe5fb 100644 --- a/src/transport/raweth/rx.c +++ b/src/transport/raweth/rx.c @@ -22,6 +22,7 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/multicast/transport.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -77,11 +78,7 @@ z_result_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_m _Z_DEBUG(">> recv session msg"); z_result_t ret = _Z_RES_OK; -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire the lock - _z_mutex_lock(&ztm->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_multicast_rx_mutex_lock(ztm); // Prepare the buffer _z_zbuf_reset(&ztm->_zbuf); @@ -105,11 +102,7 @@ z_result_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_m _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_zbuf)); ret = _z_transport_message_decode(t_msg, &ztm->_zbuf); } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_multicast_rx_mutex_unlock(ztm); return ret; } diff --git a/src/transport/raweth/tx.c b/src/transport/raweth/tx.c index b4ddc5def..87b5693ab 100644 --- a/src/transport/raweth/tx.c +++ b/src/transport/raweth/tx.c @@ -24,18 +24,13 @@ #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/protocol/keyexpr.h" #include "zenoh-pico/system/link/raweth.h" +#include "zenoh-pico/transport/multicast/transport.h" #include "zenoh-pico/transport/transport.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_RAWETH_TRANSPORT == 1 -#if Z_FEATURE_MULTI_THREAD == 1 -static void _zp_raweth_unlock_tx_mutex(_z_transport_multicast_t *ztm) { _z_mutex_unlock(&ztm->_mutex_tx); } -#else -static void _zp_raweth_unlock_tx_mutex(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } -#endif - static int _zp_raweth_find_map_entry(const _z_keyexpr_t *keyexpr, _z_raweth_socket_t *sock) { for (size_t i = 0; i < _zp_raweth_mapping_array_len(&sock->_mapping); i++) { // Find matching keyexpr @@ -196,28 +191,22 @@ z_result_t _z_raweth_send_t_msg(_z_transport_multicast_t *ztm, const _z_transpor z_result_t ret = _Z_RES_OK; _Z_DEBUG(">> send session message"); -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_lock(&ztm->_mutex_tx); -#endif + _z_multicast_tx_mutex_lock(ztm, true); // Reset wbuf _z_wbuf_reset(&ztm->_wbuf); // Set socket info - _Z_CLEAN_RETURN_IF_ERR(_zp_raweth_set_socket(NULL, &ztm->_link._socket._raweth), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_zp_raweth_set_socket(NULL, &ztm->_link._socket._raweth), _z_multicast_tx_mutex_unlock(ztm)); // Prepare buff __unsafe_z_raweth_prepare_header(&ztm->_link, &ztm->_wbuf); // Encode the session message - _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, t_msg), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, t_msg), _z_multicast_tx_mutex_unlock(ztm)); // Write the message header - _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_link, &ztm->_wbuf), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_link, &ztm->_wbuf), _z_multicast_tx_mutex_unlock(ztm)); // Send the wbuf on the socket - _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), _z_multicast_tx_mutex_unlock(ztm)); // Mark the session that we have transmitted data ztm->_transmitted = true; - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_tx); -#endif - + _z_multicast_tx_mutex_unlock(ztm); return ret; } @@ -228,20 +217,11 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ _Z_DEBUG(">> send network message"); // Acquire the lock and drop the message if needed -#if Z_FEATURE_MULTI_THREAD == 1 - if (cong_ctrl == Z_CONGESTION_CONTROL_BLOCK) { - _z_mutex_lock(&ztm->_mutex_tx); - } else { - if (_z_mutex_try_lock(&ztm->_mutex_tx) != 0) { - _Z_INFO("Dropping zenoh message because of congestion control"); - // We failed to acquire the lock, drop the message - return ret; - } + ret = _z_multicast_tx_mutex_lock(ztm, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); + if (ret != _Z_RES_OK) { + _Z_INFO("Dropping zenoh message because of congestion control"); + return ret; } -#else - _ZP_UNUSED(cong_ctrl); -#endif // Z_FEATURE_MULTI_THREAD == 1 - const _z_keyexpr_t *keyexpr = NULL; switch (n_msg->_tag) { case _Z_N_PUSH: @@ -262,21 +242,21 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ _z_wbuf_reset(&ztm->_wbuf); // Set socket info _Z_CLEAN_RETURN_IF_ERR(_zp_raweth_set_socket(keyexpr, &ztm->_link._socket._raweth), - _zp_raweth_unlock_tx_mutex(ztm)); + _z_multicast_tx_mutex_unlock(ztm)); // Prepare buff __unsafe_z_raweth_prepare_header(&ztm->_link, &ztm->_wbuf); // Set the frame header _z_zint_t sn = __unsafe_z_raweth_get_sn(ztm, reliability); _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); // Encode the frame header - _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, &t_msg), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, &t_msg), _z_multicast_tx_mutex_unlock(ztm)); // Encode the network message if (_z_network_message_encode(&ztm->_wbuf, n_msg) == _Z_RES_OK) { // Write the eth header _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_link, &ztm->_wbuf), - _zp_raweth_unlock_tx_mutex(ztm)); + _z_multicast_tx_mutex_unlock(ztm)); // Send the wbuf on the socket - _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), _z_multicast_tx_mutex_unlock(ztm)); // Mark the session that we have transmitted data ztm->_transmitted = true; } else { // The message does not fit in the current batch, let's fragment it @@ -284,7 +264,7 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ // Create an expandable wbuf for fragmentation _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); // Encode the message on the expandable wbuf - _Z_CLEAN_RETURN_IF_ERR(_z_network_message_encode(&fbf, n_msg), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_network_message_encode(&fbf, n_msg), _z_multicast_tx_mutex_unlock(ztm)); // Fragment and send the message bool is_first = true; while (_z_wbuf_len(&fbf) > 0) { @@ -299,12 +279,13 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ __unsafe_z_raweth_prepare_header(&ztm->_link, &ztm->_wbuf); // Serialize one fragment _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_serialize_zenoh_fragment(&ztm->_wbuf, &fbf, reliability, sn), - _zp_raweth_unlock_tx_mutex(ztm)); + _z_multicast_tx_mutex_unlock(ztm)); // Write the eth header _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_link, &ztm->_wbuf), - _zp_raweth_unlock_tx_mutex(ztm)); + _z_multicast_tx_mutex_unlock(ztm)); // Send the wbuf on the socket - _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), _zp_raweth_unlock_tx_mutex(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), + _z_multicast_tx_mutex_unlock(ztm)); // Mark the session that we have transmitted data ztm->_transmitted = true; } diff --git a/src/transport/transport.c b/src/transport/transport.c index 5aee622c6..28cc1eb48 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -78,6 +78,48 @@ void _z_transport_free(_z_transport_t **zt) { *zt = NULL; } +#if Z_FEATURE_BATCHING == 1 +bool _z_transport_start_batching(_z_transport_t *zt) { + uint8_t *batch_state = NULL; + switch (zt->_type) { + case _Z_TRANSPORT_UNICAST_TYPE: + batch_state = &zt->_transport._unicast._batch_state; + break; + case _Z_TRANSPORT_MULTICAST_TYPE: + batch_state = &zt->_transport._multicast._batch_state; + break; + case _Z_TRANSPORT_RAWETH_TYPE: + batch_state = &zt->_transport._raweth._batch_state; + break; + default: + break; + } + if (*batch_state == _Z_BATCHING_ACTIVE) { + return false; + } + *batch_state = _Z_BATCHING_ACTIVE; + return true; +} + +void _z_transport_stop_batching(_z_transport_t *zt) { + uint8_t *batch_state = NULL; + switch (zt->_type) { + case _Z_TRANSPORT_UNICAST_TYPE: + batch_state = &zt->_transport._unicast._batch_state; + break; + case _Z_TRANSPORT_MULTICAST_TYPE: + batch_state = &zt->_transport._multicast._batch_state; + break; + case _Z_TRANSPORT_RAWETH_TYPE: + batch_state = &zt->_transport._raweth._batch_state; + break; + default: + break; + } + *batch_state = _Z_BATCHING_IDLE; +} +#endif + /** * @brief Inserts an entry into `root`, allocating it a `_peer_id` * diff --git a/src/transport/unicast/rx.c b/src/transport/unicast/rx.c index 01c5e2014..d109ae513 100644 --- a/src/transport/unicast/rx.c +++ b/src/transport/unicast/rx.c @@ -23,6 +23,7 @@ #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/unicast/rx.h" +#include "zenoh-pico/transport/unicast/transport.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -31,11 +32,7 @@ z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg) { _Z_DEBUG(">> recv session msg"); z_result_t ret = _Z_RES_OK; -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire the lock - _z_mutex_lock(&ztu->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_unicast_rx_mutex_lock(ztu); size_t to_read = 0; do { switch (ztu->_link._cap._flow) { @@ -84,11 +81,7 @@ z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_me ztu->_received = true; } } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztu->_mutex_rx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_unicast_rx_mutex_unlock(ztu); return ret; } diff --git a/src/transport/unicast/transport.c b/src/transport/unicast/transport.c index fae652567..de01dc01e 100644 --- a/src/transport/unicast/transport.c +++ b/src/transport/unicast/transport.c @@ -36,14 +36,21 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, z_result_t ret = _Z_RES_OK; zt->_type = _Z_TRANSPORT_UNICAST_TYPE; + _z_transport_unicast_t *ztu = &zt->_transport._unicast; + +// Initialize batching data +#if Z_FEATURE_BATCHING == 1 + ztu->_batch_state = _Z_BATCHING_IDLE; + ztu->_batch = _z_network_message_vec_make(0); +#endif #if Z_FEATURE_MULTI_THREAD == 1 // Initialize the mutexes - ret = _z_mutex_init(&zt->_transport._unicast._mutex_tx); + ret = _z_mutex_init(&ztu->_mutex_tx); if (ret == _Z_RES_OK) { - ret = _z_mutex_init(&zt->_transport._unicast._mutex_rx); + ret = _z_mutex_init(&ztu->_mutex_rx); if (ret != _Z_RES_OK) { - _z_mutex_drop(&zt->_transport._unicast._mutex_tx); + _z_mutex_drop(&ztu->_mutex_tx); } } #endif // Z_FEATURE_MULTI_THREAD == 1 @@ -55,66 +62,65 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, size_t zbuf_size = param->_batch_size; // Initialize tx rx buffers - zt->_transport._unicast._wbuf = _z_wbuf_make(wbuf_size, false); - zt->_transport._unicast._zbuf = _z_zbuf_make(zbuf_size); + ztu->_wbuf = _z_wbuf_make(wbuf_size, false); + ztu->_zbuf = _z_zbuf_make(zbuf_size); // Clean up the buffers if one of them failed to be allocated - if ((_z_wbuf_capacity(&zt->_transport._unicast._wbuf) != wbuf_size) || - (_z_zbuf_capacity(&zt->_transport._unicast._zbuf) != zbuf_size)) { + if ((_z_wbuf_capacity(&ztu->_wbuf) != wbuf_size) || (_z_zbuf_capacity(&ztu->_zbuf) != zbuf_size)) { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; _Z_ERROR("Not enough memory to allocate transport tx rx buffers!"); #if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_drop(&zt->_transport._unicast._mutex_tx); - _z_mutex_drop(&zt->_transport._unicast._mutex_rx); + _z_mutex_drop(&ztu->_mutex_tx); + _z_mutex_drop(&ztu->_mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 - _z_wbuf_clear(&zt->_transport._unicast._wbuf); - _z_zbuf_clear(&zt->_transport._unicast._zbuf); + _z_wbuf_clear(&ztu->_wbuf); + _z_zbuf_clear(&ztu->_zbuf); } #if Z_FEATURE_FRAGMENTATION == 1 // Initialize the defragmentation buffers - zt->_transport._unicast._state_reliable = _Z_DBUF_STATE_NULL; - zt->_transport._unicast._state_best_effort = _Z_DBUF_STATE_NULL; - zt->_transport._unicast._dbuf_reliable = _z_wbuf_null(); - zt->_transport._unicast._dbuf_best_effort = _z_wbuf_null(); + ztu->_state_reliable = _Z_DBUF_STATE_NULL; + ztu->_state_best_effort = _Z_DBUF_STATE_NULL; + ztu->_dbuf_reliable = _z_wbuf_null(); + ztu->_dbuf_best_effort = _z_wbuf_null(); #endif // Z_FEATURE_FRAGMENTATION == 1 } if (ret == _Z_RES_OK) { // Set default SN resolution - zt->_transport._unicast._sn_res = _z_sn_max(param->_seq_num_res); + ztu->_sn_res = _z_sn_max(param->_seq_num_res); // The initial SN at TX side - zt->_transport._unicast._sn_tx_reliable = param->_initial_sn_tx; - zt->_transport._unicast._sn_tx_best_effort = param->_initial_sn_tx; + ztu->_sn_tx_reliable = param->_initial_sn_tx; + ztu->_sn_tx_best_effort = param->_initial_sn_tx; // The initial SN at RX side - _z_zint_t initial_sn_rx = _z_sn_decrement(zt->_transport._unicast._sn_res, param->_initial_sn_rx); - zt->_transport._unicast._sn_rx_reliable = initial_sn_rx; - zt->_transport._unicast._sn_rx_best_effort = initial_sn_rx; + _z_zint_t initial_sn_rx = _z_sn_decrement(ztu->_sn_res, param->_initial_sn_rx); + ztu->_sn_rx_reliable = initial_sn_rx; + ztu->_sn_rx_best_effort = initial_sn_rx; #if Z_FEATURE_MULTI_THREAD == 1 // Tasks - zt->_transport._unicast._read_task_running = false; - zt->_transport._unicast._read_task = NULL; - zt->_transport._unicast._lease_task_running = false; - zt->_transport._unicast._lease_task = NULL; + ztu->_read_task_running = false; + ztu->_read_task = NULL; + ztu->_lease_task_running = false; + ztu->_lease_task = NULL; #endif // Z_FEATURE_MULTI_THREAD == 1 // Notifiers - zt->_transport._unicast._received = 0; - zt->_transport._unicast._transmitted = 0; + ztu->_received = 0; + ztu->_transmitted = 0; // Transport lease - zt->_transport._unicast._lease = param->_lease; + ztu->_lease = param->_lease; // Transport link for unicast - zt->_transport._unicast._link = *zl; + ztu->_link = *zl; // Remote peer PID - zt->_transport._unicast._remote_zid = param->_remote_zid; + ztu->_remote_zid = param->_remote_zid; } else { param->_remote_zid = _z_id_empty(); } @@ -257,6 +263,10 @@ void _z_unicast_transport_clear(_z_transport_t *zt) { _z_mutex_drop(&ztu->_mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 +#if Z_FEATURE_BATCHING == 1 + _z_network_message_vec_clear(&ztu->_batch); +#endif + // Clean up the buffers _z_wbuf_clear(&ztu->_wbuf); _z_zbuf_clear(&ztu->_zbuf); diff --git a/src/transport/unicast/tx.c b/src/transport/unicast/tx.c index 5ed555794..78bc04f86 100644 --- a/src/transport/unicast/tx.c +++ b/src/transport/unicast/tx.c @@ -20,6 +20,7 @@ #include "zenoh-pico/protocol/codec/network.h" #include "zenoh-pico/protocol/codec/transport.h" #include "zenoh-pico/protocol/iobuf.h" +#include "zenoh-pico/transport/unicast/transport.h" #include "zenoh-pico/transport/unicast/tx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -31,7 +32,7 @@ * Make sure that the following mutexes are locked before calling this function: * - ztu->_mutex_inner */ -_z_zint_t __unsafe_z_unicast_get_sn(_z_transport_unicast_t *ztu, z_reliability_t reliability) { +static _z_zint_t __unsafe_z_unicast_get_sn(_z_transport_unicast_t *ztu, z_reliability_t reliability) { _z_zint_t sn; if (reliability == Z_RELIABILITY_RELIABLE) { sn = ztu->_sn_tx_reliable; @@ -43,134 +44,226 @@ _z_zint_t __unsafe_z_unicast_get_sn(_z_transport_unicast_t *ztu, z_reliability_t return sn; } -z_result_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_message_t *t_msg) { - z_result_t ret = _Z_RES_OK; - _Z_DEBUG(">> send session message"); +#if Z_FEATURE_FRAGMENTATION == 1 +static z_result_t __unsafe_z_unicast_send_fragment(_z_transport_unicast_t *ztu, _z_wbuf_t *fbf, + const _z_network_message_t *n_msg, z_reliability_t reliability, + _z_zint_t first_sn) { + bool is_first = true; + _z_zint_t sn = first_sn; + // Encode message on temp buffer + _Z_RETURN_IF_ERR(_z_network_message_encode(fbf, n_msg)); + // Fragment message + while (_z_wbuf_len(fbf) > 0) { + // Get fragment sequence number + if (!is_first) { + sn = __unsafe_z_unicast_get_sn(ztu, reliability); + } + is_first = false; + // Serialize fragment + __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); + z_result_t ret = __unsafe_z_serialize_zenoh_fragment(&ztu->_wbuf, fbf, reliability, sn); + if (ret != _Z_RES_OK) { + _Z_ERROR("Fragment serialization failed with err %d", ret); + return ret; + } + // Send fragment + __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztu->_link, &ztu->_wbuf)); + ztu->_transmitted = true; // Tell session we transmitted data + } + return _Z_RES_OK; +} +#else +static z_result_t __unsafe_z_unicast_send_fragment(_z_transport_unicast_t *ztu, _z_wbuf_t *fbf, + const _z_network_message_t *n_msg, z_reliability_t reliability, + _z_zint_t first_sn) { + _ZP_UNUSED(ztu); + _ZP_UNUSED(fbf); + _ZP_UNUSED(n_msg); + _ZP_UNUSED(reliability); + _ZP_UNUSED(first_sn); + _Z_INFO("Sending the message required fragmentation feature that is deactivated."); + return _Z_RES_OK; +} +#endif -#if Z_FEATURE_MULTI_THREAD == 1 - // Acquire the lock - _z_mutex_lock(&ztu->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 +static z_result_t __unsafe_z_unicast_message_send(_z_transport_unicast_t *ztu, const _z_network_message_t *n_msg, + z_reliability_t reliability) { + _Z_DEBUG("Send network message"); + // Encode frame header + __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); + _z_zint_t sn = __unsafe_z_unicast_get_sn(ztu, reliability); + _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); + _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztu->_wbuf, &t_msg)); + // Encode the network message + z_result_t ret = _z_network_message_encode(&ztu->_wbuf, n_msg); + // The message does not fit in the current batch, let's fragment it + if (ret != _Z_RES_OK) { + // Create an expandable wbuf for fragmentation + _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); + // Send message as fragments + ret = __unsafe_z_unicast_send_fragment(ztu, &fbf, n_msg, reliability, sn); + // Clear the buffer as it's no longer required + _z_wbuf_clear(&fbf); + return ret; + } + // Send network message + __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztu->_link, &ztu->_wbuf)); + ztu->_transmitted = true; // Tell session we transmitted data + return _Z_RES_OK; +} - // Prepare the buffer eventually reserving space for the message length +#if Z_FEATURE_BATCHING == 1 +static z_result_t __unsafe_z_unicast_message_batch(_z_transport_unicast_t *ztu, const _z_network_message_t *n_msg) { + _Z_DEBUG("Batching network message"); + // Copy network message + _z_network_message_t *batch_msg = z_malloc(sizeof(_z_network_message_t)); + if (batch_msg == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + if (_z_n_msg_copy(batch_msg, n_msg) != _Z_RES_OK) { + z_free(batch_msg); + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + _z_network_message_vec_append(&ztu->_batch, batch_msg); + return _Z_RES_OK; +} + +static z_result_t __unsafe_unicast_batch_send(_z_transport_unicast_t *ztu, z_reliability_t reliability) { + z_result_t ret = _Z_RES_OK; + // Get network message number + size_t msg_nb = _z_network_message_vec_len(&ztu->_batch); + size_t msg_idx = 0; + size_t curr_msg_nb = 0; + if (msg_nb == 0) { + return _Z_RES_OK; + } + // Encode the frame header __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); + _z_zint_t sn = __unsafe_z_unicast_get_sn(ztu, reliability); + _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); + _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztu->_wbuf, &t_msg)); + size_t curr_wpos = _z_wbuf_get_wpos(&ztu->_wbuf); + // Process batch + while (msg_idx < msg_nb) { + // Encode a network message + _z_network_message_t *n_msg = _z_network_message_vec_get(&ztu->_batch, msg_idx); + assert(n_msg != NULL); + if (_z_network_message_encode(&ztu->_wbuf, n_msg) != _Z_RES_OK) { + // Remove partially encoded data + _z_wbuf_set_wpos(&ztu->_wbuf, curr_wpos); + // Handle case where one message is too big to fit in frame + if (curr_msg_nb == 0) { + _Z_INFO("Batch sending interrupted by a message needing to be fragmented."); + // Create an expandable wbuf for fragmentation + _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); + // Send message as fragments + ret = __unsafe_z_unicast_send_fragment(ztu, &fbf, n_msg, reliability, sn); + // Clear the buffer as it's no longer required + _z_wbuf_clear(&fbf); + if (ret != _Z_RES_OK) { + _Z_ERROR("Send fragmented message failed with err %d.", ret); + } + // Message is sent or skipped + msg_idx++; + } else { // Frame has messages but is full + _Z_INFO("Sending batch in multiple frames because it is too big for one"); + // Send frame + __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztu->_link, &ztu->_wbuf)); + ztu->_transmitted = true; + curr_msg_nb = 0; + } + // Reset frame + __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); + sn = __unsafe_z_unicast_get_sn(ztu, reliability); + t_msg = _z_t_msg_make_frame_header(sn, reliability); + _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztu->_wbuf, &t_msg)); + } else { + curr_wpos = _z_wbuf_get_wpos(&ztu->_wbuf); + msg_idx++; + curr_msg_nb++; + } + } + // Send frame + __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztu->_link, &ztu->_wbuf)); + ztu->_transmitted = true; // Tell session we transmitted data + return ret; +} +#endif - // Encode the session message +z_result_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_message_t *t_msg) { + z_result_t ret = _Z_RES_OK; + _Z_DEBUG("Send session message"); + _z_unicast_tx_mutex_lock(ztu, true); + + // Encode transport message + __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); ret = _z_transport_message_encode(&ztu->_wbuf, t_msg); if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed + // Send message __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - // Send the wbuf on the socket ret = _z_link_send_wbuf(&ztu->_link, &ztu->_wbuf); if (ret == _Z_RES_OK) { - ztu->_transmitted = true; // Mark the session that we have transmitted data + ztu->_transmitted = true; // Tell session we transmitted data } } - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztu->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_unicast_tx_mutex_unlock(ztu); return ret; } z_result_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { z_result_t ret = _Z_RES_OK; - _Z_DEBUG(">> send network message"); - _z_transport_unicast_t *ztu = &zn->_tp._transport._unicast; // Acquire the lock and drop the message if needed - bool drop = false; - if (cong_ctrl == Z_CONGESTION_CONTROL_BLOCK) { -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_lock(&ztu->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 + ret = _z_unicast_tx_mutex_lock(ztu, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); + if (ret != _Z_RES_OK) { + _Z_INFO("Dropping zenoh message because of congestion control"); + return ret; + } + // Process batching +#if Z_FEATURE_BATCHING == 1 + if (ztu->_batch_state == _Z_BATCHING_ACTIVE) { + ret = __unsafe_z_unicast_message_batch(ztu, n_msg); } else { -#if Z_FEATURE_MULTI_THREAD == 1 - z_result_t locked = _z_mutex_try_lock(&ztu->_mutex_tx); - if (locked != 0) { - _Z_INFO("Dropping zenoh message because of congestion control"); - // We failed to acquire the lock, drop the message - drop = true; - } -#endif // Z_FEATURE_MULTI_THREAD == 1 + ret = __unsafe_z_unicast_message_send(ztu, n_msg, reliability); } - - if (drop == false) { - // Prepare the buffer eventually reserving space for the message length - __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - - _z_zint_t sn = __unsafe_z_unicast_get_sn(ztu, reliability); // Get the next sequence number - - _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); - ret = _z_transport_message_encode(&ztu->_wbuf, &t_msg); // Encode the frame header - if (ret == _Z_RES_OK) { - ret = _z_network_message_encode(&ztu->_wbuf, n_msg); // Encode the network message - if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed - __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - - if (ztu->_wbuf._ioss._len == 1) { - ret = _z_link_send_wbuf(&ztu->_link, &ztu->_wbuf); // Send the wbuf on the socket - } else { - // Change the MID - - // for () - } - if (ret == _Z_RES_OK) { - ztu->_transmitted = true; // Mark the session that we have transmitted data - } - } else { -#if Z_FEATURE_FRAGMENTATION == 1 - // The message does not fit in the current batch, let's fragment it - // Create an expandable wbuf for fragmentation - _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); - - ret = _z_network_message_encode(&fbf, n_msg); // Encode the message on the expandable wbuf - if (ret == _Z_RES_OK) { - bool is_first = true; // Fragment and send the message - while (_z_wbuf_len(&fbf) > 0) { - if (is_first == false) { // Get the fragment sequence number - sn = __unsafe_z_unicast_get_sn(ztu, reliability); - } - is_first = false; - - // Clear the buffer for serialization - __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - - // Serialize one fragment - ret = __unsafe_z_serialize_zenoh_fragment(&ztu->_wbuf, &fbf, reliability, sn); - if (ret == _Z_RES_OK) { - // Write the message length in the reserved space if needed - __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - - ret = _z_link_send_wbuf(&ztu->_link, &ztu->_wbuf); // Send the wbuf on the socket - if (ret == _Z_RES_OK) { - ztu->_transmitted = true; // Mark the session that we have transmitted data - } - } else { - _Z_ERROR("Fragment serialization failed with err %d", ret); - } - } - } - - // Clear the buffer as it's no longer required - _z_wbuf_clear(&fbf); #else - _Z_INFO("Sending the message required fragmentation feature that is deactivated."); + ret = __unsafe_z_unicast_message_send(ztu, n_msg, reliability); #endif - } - } + _z_unicast_tx_mutex_unlock(ztu); + return ret; +} -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztu->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 +z_result_t _z_unicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { +#if Z_FEATURE_BATCHING == 1 + _Z_DEBUG("Send network batch"); + _z_transport_unicast_t *ztu = &zn->_tp._transport._unicast; + // Acquire the lock and drop the message if needed + z_result_t ret = _z_unicast_tx_mutex_lock(ztu, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); + if (ret != _Z_RES_OK) { + _Z_INFO("Dropping zenoh batch because of congestion control"); + return ret; } - + // Send batch + ret = __unsafe_unicast_batch_send(ztu, reliability); + // Clean up + _z_network_message_vec_clear(&ztu->_batch); + _z_unicast_tx_mutex_unlock(ztu); return ret; +#else + _ZP_UNUSED(zn); + _ZP_UNUSED(reliability); + _ZP_UNUSED(cong_ctrl); + _Z_ERROR("Tried to send batch but batching feature is deactivated."); + return _Z_ERR_TRANSPORT_TX_FAILED; +#endif } + #else z_result_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_message_t *t_msg) { _ZP_UNUSED(ztu); @@ -186,4 +279,11 @@ z_result_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n _ZP_UNUSED(cong_ctrl); return _Z_ERR_TRANSPORT_NOT_AVAILABLE; } + +z_result_t _z_unicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { + _ZP_UNUSED(zn); + _ZP_UNUSED(reliability); + _ZP_UNUSED(cong_ctrl); + return _Z_ERR_TRANSPORT_NOT_AVAILABLE; +} #endif // Z_FEATURE_UNICAST_TRANSPORT == 1 From c855c13c8dddbb52509461cbd16cecc887639ad3 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Fri, 25 Oct 2024 17:39:52 +0200 Subject: [PATCH 06/17] feat: switch multicast address to stack (#762) --- src/link/multicast/bt.c | 8 ++++---- src/system/arduino/esp32/network.cpp | 4 ++-- src/system/arduino/opencr/network.cpp | 4 ++-- src/system/espidf/network.c | 4 ++-- src/system/mbed/network.cpp | 4 ++-- src/system/unix/link/raweth.c | 2 +- src/system/unix/network.c | 7 +++++-- src/system/windows/network.c | 4 ++-- src/system/zephyr/network.c | 4 ++-- src/transport/multicast/read.c | 11 ++++++----- 10 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/link/multicast/bt.c b/src/link/multicast/bt.c index 0b26d3643..84216e9bb 100644 --- a/src/link/multicast/bt.c +++ b/src/link/multicast/bt.c @@ -104,8 +104,8 @@ size_t _z_f_link_write_all_bt(const _z_link_t *self, const uint8_t *ptr, size_t size_t _z_f_link_read_bt(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { size_t rb = _z_read_bt(self->_socket._bt._sock, ptr, len); if ((rb > (size_t)0) && (addr != NULL)) { - *addr = _z_slice_make(strlen(self->_socket._bt._gname)); - (void)memcpy((uint8_t *)addr->start, self->_socket._bt._gname, addr->len); + addr->len = strlen(self->_socket._bt._gname); + (void)memcpy((uint8_t *)addr->start, self->_socket._bt._gname, strlen(self->_socket._bt._gname)); } return rb; @@ -114,8 +114,8 @@ size_t _z_f_link_read_bt(const _z_link_t *self, uint8_t *ptr, size_t len, _z_sli size_t _z_f_link_read_exact_bt(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { size_t rb = _z_read_exact_bt(self->_socket._bt._sock, ptr, len); if ((rb == len) && (addr != NULL)) { - *addr = _z_slice_make(strlen(self->_socket._bt._gname)); - (void)memcpy((uint8_t *)addr->start, self->_socket._bt._gname, addr->len); + addr->len = strlen(self->_socket._bt._gname); + (void)memcpy((uint8_t *)addr->start, self->_socket._bt._gname, strlen(self->_socket._bt._gname)); } return rb; diff --git a/src/system/arduino/esp32/network.cpp b/src/system/arduino/esp32/network.cpp index 8c88d4dc6..c0a82927d 100644 --- a/src/system/arduino/esp32/network.cpp +++ b/src/system/arduino/esp32/network.cpp @@ -500,7 +500,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ if (!((a->sin_port == b->sin_port) && (a->sin_addr.s_addr == b->sin_addr.s_addr))) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(in_addr_t) + sizeof(in_port_t)); + addr->len = sizeof(in_addr_t) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin_addr.s_addr, sizeof(in_addr_t)); (void)memcpy((uint8_t *)(addr->start + sizeof(in_addr_t)), &b->sin_port, sizeof(in_port_t)); } @@ -513,7 +513,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ (memcmp(&a->sin6_addr, &b->sin6_addr, sizeof(struct in6_addr)) != 0)) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(struct in6_addr) + sizeof(in_port_t)); + addr->len = sizeof(struct in6_addr) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin6_addr.s6_addr, sizeof(struct in6_addr)); (void)memcpy((uint8_t *)(addr->start + sizeof(struct in6_addr)), &b->sin6_port, sizeof(in_port_t)); } diff --git a/src/system/arduino/opencr/network.cpp b/src/system/arduino/opencr/network.cpp index b690559f1..c02765d8c 100644 --- a/src/system/arduino/opencr/network.cpp +++ b/src/system/arduino/opencr/network.cpp @@ -295,8 +295,8 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ IPAddress rip = sock._udp->remoteIP(); uint16_t rport = sock._udp->remotePort(); - *addr = _z_slice_make(strlen((const char *)&rip[0]) + strlen((const char *)&rip[1]) + - strlen((const char *)&rip[2]) + strlen((const char *)&rip[3]) + sizeof(uint16_t)); + addr->len = strlen((const char *)&rip[0]) + strlen((const char *)&rip[1]) + + strlen((const char *)&rip[2]) + strlen((const char *)&rip[3]) + sizeof(uint16_t); uint8_t offset = 0; for (uint8_t i = 0; i < (uint8_t)4; i++) { (void)memcpy(const_cast(addr->start + offset), &rip[i], strlen((const char *)&rip[i])); diff --git a/src/system/espidf/network.c b/src/system/espidf/network.c index bc91f50c3..0634d2a23 100644 --- a/src/system/espidf/network.c +++ b/src/system/espidf/network.c @@ -496,7 +496,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ if (!((a->sin_port == b->sin_port) && (a->sin_addr.s_addr == b->sin_addr.s_addr))) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(in_addr_t) + sizeof(in_port_t)); + addr->len = sizeof(in_addr_t) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin_addr.s_addr, sizeof(in_addr_t)); (void)memcpy((uint8_t *)(addr->start + sizeof(in_addr_t)), &b->sin_port, sizeof(in_port_t)); } @@ -509,7 +509,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ (memcmp(&a->sin6_addr, &b->sin6_addr, sizeof(struct in6_addr)) != 0)) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(struct in6_addr) + sizeof(in_port_t)); + addr->len = sizeof(struct in6_addr) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin6_addr.s6_addr, sizeof(struct in6_addr)); (void)memcpy((uint8_t *)(addr->start + sizeof(struct in6_addr)), &b->sin6_port, sizeof(in_port_t)); } diff --git a/src/system/mbed/network.cpp b/src/system/mbed/network.cpp index 310a107af..a9d365782 100644 --- a/src/system/mbed/network.cpp +++ b/src/system/mbed/network.cpp @@ -274,13 +274,13 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ } if (raddr.get_ip_version() == NSAPI_IPv4) { - *addr = _z_slice_make(NSAPI_IPv4_BYTES + sizeof(uint16_t)); + addr->len = NSAPI_IPv4_BYTES + sizeof(uint16_t); (void)memcpy(const_cast(addr->start), raddr.get_ip_bytes(), NSAPI_IPv4_BYTES); uint16_t port = raddr.get_port(); (void)memcpy(const_cast(addr->start + NSAPI_IPv4_BYTES), &port, sizeof(uint16_t)); break; } else if (raddr.get_ip_version() == NSAPI_IPv6) { - *addr = _z_slice_make(NSAPI_IPv6_BYTES + sizeof(uint16_t)); + addr->len = NSAPI_IPv6_BYTES + sizeof(uint16_t); (void)memcpy(const_cast(addr->start), raddr.get_ip_bytes(), NSAPI_IPv6_BYTES); uint16_t port = raddr.get_port(); (void)memcpy(const_cast(addr->start + NSAPI_IPv6_BYTES), &port, sizeof(uint16_t)); diff --git a/src/system/unix/link/raweth.c b/src/system/unix/link/raweth.c index f1abcf325..6e15cae0d 100644 --- a/src/system/unix/link/raweth.c +++ b/src/system/unix/link/raweth.c @@ -118,7 +118,7 @@ size_t _z_receive_raweth(const _z_sys_net_socket_t *sock, void *buff, size_t buf // Copy sender mac if needed if (addr != NULL) { uint8_t *header_addr = (uint8_t *)buff; - *addr = _z_slice_make(sizeof(ETH_ALEN)); + addr->len = sizeof(ETH_ALEN); (void)memcpy((uint8_t *)addr->start, (header_addr + ETH_ALEN), sizeof(ETH_ALEN)); } return (size_t)bytesRead; diff --git a/src/system/unix/network.c b/src/system/unix/network.c index 86be15dc0..978b61315 100644 --- a/src/system/unix/network.c +++ b/src/system/unix/network.c @@ -13,6 +13,7 @@ // #include +#include #include #include #include @@ -535,7 +536,8 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ if (!((a->sin_port == b->sin_port) && (a->sin_addr.s_addr == b->sin_addr.s_addr))) { // If addr is not NULL, it means that the rep was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(in_addr_t) + sizeof(in_port_t)); + assert(addr->len >= sizeof(in_addr_t) + sizeof(in_port_t)); + addr->len = sizeof(in_addr_t) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin_addr.s_addr, sizeof(in_addr_t)); (void)memcpy((uint8_t *)(addr->start + sizeof(in_addr_t)), &b->sin_port, sizeof(in_port_t)); } @@ -548,7 +550,8 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ (memcmp(a->sin6_addr.s6_addr, b->sin6_addr.s6_addr, sizeof(struct in6_addr)) == 0))) { // If addr is not NULL, it means that the rep was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(struct in6_addr) + sizeof(in_port_t)); + assert(addr->len >= sizeof(struct in6_addr) + sizeof(in_port_t)); + addr->len = sizeof(struct in6_addr) + sizeof(in_port_t); (void)memcpy((uint8_t *)addr->start, &b->sin6_addr.s6_addr, sizeof(struct in6_addr)); (void)memcpy((uint8_t *)(addr->start + sizeof(struct in6_addr)), &b->sin6_port, sizeof(in_port_t)); } diff --git a/src/system/windows/network.c b/src/system/windows/network.c index b0d9a6990..c3a8a3f27 100644 --- a/src/system/windows/network.c +++ b/src/system/windows/network.c @@ -548,7 +548,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ if (!((a->sin_port == b->sin_port) && (a->sin_addr.s_addr == b->sin_addr.s_addr))) { // If addr is not NULL, it means that the rep was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(IN_ADDR) + sizeof(USHORT)); + addr->len = sizeof(IN_ADDR) + sizeof(USHORT); (void)memcpy((uint8_t *)addr->start, &b->sin_addr.s_addr, sizeof(IN_ADDR)); (void)memcpy((uint8_t *)(addr->start + sizeof(IN_ADDR)), &b->sin_port, sizeof(USHORT)); } @@ -561,7 +561,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ (memcmp(a->sin6_addr.s6_addr, b->sin6_addr.s6_addr, sizeof(struct in6_addr)) == 0))) { // If addr is not NULL, it means that the rep was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(struct in6_addr) + sizeof(USHORT)); + addr->len = sizeof(struct in6_addr) + sizeof(USHORT); (void)memcpy((uint8_t *)addr->start, &b->sin6_addr.s6_addr, sizeof(struct in6_addr)); (void)memcpy((uint8_t *)(addr->start + sizeof(struct in6_addr)), &b->sin6_port, sizeof(USHORT)); } diff --git a/src/system/zephyr/network.c b/src/system/zephyr/network.c index d8ac405b3..d60555aa2 100644 --- a/src/system/zephyr/network.c +++ b/src/system/zephyr/network.c @@ -510,7 +510,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ if (!((a->sin_port == b->sin_port) && (a->sin_addr.s_addr == b->sin_addr.s_addr))) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make(sizeof(uint32_t) + sizeof(uint16_t)); + addr->len = sizeof(uint32_t) + sizeof(uint16_t); (void)memcpy((uint8_t *)addr->start, &b->sin_addr.s_addr, sizeof(uint32_t)); (void)memcpy((uint8_t *)(addr->start + sizeof(uint32_t)), &b->sin_port, sizeof(uint16_t)); } @@ -523,7 +523,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ (memcmp(a->sin6_addr.s6_addr, b->sin6_addr.s6_addr, sizeof(uint32_t) * 4UL) == 0))) { // If addr is not NULL, it means that the raddr was requested by the upper-layers if (addr != NULL) { - *addr = _z_slice_make((sizeof(uint32_t) * 4UL) + sizeof(uint16_t)); + addr->len = (sizeof(uint32_t) * 4UL) + sizeof(uint16_t); (void)memcpy((uint8_t *)addr->start, &b->sin6_addr.s6_addr, sizeof(uint32_t) * 4UL); (void)memcpy((uint8_t *)(addr->start + (sizeof(uint32_t) * 4UL)), &b->sin6_port, sizeof(uint16_t)); } diff --git a/src/transport/multicast/read.c b/src/transport/multicast/read.c index e3036af31..5cc377c5e 100644 --- a/src/transport/multicast/read.c +++ b/src/transport/multicast/read.c @@ -26,10 +26,13 @@ #if Z_FEATURE_MULTICAST_TRANSPORT == 1 +#define _Z_MULTICAST_ADDR_BUFF_SIZE 32 // Arbitrary size that must be able to contain any link address. + z_result_t _zp_multicast_read(_z_transport_multicast_t *ztm) { z_result_t ret = _Z_RES_OK; - _z_slice_t addr; + static uint8_t addr_buff[_Z_MULTICAST_ADDR_BUFF_SIZE] = {0}; + _z_slice_t addr = _z_slice_alias_buf(addr_buff, sizeof(addr_buff)); _z_transport_message_t t_msg; ret = _z_multicast_recv_t_msg(ztm, &t_msg, &addr); if (ret == _Z_RES_OK) { @@ -60,7 +63,8 @@ void *_zp_multicast_read_task(void *ztm_arg) { // Prepare the buffer _z_zbuf_reset(&ztm->_zbuf); - _z_slice_t addr = _z_slice_empty(); + uint8_t addr_buff[_Z_MULTICAST_ADDR_BUFF_SIZE] = {0}; + _z_slice_t addr = _z_slice_alias_buf(addr_buff, sizeof(addr_buff)); while (ztm->_read_task_running == true) { size_t to_read = 0; @@ -70,7 +74,6 @@ void *_zp_multicast_read_task(void *ztm_arg) { if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, &addr); if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_slice_clear(&addr); _z_zbuf_compact(&ztm->_zbuf); continue; } @@ -109,10 +112,8 @@ void *_zp_multicast_read_task(void *ztm_arg) { if (ret == _Z_RES_OK) { _z_t_msg_clear(&t_msg); - _z_slice_clear(&addr); } else { _Z_ERROR("Dropping message due to processing error: %d", ret); - _z_slice_clear(&addr); continue; } } else { From 232c445760df4fda2c2c7bbc2adb79b067823ab4 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Fri, 25 Oct 2024 17:42:37 +0200 Subject: [PATCH 07/17] Add local query timeout (#763) * refactor: rename session mutex function * fix: api options recopy * feat: add local query timeout info * feat: add local lazy query timeout check * feat: centralize query timeout process --- include/zenoh-pico/session/query.h | 2 ++ include/zenoh-pico/session/session.h | 2 ++ include/zenoh-pico/session/utils.h | 9 +++-- src/api/api.c | 15 +++----- src/net/primitives.c | 2 ++ src/session/interest.c | 44 +++++++++++------------ src/session/query.c | 52 ++++++++++++++++++++-------- src/session/queryable.c | 26 +++++++------- src/session/resource.c | 28 +++++++-------- src/session/subscription.c | 26 +++++++------- src/session/utils.c | 8 ----- src/transport/multicast/lease.c | 6 ++-- src/transport/unicast/lease.c | 7 ++-- 13 files changed, 126 insertions(+), 101 deletions(-) diff --git a/include/zenoh-pico/session/query.h b/include/zenoh-pico/session/query.h index 1bf03b74d..9a8ea69ae 100644 --- a/include/zenoh-pico/session/query.h +++ b/include/zenoh-pico/session/query.h @@ -18,6 +18,8 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +void _z_pending_query_process_timeout(_z_session_t *zn); + #if Z_FEATURE_QUERY == 1 /*------------------ Query ------------------*/ _z_zint_t _z_get_query_id(_z_session_t *zn); diff --git a/include/zenoh-pico/session/session.h b/include/zenoh-pico/session/session.h index 9d1d00038..194b7f898 100644 --- a/include/zenoh-pico/session/session.h +++ b/include/zenoh-pico/session/session.h @@ -121,6 +121,8 @@ typedef struct { _z_zint_t _id; _z_reply_handler_t _callback; _z_drop_handler_t _dropper; + z_clock_t _start_time; + uint64_t _timeout; void *_arg; _z_pending_reply_list_t *_pending_replies; z_query_target_t _target; diff --git a/include/zenoh-pico/session/utils.h b/include/zenoh-pico/session/utils.h index db7969a3c..2e3a47987 100644 --- a/include/zenoh-pico/session/utils.h +++ b/include/zenoh-pico/session/utils.h @@ -35,7 +35,12 @@ z_result_t _z_send_n_msg(_z_session_t *zn, _z_network_message_t *n_msg, z_reliab z_congestion_control_t cong_ctrl); z_result_t _z_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl); -void _zp_session_lock_mutex(_z_session_t *zn); -void _zp_session_unlock_mutex(_z_session_t *zn); +#if Z_FEATURE_MULTI_THREAD == 1 +static inline void _z_session_mutex_lock(_z_session_t *zn) { (void)_z_mutex_lock(&zn->_mutex_inner); } +static inline void _z_session_mutex_unlock(_z_session_t *zn) { (void)_z_mutex_unlock(&zn->_mutex_inner); } +#else +static inline void _z_session_mutex_lock(_z_session_t *zn) { _ZP_UNUSED(zn); } +static inline void _z_session_mutex_unlock(_z_session_t *zn) { _ZP_UNUSED(zn); } +#endif #endif /* INCLUDE_ZENOH_PICO_SESSION_UTILS_H */ diff --git a/src/api/api.c b/src/api/api.c index 3e1149a42..a2ed97a53 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -1076,14 +1076,7 @@ z_result_t z_get(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr z_get_options_t opt; z_get_options_default(&opt); if (options != NULL) { - opt.consolidation = options->consolidation; - opt.target = options->target; - opt.encoding = options->encoding; - opt.payload = options->payload; - opt.attachment = options->attachment; - opt.congestion_control = options->congestion_control; - opt.priority = options->priority; - opt.is_express = options->is_express; + opt = *options; } if (opt.consolidation.mode == Z_CONSOLIDATION_MODE_AUTO) { @@ -1170,7 +1163,7 @@ z_result_t z_declare_queryable(const z_loaned_session_t *zs, z_owned_queryable_t z_queryable_options_t opt; z_queryable_options_default(&opt); if (options != NULL) { - opt.complete = options->complete; + opt = *options; } queryable->_val = @@ -1472,7 +1465,7 @@ z_result_t zp_start_read_task(z_loaned_session_t *zs, const zp_task_read_options zp_task_read_options_t opt; zp_task_read_options_default(&opt); if (options != NULL) { - opt.task_attributes = options->task_attributes; + opt = *options; } return _zp_start_read_task(_Z_RC_IN_VAL(zs), opt.task_attributes); #else @@ -1504,7 +1497,7 @@ z_result_t zp_start_lease_task(z_loaned_session_t *zs, const zp_task_lease_optio zp_task_lease_options_t opt; zp_task_lease_options_default(&opt); if (options != NULL) { - opt.task_attributes = options->task_attributes; + opt = *options; } return _zp_start_lease_task(_Z_RC_IN_VAL(zs), opt.task_attributes); #else diff --git a/src/net/primitives.c b/src/net/primitives.c index 96c0b919f..c2232d6b4 100644 --- a/src/net/primitives.c +++ b/src/net/primitives.c @@ -469,6 +469,8 @@ z_result_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *paramete pq->_dropper = dropper; pq->_pending_replies = NULL; pq->_arg = arg; + pq->_timeout = timeout_ms; + pq->_start_time = z_clock_now(); ret = _z_register_pending_query(zn, pq); // Add the pending query to the current session if (ret == _Z_RES_OK) { diff --git a/src/session/interest.c b/src/session/interest.c index 1467cf874..033942773 100644 --- a/src/session/interest.c +++ b/src/session/interest.c @@ -94,9 +94,9 @@ static _z_session_interest_rc_list_t *__unsafe_z_get_interest_by_key_and_flags(_ } static z_result_t _z_interest_send_decl_resource(_z_session_t *zn, uint32_t interest_id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_list_t *res_list = _z_resource_list_clone(zn->_local_resources); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); _z_resource_list_t *xs = res_list; while (xs != NULL) { _z_resource_t *res = _z_resource_list_head(xs); @@ -116,9 +116,9 @@ static z_result_t _z_interest_send_decl_resource(_z_session_t *zn, uint32_t inte #if Z_FEATURE_SUBSCRIPTION == 1 static z_result_t _z_interest_send_decl_subscriber(_z_session_t *zn, uint32_t interest_id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_subscription_rc_list_t *sub_list = _z_subscription_rc_list_clone(zn->_local_subscriptions); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); _z_subscription_rc_list_t *xs = sub_list; while (xs != NULL) { _z_subscription_rc_t *sub = _z_subscription_rc_list_head(xs); @@ -145,9 +145,9 @@ static z_result_t _z_interest_send_decl_subscriber(_z_session_t *zn, uint32_t in #if Z_FEATURE_QUERYABLE == 1 static z_result_t _z_interest_send_decl_queryable(_z_session_t *zn, uint32_t interest_id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_queryable_rc_list_t *qle_list = _z_session_queryable_rc_list_clone(zn->_local_queryable); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); _z_session_queryable_rc_list_t *xs = qle_list; while (xs != NULL) { _z_session_queryable_rc_t *qle = _z_session_queryable_rc_list_head(xs); @@ -184,9 +184,9 @@ static z_result_t _z_interest_send_declare_final(_z_session_t *zn, uint32_t inte } _z_session_interest_rc_t *_z_get_interest_by_id(_z_session_t *zn, const _z_zint_t id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_interest_rc_t *intr = __unsafe_z_get_interest_by_id(zn, id); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return intr; } @@ -195,13 +195,13 @@ _z_session_interest_rc_t *_z_register_interest(_z_session_t *zn, _z_session_inte (int)_z_string_len(&intr->_key._suffix), _z_string_data(&intr->_key._suffix)); _z_session_interest_rc_t *ret = NULL; - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); ret = (_z_session_interest_rc_t *)z_malloc(sizeof(_z_session_interest_rc_t)); if (ret != NULL) { *ret = _z_session_interest_rc_new_from_val(intr); zn->_local_interests = _z_session_interest_rc_list_push(zn->_local_interests, ret); } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return ret; } @@ -269,17 +269,17 @@ z_result_t _z_interest_process_declares(_z_session_t *zn, const _z_declaration_t return _Z_ERR_MESSAGE_ZENOH_DECLARATION_UNKNOWN; } // Retrieve key - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, decl_key); if (!_z_keyexpr_has_suffix(&key)) { - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return _Z_ERR_KEYEXPR_UNKNOWN; } // Register declare _unsafe_z_register_declare(zn, &key, msg.id, decl_type); // Retrieve interests _z_session_interest_rc_list_t *intrs = __unsafe_z_get_interest_by_key_and_flags(zn, flags, &key); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); // Parse session_interest list _z_session_interest_rc_list_t *xs = intrs; while (xs != NULL) { @@ -315,17 +315,17 @@ z_result_t _z_interest_process_undeclares(_z_session_t *zn, const _z_declaration default: return _Z_ERR_MESSAGE_ZENOH_DECLARATION_UNKNOWN; } - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); // Retrieve declare data _z_keyexpr_t key = _unsafe_z_get_key_from_declare(zn, msg.id, decl_type); if (!_z_keyexpr_has_suffix(&key)) { - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return _Z_ERR_KEYEXPR_UNKNOWN; } _z_session_interest_rc_list_t *intrs = __unsafe_z_get_interest_by_key_and_flags(zn, flags, &key); // Remove declare _unsafe_z_unregister_declare(zn, msg.id, decl_type); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); // Parse session_interest list _z_session_interest_rc_list_t *xs = intrs; @@ -343,25 +343,25 @@ z_result_t _z_interest_process_undeclares(_z_session_t *zn, const _z_declaration } void _z_unregister_interest(_z_session_t *zn, _z_session_interest_rc_t *intr) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); zn->_local_interests = _z_session_interest_rc_list_drop_filter(zn->_local_interests, _z_session_interest_rc_eq, intr); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } void _z_flush_interest(_z_session_t *zn) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_interest_rc_list_free(&zn->_local_interests); _z_declare_data_list_free(&zn->_remote_declares); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } z_result_t _z_interest_process_declare_final(_z_session_t *zn, uint32_t id) { _z_interest_msg_t msg = {.type = _Z_INTEREST_MSG_TYPE_FINAL, .id = id}; // Retrieve interest - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_interest_rc_t *intr = __unsafe_z_get_interest_by_id(zn, id); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); if (intr == NULL) { return _Z_RES_OK; } diff --git a/src/session/query.c b/src/session/query.c index f3401dace..150d9c54f 100644 --- a/src/session/query.c +++ b/src/session/query.c @@ -35,6 +35,23 @@ void _z_pending_query_clear(_z_pending_query_t *pen_qry) { bool _z_pending_query_eq(const _z_pending_query_t *one, const _z_pending_query_t *two) { return one->_id == two->_id; } +static bool _z_pending_query_timeout(const _z_pending_query_t *foo, const _z_pending_query_t *pq) { + _ZP_UNUSED(foo); + bool result = z_clock_elapsed_ms((z_clock_t *)&pq->_start_time) >= pq->_timeout; + if (result) { + _Z_INFO("Dropping query because of timeout"); + } + return result; +} + +void _z_pending_query_process_timeout(_z_session_t *zn) { + // Lock session + _z_session_mutex_lock(zn); + // Drop all queries with timeout elapsed + zn->_pending_queries = _z_pending_query_list_drop_filter(zn->_pending_queries, _z_pending_query_timeout, NULL); + _z_session_mutex_unlock(zn); +} + /*------------------ Query ------------------*/ _z_zint_t _z_get_query_id(_z_session_t *zn) { return zn->_query_id++; } @@ -66,11 +83,11 @@ _z_pending_query_t *__unsafe__z_get_pending_query_by_id(_z_session_t *zn, const } _z_pending_query_t *_z_get_pending_query_by_id(_z_session_t *zn, const _z_zint_t id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_pending_query_t *pql = __unsafe__z_get_pending_query_by_id(zn, id); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return pql; } @@ -80,7 +97,7 @@ z_result_t _z_register_pending_query(_z_session_t *zn, _z_pending_query_t *pen_q _Z_DEBUG(">>> Allocating query for (%ju:%.*s)", (uintmax_t)pen_qry->_key._id, (int)_z_string_len(&pen_qry->_key._suffix), _z_string_data(&pen_qry->_key._suffix)); - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_pending_query_t *pql = __unsafe__z_get_pending_query_by_id(zn, pen_qry->_id); if (pql == NULL) { // Register query only if a pending one with the same ID does not exist @@ -89,7 +106,7 @@ z_result_t _z_register_pending_query(_z_session_t *zn, _z_pending_query_t *pen_q ret = _Z_ERR_ENTITY_DECLARATION_FAILED; } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return ret; } @@ -98,7 +115,7 @@ z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, _z_msg_put_t *msg, z_sample_kind_t kind) { z_result_t ret = _Z_RES_OK; - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, id); if ((ret == _Z_RES_OK) && (pen_qry == NULL)) { @@ -162,7 +179,7 @@ z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, } } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); // Trigger the user callback if ((ret == _Z_RES_OK) && (pen_qry->_consolidation != Z_CONSOLIDATION_MODE_LATEST)) { @@ -183,7 +200,7 @@ z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, z_result_t _z_trigger_query_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *msg) { z_result_t ret = _Z_RES_OK; - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, id); if ((ret == _Z_RES_OK) && (pen_qry == NULL)) { @@ -193,7 +210,7 @@ z_result_t _z_trigger_query_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err // Build the reply _z_reply_t reply = _z_reply_err_create(msg->_payload, &msg->_encoding); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); // Trigger the user callback if (ret == _Z_RES_OK) { @@ -213,7 +230,7 @@ z_result_t _z_trigger_query_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err z_result_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id) { z_result_t ret = _Z_RES_OK; - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); // Final reply received for unknown query id _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, id); @@ -239,24 +256,31 @@ z_result_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id) { zn->_pending_queries = _z_pending_query_list_drop_filter(zn->_pending_queries, _z_pending_query_eq, pen_qry); } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return ret; } void _z_unregister_pending_query(_z_session_t *zn, _z_pending_query_t *pen_qry) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); zn->_pending_queries = _z_pending_query_list_drop_filter(zn->_pending_queries, _z_pending_query_eq, pen_qry); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } void _z_flush_pending_queries(_z_session_t *zn) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_pending_query_list_free(&zn->_pending_queries); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); +} +#else + +void _z_pending_query_process_timeout(_z_session_t *zn) { + _ZP_UNUSED(zn); + return; } + #endif diff --git a/src/session/queryable.c b/src/session/queryable.c index 3e05a70c3..a7a25eaee 100644 --- a/src/session/queryable.c +++ b/src/session/queryable.c @@ -94,22 +94,22 @@ _z_session_queryable_rc_list_t *__unsafe_z_get_session_queryable_by_key(_z_sessi } _z_session_queryable_rc_t *_z_get_session_queryable_by_id(_z_session_t *zn, const _z_zint_t id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_queryable_rc_t *qle = __unsafe_z_get_session_queryable_by_id(zn, id); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return qle; } _z_session_queryable_rc_list_t *_z_get_session_queryable_by_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr); _z_session_queryable_rc_list_t *qles = __unsafe_z_get_session_queryable_by_key(zn, key); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return qles; } @@ -119,7 +119,7 @@ _z_session_queryable_rc_t *_z_register_session_queryable(_z_session_t *zn, _z_se _z_string_data(&q->_key._suffix)); _z_session_queryable_rc_t *ret = NULL; - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); ret = (_z_session_queryable_rc_t *)z_malloc(sizeof(_z_session_queryable_rc_t)); if (ret != NULL) { @@ -127,7 +127,7 @@ _z_session_queryable_rc_t *_z_register_session_queryable(_z_session_t *zn, _z_se zn->_local_queryable = _z_session_queryable_rc_list_push(zn->_local_queryable, ret); } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return ret; } @@ -137,13 +137,13 @@ z_result_t _z_trigger_queryables(_z_session_rc_t *zsrc, _z_msg_query_t *msgq, co z_result_t ret = _Z_RES_OK; _z_session_t *zn = _Z_RC_IN_VAL(zsrc); - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, &q_key); if (_z_keyexpr_has_suffix(&key)) { _z_session_queryable_rc_list_t *qles = __unsafe_z_get_session_queryable_by_key(zn, key); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); // Build the z_query _z_query_t q = _z_query_create(&msgq->_ext_value, &key, &msgq->_parameters, zsrc, qid, attachment); @@ -159,7 +159,7 @@ z_result_t _z_trigger_queryables(_z_session_rc_t *zsrc, _z_msg_query_t *msgq, co _z_query_rc_drop(&query); _z_session_queryable_rc_list_free(&qles); } else { - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); ret = _Z_ERR_KEYEXPR_UNKNOWN; } @@ -167,20 +167,20 @@ z_result_t _z_trigger_queryables(_z_session_rc_t *zsrc, _z_msg_query_t *msgq, co } void _z_unregister_session_queryable(_z_session_t *zn, _z_session_queryable_rc_t *qle) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); zn->_local_queryable = _z_session_queryable_rc_list_drop_filter(zn->_local_queryable, _z_session_queryable_rc_eq, qle); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } void _z_flush_session_queryable(_z_session_t *zn) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_session_queryable_rc_list_free(&zn->_local_queryable); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } #endif diff --git a/src/session/resource.c b/src/session/resource.c index d90a53ca3..37c19411a 100644 --- a/src/session/resource.c +++ b/src/session/resource.c @@ -175,11 +175,11 @@ _z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_key } _z_resource_t *_z_get_resource_by_id(_z_session_t *zn, uint16_t mapping, _z_zint_t rid) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_t *res = __unsafe_z_get_resource_by_id(zn, mapping, rid); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return res; } @@ -188,20 +188,20 @@ _z_resource_t *_z_get_resource_by_key(_z_session_t *zn, const _z_keyexpr_t *keye if (!_z_keyexpr_has_suffix(keyexpr)) { return _z_get_resource_by_id(zn, _z_keyexpr_mapping_id(keyexpr), keyexpr->_id); } - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_t *res = __unsafe_z_get_resource_by_key(zn, keyexpr); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return res; } _z_keyexpr_t _z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_keyexpr_t res = __unsafe_z_get_expanded_key_from_key(zn, keyexpr); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return res; } @@ -212,7 +212,7 @@ uint16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, u uint16_t mapping = register_to_mapping; uint16_t parent_mapping = _z_keyexpr_mapping_id(&key); - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); if (key._id != Z_RESOURCE_ID_NONE) { if (parent_mapping == mapping) { @@ -241,7 +241,7 @@ uint16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, u } } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return ret; } @@ -249,7 +249,7 @@ uint16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, u void _z_unregister_resource(_z_session_t *zn, uint16_t id, uint16_t mapping) { bool is_local = mapping == _Z_KEYEXPR_MAPPING_LOCAL; _Z_DEBUG("unregistering: id %d, mapping: %d", id, mapping); - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_list_t **parent_mut = is_local ? &zn->_local_resources : &zn->_remote_resources; while (id != 0) { _z_resource_list_t *parent = *parent_mut; @@ -271,7 +271,7 @@ void _z_unregister_resource(_z_session_t *zn, uint16_t id, uint16_t mapping) { parent = *parent_mut; } } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } bool _z_unregister_resource_for_peer_filter(const _z_resource_t *candidate, const _z_resource_t *ctx) { @@ -279,19 +279,19 @@ bool _z_unregister_resource_for_peer_filter(const _z_resource_t *candidate, cons return _z_keyexpr_mapping_id(&candidate->_key) == mapping; } void _z_unregister_resources_for_peer(_z_session_t *zn, uint16_t mapping) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_t ctx = {._id = mapping, ._refcount = 0, ._key = {0}}; zn->_remote_resources = _z_resource_list_drop_filter(zn->_remote_resources, _z_unregister_resource_for_peer_filter, &ctx); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } void _z_flush_resources(_z_session_t *zn) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_resource_list_free(&zn->_local_resources); _z_resource_list_free(&zn->_remote_resources); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } diff --git a/src/session/subscription.c b/src/session/subscription.c index 7d8117101..db397367f 100644 --- a/src/session/subscription.c +++ b/src/session/subscription.c @@ -97,21 +97,21 @@ _z_subscription_rc_list_t *__unsafe_z_get_subscriptions_by_key(_z_session_t *zn, } _z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_subscription_rc_t *sub = __unsafe_z_get_subscription_by_id(zn, is_local, id); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return sub; } _z_subscription_rc_list_t *_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *key) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, is_local, key); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return subs; } @@ -121,7 +121,7 @@ _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_loca _z_string_data(&s->_key._suffix)); _z_subscription_rc_t *ret = NULL; - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); ret = (_z_subscription_rc_t *)z_malloc(sizeof(_z_subscription_rc_t)); if (ret != NULL) { @@ -133,7 +133,7 @@ _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_loca } } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); return ret; } @@ -151,7 +151,7 @@ z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexp const _z_n_qos_t qos, const _z_bytes_t *attachment, z_reliability_t reliability) { z_result_t ret = _Z_RES_OK; - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr->_id, (int)_z_string_len(&keyexpr->_suffix), _z_string_data(&keyexpr->_suffix), _z_keyexpr_mapping_id(keyexpr)); @@ -159,7 +159,7 @@ z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexp _Z_DEBUG("Triggering subs for %d - %.*s", key._id, (int)_z_string_len(&key._suffix), _z_string_data(&key._suffix)); if (_z_keyexpr_has_suffix(&key)) { _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, &key); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); // Check if there is subs size_t sub_nb = _z_subscription_rc_list_len(subs); @@ -180,7 +180,7 @@ z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexp _z_sample_clear(&sample); _z_subscription_rc_list_free(&subs); } else { - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); ret = _Z_ERR_KEYEXPR_UNKNOWN; } @@ -188,7 +188,7 @@ z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexp } void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); if (is_local == _Z_RESOURCE_IS_LOCAL) { zn->_local_subscriptions = @@ -198,16 +198,16 @@ void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscript _z_subscription_rc_list_drop_filter(zn->_remote_subscriptions, _z_subscription_rc_eq, sub); } - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } void _z_flush_subscriptions(_z_session_t *zn) { - _zp_session_lock_mutex(zn); + _z_session_mutex_lock(zn); _z_subscription_rc_list_free(&zn->_local_subscriptions); _z_subscription_rc_list_free(&zn->_remote_subscriptions); - _zp_session_unlock_mutex(zn); + _z_session_mutex_unlock(zn); } #else // Z_FEATURE_SUBSCRIPTION == 0 diff --git a/src/session/utils.c b/src/session/utils.c index 05d8da358..f88fcf03d 100644 --- a/src/session/utils.c +++ b/src/session/utils.c @@ -134,11 +134,3 @@ z_result_t _z_session_close(_z_session_t *zn, uint8_t reason) { return ret; } - -#if Z_FEATURE_MULTI_THREAD == 1 -void _zp_session_lock_mutex(_z_session_t *zn) { (void)_z_mutex_lock(&zn->_mutex_inner); } -void _zp_session_unlock_mutex(_z_session_t *zn) { (void)_z_mutex_unlock(&zn->_mutex_inner); } -#else -void _zp_session_lock_mutex(_z_session_t *zn) { _ZP_UNUSED(zn); } -void _zp_session_unlock_mutex(_z_session_t *zn) { _ZP_UNUSED(zn); } -#endif diff --git a/src/transport/multicast/lease.c b/src/transport/multicast/lease.c index 50c299f3a..b97663c8f 100644 --- a/src/transport/multicast/lease.c +++ b/src/transport/multicast/lease.c @@ -17,6 +17,7 @@ #include #include "zenoh-pico/config.h" +#include "zenoh-pico/session/query.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/multicast/lease.h" #include "zenoh-pico/utils/logging.h" @@ -131,14 +132,15 @@ void *_zp_multicast_lease_task(void *ztm_arg) { // Check if need to send a keep alive if (ztm->_transmitted == false) { if (_zp_multicast_send_keep_alive(ztm) < 0) { - // TODO: Handle retransmission or error + _Z_INFO("Send keep alive failed."); } } - // Reset the keep alive parameters ztm->_transmitted = false; next_keep_alive = (int)(_z_get_minimum_lease(ztm->_peers, ztm->_lease) / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); } + // Query timeout process + _z_pending_query_process_timeout(_Z_RC_IN_VAL(ztm->_session)); // Compute the target interval to sleep int interval; diff --git a/src/transport/unicast/lease.c b/src/transport/unicast/lease.c index 32358eaba..1e3da00cd 100644 --- a/src/transport/unicast/lease.c +++ b/src/transport/unicast/lease.c @@ -14,6 +14,8 @@ #include "zenoh-pico/transport/unicast/lease.h" +#include "zenoh-pico/session/query.h" +#include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/unicast/transport.h" #include "zenoh-pico/transport/unicast/tx.h" #include "zenoh-pico/utils/logging.h" @@ -66,14 +68,15 @@ void *_zp_unicast_lease_task(void *ztu_arg) { // Check if need to send a keep alive if (ztu->_transmitted == false) { if (_zp_unicast_send_keep_alive(ztu) < 0) { - // TODO: Handle retransmission or error + _Z_INFO("Send keep alive failed."); } } - // Reset the keep alive parameters ztu->_transmitted = false; next_keep_alive = (int)(ztu->_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); } + // Query timeout process + _z_pending_query_process_timeout(_Z_RC_IN_VAL(ztu->_session)); // Compute the target interval int interval; From 5dd1fcd54c2b553cd50e65b1ff11a19e20a57daa Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Mon, 28 Oct 2024 13:35:30 +0100 Subject: [PATCH 08/17] Add peer tcp unicast (#764) * feat: add tcp dummy functions * feat: add unix listen_tcp * fix: don't print error if connection is closed * feat: add is_open arg for peer mode * fix: listen tcp * feat: add peer unicast * refactor: _z_open * fix: peer multicast test config * fix: timing * feat: switch from bool to enum * feat: remove tcp peer timing --- include/zenoh-pico/link/manager.h | 3 +- include/zenoh-pico/transport/manager.h | 7 +- .../zenoh-pico/transport/unicast/transport.h | 2 +- src/link/link.c | 9 +- src/link/unicast/tcp.c | 11 + src/net/session.c | 140 +++++----- src/system/unix/network.c | 69 ++++- src/transport/manager.c | 16 +- src/transport/unicast/read.c | 4 +- src/transport/unicast/transport.c | 254 +++++++++++------- tests/z_peer_multicast_test.c | 2 +- 11 files changed, 334 insertions(+), 183 deletions(-) diff --git a/include/zenoh-pico/link/manager.h b/include/zenoh-pico/link/manager.h index e0aba1f93..d9e716ecc 100644 --- a/include/zenoh-pico/link/manager.h +++ b/include/zenoh-pico/link/manager.h @@ -19,10 +19,9 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/link/link.h" -#if Z_FEATURE_LINK_TCP == 1 z_result_t _z_endpoint_tcp_valid(_z_endpoint_t *ep); z_result_t _z_new_link_tcp(_z_link_t *zl, _z_endpoint_t *ep); -#endif + #if Z_FEATURE_LINK_UDP_UNICAST == 1 z_result_t _z_endpoint_udp_unicast_valid(_z_endpoint_t *ep); z_result_t _z_new_link_udp_unicast(_z_link_t *zl, _z_endpoint_t ep); diff --git a/include/zenoh-pico/transport/manager.h b/include/zenoh-pico/transport/manager.h index 8ac95dd7c..b850e506e 100644 --- a/include/zenoh-pico/transport/manager.h +++ b/include/zenoh-pico/transport/manager.h @@ -19,7 +19,12 @@ #include "zenoh-pico/link/manager.h" #include "zenoh-pico/transport/transport.h" -z_result_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, _z_string_t *locator, z_whatami_t mode); +enum _z_peer_op_e { + _Z_PEER_OP_OPEN = 0, + _Z_PEER_OP_LISTEN = 1, +}; + +z_result_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, _z_string_t *locator, z_whatami_t mode, int peer_op); void _z_free_transport(_z_transport_t **zt); #endif /* INCLUDE_ZENOH_PICO_TRANSPORT_MANAGER_H */ diff --git a/include/zenoh-pico/transport/unicast/transport.h b/include/zenoh-pico/transport/unicast/transport.h index df0ca1ff8..d6eeb1599 100644 --- a/include/zenoh-pico/transport/unicast/transport.h +++ b/include/zenoh-pico/transport/unicast/transport.h @@ -22,7 +22,7 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, const _z_id_t *local_zid); z_result_t _z_unicast_open_peer(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_id_t *local_zid); + const _z_id_t *local_zid, int peer_op); z_result_t _z_unicast_send_close(_z_transport_unicast_t *ztu, uint8_t reason, bool link_only); z_result_t _z_unicast_transport_close(_z_transport_unicast_t *ztu, uint8_t reason); void _z_unicast_transport_clear(_z_transport_t *zt); diff --git a/src/link/link.c b/src/link/link.c index 9f725ee9c..8c5ffb312 100644 --- a/src/link/link.c +++ b/src/link/link.c @@ -27,13 +27,10 @@ z_result_t _z_open_link(_z_link_t *zl, _z_string_t *locator) { _z_endpoint_t ep; ret = _z_endpoint_from_string(&ep, locator); if (ret == _Z_RES_OK) { - // TODO[peer]: when peer unicast mode is supported, this must be revisited // Create transport link -#if Z_FEATURE_LINK_TCP == 1 if (_z_endpoint_tcp_valid(&ep) == _Z_RES_OK) { ret = _z_new_link_tcp(zl, &ep); } else -#endif #if Z_FEATURE_LINK_UDP_UNICAST == 1 if (_z_endpoint_udp_unicast_valid(&ep) == _Z_RES_OK) { ret = _z_new_link_udp_unicast(zl, ep); @@ -80,10 +77,12 @@ z_result_t _z_listen_link(_z_link_t *zl, _z_string_t *locator) { _z_endpoint_t ep; ret = _z_endpoint_from_string(&ep, locator); if (ret == _Z_RES_OK) { - // TODO[peer]: when peer unicast mode is supported, this must be revisited // Create transport link + if (_z_endpoint_tcp_valid(&ep) == _Z_RES_OK) { + ret = _z_new_link_tcp(zl, &ep); + } else #if Z_FEATURE_LINK_UDP_MULTICAST == 1 - if (_z_endpoint_udp_multicast_valid(&ep) == _Z_RES_OK) { + if (_z_endpoint_udp_multicast_valid(&ep) == _Z_RES_OK) { ret = _z_new_link_udp_multicast(zl, ep); } else #endif diff --git a/src/link/unicast/tcp.c b/src/link/unicast/tcp.c index d55cf7c31..232b7ffdc 100644 --- a/src/link/unicast/tcp.c +++ b/src/link/unicast/tcp.c @@ -188,4 +188,15 @@ z_result_t _z_new_link_tcp(_z_link_t *zl, _z_endpoint_t *endpoint) { return ret; } +#else +z_result_t _z_endpoint_tcp_valid(_z_endpoint_t *endpoint) { + _ZP_UNUSED(endpoint); + return _Z_ERR_TRANSPORT_NOT_AVAILABLE; +} + +z_result_t _z_new_link_tcp(_z_link_t *zl, _z_endpoint_t *endpoint) { + _ZP_UNUSED(zl); + _ZP_UNUSED(endpoint); + return _Z_ERR_TRANSPORT_NOT_AVAILABLE; +} #endif diff --git a/src/net/session.c b/src/net/session.c index 0e8fcac4e..cf86220cd 100644 --- a/src/net/session.c +++ b/src/net/session.c @@ -37,7 +37,7 @@ #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/uuid.h" -z_result_t __z_open_inner(_z_session_rc_t *zn, _z_string_t *locator, z_whatami_t mode) { +static z_result_t __z_open_inner(_z_session_rc_t *zn, _z_string_t *locator, z_whatami_t mode, int peer_op) { z_result_t ret = _Z_RES_OK; _z_id_t local_zid = _z_id_empty(); @@ -46,7 +46,7 @@ z_result_t __z_open_inner(_z_session_rc_t *zn, _z_string_t *locator, z_whatami_t local_zid = _z_id_empty(); return ret; } - ret = _z_new_transport(&_Z_RC_IN_VAL(zn)->_tp, &local_zid, locator, mode); + ret = _z_new_transport(&_Z_RC_IN_VAL(zn)->_tp, &local_zid, locator, mode, peer_op); if (ret != _Z_RES_OK) { local_zid = _z_id_empty(); return ret; @@ -64,89 +64,89 @@ z_result_t _z_open(_z_session_rc_t *zn, _z_config_t *config) { if (opt_as_str != NULL) { _z_uuid_to_bytes(zid.id, opt_as_str); } + if (config == NULL) { + _Z_ERROR("A valid config is missing."); + return _Z_ERR_GENERIC; + } + int peer_op = _Z_PEER_OP_LISTEN; + _z_string_svec_t locators = _z_string_svec_make(0); + char *connect = _z_config_get(config, Z_CONFIG_CONNECT_KEY); + char *listen = _z_config_get(config, Z_CONFIG_LISTEN_KEY); + if (connect == NULL && listen == NULL) { // Scout if peer is not configured + opt_as_str = _z_config_get(config, Z_CONFIG_SCOUTING_WHAT_KEY); + if (opt_as_str == NULL) { + opt_as_str = (char *)Z_CONFIG_SCOUTING_WHAT_DEFAULT; + } + z_what_t what = strtol(opt_as_str, NULL, 10); - if (config != NULL) { - _z_string_svec_t locators = _z_string_svec_make(0); - char *connect = _z_config_get(config, Z_CONFIG_CONNECT_KEY); - char *listen = _z_config_get(config, Z_CONFIG_LISTEN_KEY); - if (connect == NULL && listen == NULL) { // Scout if peer is not configured - opt_as_str = _z_config_get(config, Z_CONFIG_SCOUTING_WHAT_KEY); - if (opt_as_str == NULL) { - opt_as_str = (char *)Z_CONFIG_SCOUTING_WHAT_DEFAULT; - } - z_what_t what = strtol(opt_as_str, NULL, 10); - - opt_as_str = _z_config_get(config, Z_CONFIG_MULTICAST_LOCATOR_KEY); - if (opt_as_str == NULL) { - opt_as_str = (char *)Z_CONFIG_MULTICAST_LOCATOR_DEFAULT; - } - _z_string_t mcast_locator = _z_string_alias_str(opt_as_str); + opt_as_str = _z_config_get(config, Z_CONFIG_MULTICAST_LOCATOR_KEY); + if (opt_as_str == NULL) { + opt_as_str = (char *)Z_CONFIG_MULTICAST_LOCATOR_DEFAULT; + } + _z_string_t mcast_locator = _z_string_alias_str(opt_as_str); - opt_as_str = _z_config_get(config, Z_CONFIG_SCOUTING_TIMEOUT_KEY); - if (opt_as_str == NULL) { - opt_as_str = (char *)Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT; - } - uint32_t timeout = (uint32_t)strtoul(opt_as_str, NULL, 10); + opt_as_str = _z_config_get(config, Z_CONFIG_SCOUTING_TIMEOUT_KEY); + if (opt_as_str == NULL) { + opt_as_str = (char *)Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT; + } + uint32_t timeout = (uint32_t)strtoul(opt_as_str, NULL, 10); - // Scout and return upon the first result - _z_hello_list_t *hellos = _z_scout_inner(what, zid, &mcast_locator, timeout, true); - if (hellos != NULL) { - _z_hello_t *hello = _z_hello_list_head(hellos); - _z_string_svec_copy(&locators, &hello->_locators); + // Scout and return upon the first result + _z_hello_list_t *hellos = _z_scout_inner(what, zid, &mcast_locator, timeout, true); + if (hellos != NULL) { + _z_hello_t *hello = _z_hello_list_head(hellos); + _z_string_svec_copy(&locators, &hello->_locators); + } + _z_hello_list_free(&hellos); + } else { + uint_fast8_t key = Z_CONFIG_CONNECT_KEY; + if (listen != NULL) { + if (connect == NULL) { + key = Z_CONFIG_LISTEN_KEY; + _zp_config_insert(config, Z_CONFIG_MODE_KEY, Z_CONFIG_MODE_PEER); + } else { + return _Z_ERR_GENERIC; } - _z_hello_list_free(&hellos); } else { - uint_fast8_t key = Z_CONFIG_CONNECT_KEY; - if (listen != NULL) { - if (connect == NULL) { - key = Z_CONFIG_LISTEN_KEY; - _zp_config_insert(config, Z_CONFIG_MODE_KEY, Z_CONFIG_MODE_PEER); - } else { - return _Z_ERR_GENERIC; - } - } - locators = _z_string_svec_make(1); - _z_string_t s = _z_string_copy_from_str(_z_config_get(config, key)); - _z_string_svec_append(&locators, &s); + peer_op = _Z_PEER_OP_OPEN; } + locators = _z_string_svec_make(1); + _z_string_t s = _z_string_copy_from_str(_z_config_get(config, key)); + _z_string_svec_append(&locators, &s); + } - ret = _Z_ERR_SCOUT_NO_RESULTS; - size_t len = _z_string_svec_len(&locators); - for (size_t i = 0; i < len; i++) { - ret = _Z_RES_OK; + ret = _Z_ERR_SCOUT_NO_RESULTS; + size_t len = _z_string_svec_len(&locators); + for (size_t i = 0; i < len; i++) { + ret = _Z_RES_OK; - _z_string_t *locator = _z_string_svec_get(&locators, i); - // @TODO: check invalid configurations - // For example, client mode in multicast links + _z_string_t *locator = _z_string_svec_get(&locators, i); + // @TODO: check invalid configurations + // For example, client mode in multicast links - // Check operation mode - char *s_mode = _z_config_get(config, Z_CONFIG_MODE_KEY); - z_whatami_t mode = Z_WHATAMI_CLIENT; // By default, zenoh-pico will operate as a client - if (s_mode != NULL) { - if (_z_str_eq(s_mode, Z_CONFIG_MODE_CLIENT) == true) { - mode = Z_WHATAMI_CLIENT; - } else if (_z_str_eq(s_mode, Z_CONFIG_MODE_PEER) == true) { - mode = Z_WHATAMI_PEER; - } else { - ret = _Z_ERR_CONFIG_INVALID_MODE; - } + // Check operation mode + char *s_mode = _z_config_get(config, Z_CONFIG_MODE_KEY); + z_whatami_t mode = Z_WHATAMI_CLIENT; // By default, zenoh-pico will operate as a client + if (s_mode != NULL) { + if (_z_str_eq(s_mode, Z_CONFIG_MODE_CLIENT) == true) { + mode = Z_WHATAMI_CLIENT; + } else if (_z_str_eq(s_mode, Z_CONFIG_MODE_PEER) == true) { + mode = Z_WHATAMI_PEER; + } else { + ret = _Z_ERR_CONFIG_INVALID_MODE; } + } + if (ret == _Z_RES_OK) { + ret = __z_open_inner(zn, locator, mode, peer_op); if (ret == _Z_RES_OK) { - ret = __z_open_inner(zn, locator, mode); - if (ret == _Z_RES_OK) { - break; - } - } else { - _Z_ERROR("Trying to configure an invalid mode."); + break; } + } else { + _Z_ERROR("Trying to configure an invalid mode."); } - _z_string_svec_clear(&locators); - } else { - _Z_ERROR("A valid config is missing."); - ret = _Z_ERR_GENERIC; } - + _z_string_svec_clear(&locators); return ret; } diff --git a/src/system/unix/network.c b/src/system/unix/network.c index 978b61315..c822e4aa5 100644 --- a/src/system/unix/network.c +++ b/src/system/unix/network.c @@ -115,12 +115,69 @@ z_result_t _z_open_tcp(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t re z_result_t _z_listen_tcp(_z_sys_net_socket_t *sock, const _z_sys_net_endpoint_t lep) { z_result_t ret = _Z_RES_OK; - (void)sock; - (void)lep; - - // @TODO: To be implemented - ret = _Z_ERR_GENERIC; - + // Open socket + sock->_fd = socket(lep._iptcp->ai_family, lep._iptcp->ai_socktype, lep._iptcp->ai_protocol); + if (sock->_fd == -1) { + return _Z_ERR_GENERIC; + } + // Set options + int value = true; + if ((ret == _Z_RES_OK) && (setsockopt(sock->_fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) < 0)) { + ret = _Z_ERR_GENERIC; + } + int flags = 1; + if ((ret == _Z_RES_OK) && (setsockopt(sock->_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags, sizeof(flags)) < 0)) { + ret = _Z_ERR_GENERIC; + } +#if Z_FEATURE_TCP_NODELAY == 1 + if ((ret == _Z_RES_OK) && (setsockopt(sock->_fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)) < 0)) { + ret = _Z_ERR_GENERIC; + } +#endif + struct linger ling; + ling.l_onoff = 1; + ling.l_linger = Z_TRANSPORT_LEASE / 1000; + if ((ret == _Z_RES_OK) && + (setsockopt(sock->_fd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(struct linger)) < 0)) { + ret = _Z_ERR_GENERIC; + } +#if defined(ZENOH_MACOS) || defined(ZENOH_BSD) + setsockopt(sock->_fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)0, sizeof(int)); +#endif + if (ret != _Z_RES_OK) { + close(sock->_fd); + return ret; + } + struct addrinfo *it = NULL; + for (it = lep._iptcp; it != NULL; it = it->ai_next) { + if (bind(sock->_fd, it->ai_addr, it->ai_addrlen) < 0) { + if (it->ai_next == NULL) { + ret = _Z_ERR_GENERIC; + break; + } + } + if (listen(sock->_fd, 1) < 0) { + if (it->ai_next == NULL) { + ret = _Z_ERR_GENERIC; + break; + } + } + struct sockaddr naddr; + unsigned int nlen = sizeof(naddr); + int con_socket = accept(sock->_fd, &naddr, &nlen); + if (con_socket < 0) { + if (it->ai_next == NULL) { + ret = _Z_ERR_GENERIC; + break; + } + } else { + sock->_fd = con_socket; + break; + } + } + if (ret != _Z_RES_OK) { + close(sock->_fd); + } return ret; } diff --git a/src/transport/manager.c b/src/transport/manager.c index 360f5329d..6b2447eea 100644 --- a/src/transport/manager.c +++ b/src/transport/manager.c @@ -20,7 +20,7 @@ #include "zenoh-pico/transport/multicast/transport.h" #include "zenoh-pico/transport/unicast/transport.h" -z_result_t _z_new_transport_client(_z_transport_t *zt, _z_string_t *locator, _z_id_t *local_zid) { +static z_result_t _z_new_transport_client(_z_transport_t *zt, _z_string_t *locator, _z_id_t *local_zid) { z_result_t ret = _Z_RES_OK; // Init link _z_link_t zl; @@ -62,20 +62,24 @@ z_result_t _z_new_transport_client(_z_transport_t *zt, _z_string_t *locator, _z_ return ret; } -z_result_t _z_new_transport_peer(_z_transport_t *zt, _z_string_t *locator, _z_id_t *local_zid) { +static z_result_t _z_new_transport_peer(_z_transport_t *zt, _z_string_t *locator, _z_id_t *local_zid, int peer_op) { z_result_t ret = _Z_RES_OK; // Init link _z_link_t zl; memset(&zl, 0, sizeof(_z_link_t)); // Listen link - ret = _z_listen_link(&zl, locator); + if (peer_op == _Z_PEER_OP_OPEN) { + ret = _z_open_link(&zl, locator); + } else { + ret = _z_listen_link(&zl, locator); + } if (ret != _Z_RES_OK) { return ret; } switch (zl._cap._transport) { case Z_LINK_CAP_TRANSPORT_UNICAST: { _z_transport_unicast_establish_param_t tp_param; - ret = _z_unicast_open_peer(&tp_param, &zl, local_zid); + ret = _z_unicast_open_peer(&tp_param, &zl, local_zid, peer_op); if (ret != _Z_RES_OK) { _z_link_clear(&zl); return ret; @@ -101,13 +105,13 @@ z_result_t _z_new_transport_peer(_z_transport_t *zt, _z_string_t *locator, _z_id return ret; } -z_result_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, _z_string_t *locator, z_whatami_t mode) { +z_result_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, _z_string_t *locator, z_whatami_t mode, int peer_op) { z_result_t ret; if (mode == Z_WHATAMI_CLIENT) { ret = _z_new_transport_client(zt, locator, bs); } else { - ret = _z_new_transport_peer(zt, locator, bs); + ret = _z_new_transport_peer(zt, locator, bs, peer_op); } return ret; diff --git a/src/transport/unicast/read.c b/src/transport/unicast/read.c index d6520b6c3..738de4c02 100644 --- a/src/transport/unicast/read.c +++ b/src/transport/unicast/read.c @@ -108,7 +108,9 @@ void *_zp_unicast_read_task(void *ztu_arg) { if (ret == _Z_RES_OK) { _z_t_msg_clear(&t_msg); } else { - _Z_ERROR("Connection closed due to message processing error: %d", ret); + if (ret != _Z_ERR_CONNECTION_CLOSED) { + _Z_ERROR("Connection closed due to message processing error: %d", ret); + } ztu->_read_task_running = false; continue; } diff --git a/src/transport/unicast/transport.c b/src/transport/unicast/transport.c index de01dc01e..99357c1ba 100644 --- a/src/transport/unicast/transport.c +++ b/src/transport/unicast/transport.c @@ -128,107 +128,180 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, return ret; } -z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_id_t *local_zid) { - z_result_t ret = _Z_RES_OK; - - _z_id_t zid = *local_zid; - _z_transport_message_t ism = _z_t_msg_make_init_syn(Z_WHATAMI_CLIENT, zid); +static z_result_t _z_unicast_handshake_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, + const _z_id_t *local_zid, enum z_whatami_t whatami) { + _z_transport_message_t ism = _z_t_msg_make_init_syn(whatami, *local_zid); param->_seq_num_res = ism._body._init._seq_num_res; // The announced sn resolution param->_req_id_res = ism._body._init._req_id_res; // The announced req id resolution param->_batch_size = ism._body._init._batch_size; // The announced batch size // Encode and send the message _Z_DEBUG("Sending Z_INIT(Syn)"); - ret = _z_link_send_t_msg(zl, &ism); + z_result_t ret = _z_link_send_t_msg(zl, &ism); _z_t_msg_clear(&ism); - if (ret == _Z_RES_OK) { - _z_transport_message_t iam; - ret = _z_link_recv_t_msg(&iam, zl); - if (ret == _Z_RES_OK) { - if ((_Z_MID(iam._header) == _Z_MID_T_INIT) && (_Z_HAS_FLAG(iam._header, _Z_FLAG_T_INIT_A) == true)) { - _Z_DEBUG("Received Z_INIT(Ack)"); - - // Any of the size parameters in the InitAck must be less or equal than the one in the InitSyn, - // otherwise the InitAck message is considered invalid and it should be treated as a - // CLOSE message with L==0 by the Initiating Peer -- the recipient of the InitAck message. - if (iam._body._init._seq_num_res <= param->_seq_num_res) { - param->_seq_num_res = iam._body._init._seq_num_res; - } else { - ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; - } - - if (iam._body._init._req_id_res <= param->_req_id_res) { - param->_req_id_res = iam._body._init._req_id_res; - } else { - ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; - } - - if (iam._body._init._batch_size <= param->_batch_size) { - param->_batch_size = iam._body._init._batch_size; - } else { - ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; - } - - if (ret == _Z_RES_OK) { - param->_key_id_res = 0x08 << param->_key_id_res; - param->_req_id_res = 0x08 << param->_req_id_res; - - // The initial SN at TX side - z_random_fill(¶m->_initial_sn_tx, sizeof(param->_initial_sn_tx)); - param->_initial_sn_tx = param->_initial_sn_tx & !_z_sn_modulo_mask(param->_seq_num_res); - - // Initialize the Local and Remote Peer IDs - param->_remote_zid = iam._body._init._zid; - - // Create the OpenSyn message - _z_zint_t lease = Z_TRANSPORT_LEASE; - _z_zint_t initial_sn = param->_initial_sn_tx; - _z_slice_t cookie; - _z_slice_copy(&cookie, &iam._body._init._cookie); - - _z_transport_message_t osm = _z_t_msg_make_open_syn(lease, initial_sn, cookie); - - // Encode and send the message - _Z_DEBUG("Sending Z_OPEN(Syn)"); - ret = _z_link_send_t_msg(zl, &osm); - if (ret == _Z_RES_OK) { - _z_transport_message_t oam; - ret = _z_link_recv_t_msg(&oam, zl); - if (ret == _Z_RES_OK) { - if ((_Z_MID(oam._header) == _Z_MID_T_OPEN) && - (_Z_HAS_FLAG(oam._header, _Z_FLAG_T_OPEN_A) == true)) { - _Z_DEBUG("Received Z_OPEN(Ack)"); - param->_lease = oam._body._open._lease; // The session lease - - // The initial SN at RX side. Initialize the session as we had already received - // a message with a SN equal to initial_sn - 1. - param->_initial_sn_rx = oam._body._open._initial_sn; - } else { - ret = _Z_ERR_MESSAGE_UNEXPECTED; - } - _z_t_msg_clear(&oam); - } - } - _z_t_msg_clear(&osm); - } - } else { - ret = _Z_ERR_MESSAGE_UNEXPECTED; - } - _z_t_msg_clear(&iam); - } + if (ret != _Z_RES_OK) { + return ret; + } + // Try to receive response + _z_transport_message_t iam; + _Z_RETURN_IF_ERR(_z_link_recv_t_msg(&iam, zl)); + if ((_Z_MID(iam._header) != _Z_MID_T_INIT) || !_Z_HAS_FLAG(iam._header, _Z_FLAG_T_INIT_A)) { + _z_t_msg_clear(&iam); + return _Z_ERR_MESSAGE_UNEXPECTED; + } + _Z_DEBUG("Received Z_INIT(Ack)"); + // Any of the size parameters in the InitAck must be less or equal than the one in the InitSyn, + // otherwise the InitAck message is considered invalid and it should be treated as a + // CLOSE message with L==0 by the Initiating Peer -- the recipient of the InitAck message. + if (iam._body._init._seq_num_res <= param->_seq_num_res) { + param->_seq_num_res = iam._body._init._seq_num_res; + } else { + ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; + } + if (iam._body._init._req_id_res <= param->_req_id_res) { + param->_req_id_res = iam._body._init._req_id_res; + } else { + ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; } + if (iam._body._init._batch_size <= param->_batch_size) { + param->_batch_size = iam._body._init._batch_size; + } else { + ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; + } + if (ret != _Z_RES_OK) { + _z_t_msg_clear(&iam); + return ret; + } + param->_key_id_res = 0x08 << param->_key_id_res; + param->_req_id_res = 0x08 << param->_req_id_res; + + // The initial SN at TX side + z_random_fill(¶m->_initial_sn_tx, sizeof(param->_initial_sn_tx)); + param->_initial_sn_tx = param->_initial_sn_tx & !_z_sn_modulo_mask(param->_seq_num_res); + + // Initialize the Local and Remote Peer IDs + param->_remote_zid = iam._body._init._zid; + + // Create the OpenSyn message + _z_zint_t lease = Z_TRANSPORT_LEASE; + _z_zint_t initial_sn = param->_initial_sn_tx; + _z_slice_t cookie; + _z_slice_copy(&cookie, &iam._body._init._cookie); + _z_transport_message_t osm = _z_t_msg_make_open_syn(lease, initial_sn, cookie); + _z_t_msg_clear(&iam); + // Encode and send the message + _Z_DEBUG("Sending Z_OPEN(Syn)"); + ret = _z_link_send_t_msg(zl, &osm); + _z_t_msg_clear(&osm); + if (ret != _Z_RES_OK) { + return ret; + } + // Try to receive response + _z_transport_message_t oam; + _Z_RETURN_IF_ERR(_z_link_recv_t_msg(&oam, zl)); + if ((_Z_MID(oam._header) != _Z_MID_T_OPEN) || !_Z_HAS_FLAG(oam._header, _Z_FLAG_T_OPEN_A)) { + _z_t_msg_clear(&oam); + ret = _Z_ERR_MESSAGE_UNEXPECTED; + } + _Z_DEBUG("Received Z_OPEN(Ack)"); + param->_lease = oam._body._open._lease; // The session lease + // The initial SN at RX side. Initialize the session as we had already received + // a message with a SN equal to initial_sn - 1. + param->_initial_sn_rx = oam._body._open._initial_sn; + _z_t_msg_clear(&oam); + return _Z_RES_OK; +} - return ret; +static z_result_t _z_unicast_handshake_listener(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, + const _z_id_t *local_zid, enum z_whatami_t whatami) { + // Read t message from link + _z_transport_message_t tmsg; + z_result_t ret = _z_link_recv_t_msg(&tmsg, zl); + if (ret != _Z_RES_OK) { + return ret; + } + // Receive InitSyn + if (_Z_MID(tmsg._header) != _Z_MID_T_INIT || _Z_HAS_FLAG(tmsg._header, _Z_FLAG_T_INIT_A)) { + _z_t_msg_clear(&tmsg); + return _Z_ERR_MESSAGE_UNEXPECTED; + } + _Z_DEBUG("Received Z_INIT(Syn)"); + // Encode InitAck + _z_slice_t cookie = _z_slice_empty(); + _z_transport_message_t iam = _z_t_msg_make_init_ack(whatami, *local_zid, cookie); + // Any of the size parameters in the InitAck must be less or equal than the one in the InitSyn, + if (iam._body._init._seq_num_res > tmsg._body._init._seq_num_res) { + iam._body._init._seq_num_res = tmsg._body._init._seq_num_res; + } + if (iam._body._init._req_id_res > tmsg._body._init._req_id_res) { + iam._body._init._req_id_res = tmsg._body._init._req_id_res; + } + if (iam._body._init._batch_size > tmsg._body._init._batch_size) { + iam._body._init._batch_size = tmsg._body._init._batch_size; + } + param->_remote_zid = tmsg._body._init._zid; + param->_seq_num_res = iam._body._init._seq_num_res; + param->_req_id_res = iam._body._init._req_id_res; + param->_batch_size = iam._body._init._batch_size; + param->_key_id_res = 0x08 << param->_key_id_res; + param->_req_id_res = 0x08 << param->_req_id_res; + _z_t_msg_clear(&tmsg); + // Send InitAck + _Z_DEBUG("Sending Z_INIT(Ack)"); + ret = _z_link_send_t_msg(zl, &iam); + _z_t_msg_clear(&iam); + if (ret != _Z_RES_OK) { + return ret; + } + // Read t message from link + ret = _z_link_recv_t_msg(&tmsg, zl); + if (ret != _Z_RES_OK) { + return ret; + } + // Receive OpenSyn + if (_Z_MID(tmsg._header) != _Z_MID_T_OPEN || _Z_HAS_FLAG(tmsg._header, _Z_FLAG_T_INIT_A)) { + _z_t_msg_clear(&tmsg); + return _Z_ERR_MESSAGE_UNEXPECTED; + } + _Z_DEBUG("Received Z_OPEN(Syn)"); + // Process message + param->_lease = tmsg._body._open._lease; + param->_initial_sn_rx = tmsg._body._open._initial_sn; + _z_t_msg_clear(&tmsg); + + // Init sn, tx side + z_random_fill(¶m->_initial_sn_tx, sizeof(param->_initial_sn_tx)); + param->_initial_sn_tx = param->_initial_sn_tx & !_z_sn_modulo_mask(param->_seq_num_res); + + // Encode OpenAck + _z_zint_t lease = Z_TRANSPORT_LEASE; + _z_zint_t initial_sn = param->_initial_sn_tx; + _z_transport_message_t oam = _z_t_msg_make_open_ack(lease, initial_sn); + + // Encode and send the message + _Z_DEBUG("Sending Z_OPEN(Ack)"); + ret = _z_link_send_t_msg(zl, &oam); + _z_t_msg_clear(&oam); + if (ret != _Z_RES_OK) { + return ret; + } + // Handshake finished + return _Z_RES_OK; +} + +z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, + const _z_id_t *local_zid) { + return _z_unicast_handshake_client(param, zl, local_zid, Z_WHATAMI_CLIENT); } z_result_t _z_unicast_open_peer(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_id_t *local_zid) { - _ZP_UNUSED(param); - _ZP_UNUSED(zl); - _ZP_UNUSED(local_zid); - z_result_t ret = _Z_ERR_CONFIG_UNSUPPORTED_PEER_UNICAST; - // @TODO: not implemented + const _z_id_t *local_zid, int peer_op) { + z_result_t ret = _Z_RES_OK; + if (peer_op == _Z_PEER_OP_OPEN) { + ret = _z_unicast_handshake_client(param, zl, local_zid, Z_WHATAMI_PEER); + } else { + ret = _z_unicast_handshake_listener(param, zl, local_zid, Z_WHATAMI_PEER); + } return ret; } @@ -299,10 +372,11 @@ z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, } z_result_t _z_unicast_open_peer(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_id_t *local_zid) { + const _z_id_t *local_zid, int peer_op) { _ZP_UNUSED(param); _ZP_UNUSED(zl); _ZP_UNUSED(local_zid); + _ZP_UNUSED(peer_op); return _Z_ERR_TRANSPORT_NOT_AVAILABLE; } diff --git a/tests/z_peer_multicast_test.c b/tests/z_peer_multicast_test.c index 9cbd017b5..1319083ba 100644 --- a/tests/z_peer_multicast_test.c +++ b/tests/z_peer_multicast_test.c @@ -90,7 +90,7 @@ int main(int argc, char **argv) { z_config_default(&config); zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, "peer"); - zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[1]); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, argv[1]); z_owned_session_t s2; assert(z_open(&s2, z_move(config), NULL) == Z_OK); From 7388049ad2c2f40625ce1ac688b029897a9ff8f1 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Mon, 28 Oct 2024 14:41:52 +0100 Subject: [PATCH 09/17] Batching v2 (#765) * feat: switch id empty/check to static inline * feat: use batch count instead of batch vec * refactor: batch don't copy messages * feat: rename batch api * feat: group common transport fields * feat: use common struct in tx functions * feat: rename multicast tx functions * fix: unreachable * refactor: fuse unicast and multicast tx --- include/zenoh-pico/api/primitives.h | 6 +- include/zenoh-pico/protocol/core.h | 5 +- include/zenoh-pico/session/utils.h | 3 - include/zenoh-pico/transport/common/tx.h | 4 + .../transport/multicast/transport.h | 21 -- include/zenoh-pico/transport/multicast/tx.h | 26 -- include/zenoh-pico/transport/raweth/tx.h | 2 +- include/zenoh-pico/transport/transport.h | 141 ++++----- .../zenoh-pico/transport/unicast/transport.h | 25 +- include/zenoh-pico/transport/unicast/tx.h | 26 -- src/api/api.c | 6 +- src/net/primitives.c | 1 + src/net/query.c | 1 + src/protocol/core.c | 29 +- src/session/interest.c | 1 + src/session/rx.c | 1 + src/session/tx.c | 61 ---- src/session/utils.c | 6 +- src/transport/common/tx.c | 281 ++++++++++++++++- src/transport/multicast.c | 1 - src/transport/multicast/lease.c | 35 +-- src/transport/multicast/read.c | 51 ++-- src/transport/multicast/rx.c | 49 +-- src/transport/multicast/transport.c | 80 +++-- src/transport/multicast/tx.c | 287 ----------------- src/transport/raweth/read.c | 16 +- src/transport/raweth/rx.c | 26 +- src/transport/raweth/tx.c | 80 ++--- src/transport/transport.c | 19 +- src/transport/unicast.c | 1 - src/transport/unicast/lease.c | 32 +- src/transport/unicast/read.c | 53 ++-- src/transport/unicast/rx.c | 53 ++-- src/transport/unicast/transport.c | 76 +++-- src/transport/unicast/tx.c | 289 ------------------ 35 files changed, 645 insertions(+), 1149 deletions(-) delete mode 100644 include/zenoh-pico/transport/multicast/tx.h delete mode 100644 include/zenoh-pico/transport/unicast/tx.h delete mode 100644 src/session/tx.c delete mode 100644 src/transport/multicast/tx.c delete mode 100644 src/transport/unicast/tx.c diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index 07c1e4e35..a944149c6 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -2060,7 +2060,7 @@ const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *subs /** * Activate the batching mechanism. * Any message that would have been sent on the network by a subsequent api call (e.g z_put, z_get) - * will be instead stored until the batch is flushed with :c:func:`zp_batch_flush`. + * will be instead stored until the batch is full or batching is stopped with :c:func:`zp_batch_stop`. * * Parameters: * zs: Pointer to a :c:type:`z_loaned_session_t` that will start batching messages. @@ -2071,7 +2071,7 @@ const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *subs z_result_t zp_batch_start(const z_loaned_session_t *zs); /** - * Deactivate the batching mechanism and flush the messages that were stored. + * Deactivate the batching mechanism and flush the remaining messages. * * Parameters: * zs: Pointer to a :c:type:`z_loaned_session_t` that will stop batching messages. @@ -2079,7 +2079,7 @@ z_result_t zp_batch_start(const z_loaned_session_t *zs); * Return: * ``0`` if batching stopped and batch successfully sent, ``negative value`` otherwise. */ -z_result_t zp_batch_flush(const z_loaned_session_t *zs); +z_result_t zp_batch_stop(const z_loaned_session_t *zs); #endif /************* Multi Thread Tasks helpers **************/ diff --git a/include/zenoh-pico/protocol/core.h b/include/zenoh-pico/protocol/core.h index 34970275f..366659e39 100644 --- a/include/zenoh-pico/protocol/core.h +++ b/include/zenoh-pico/protocol/core.h @@ -54,9 +54,10 @@ typedef size_t _z_zint_t; typedef struct { uint8_t id[16]; } _z_id_t; +extern const _z_id_t empty_id; uint8_t _z_id_len(_z_id_t id); -bool _z_id_check(_z_id_t id); -_z_id_t _z_id_empty(void); +static inline bool _z_id_check(_z_id_t id) { return memcmp(&id, &empty_id, sizeof(id)) != 0; } +static inline _z_id_t _z_id_empty(void) { return (_z_id_t){0}; } /** * A zenoh timestamp. diff --git a/include/zenoh-pico/session/utils.h b/include/zenoh-pico/session/utils.h index 2e3a47987..6d8c381b2 100644 --- a/include/zenoh-pico/session/utils.h +++ b/include/zenoh-pico/session/utils.h @@ -31,9 +31,6 @@ void _z_session_clear(_z_session_t *zn); z_result_t _z_session_close(_z_session_t *zn, uint8_t reason); z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t *z_msg, uint16_t local_peer_id); -z_result_t _z_send_n_msg(_z_session_t *zn, _z_network_message_t *n_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl); -z_result_t _z_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl); #if Z_FEATURE_MULTI_THREAD == 1 static inline void _z_session_mutex_lock(_z_session_t *zn) { (void)_z_mutex_lock(&zn->_mutex_inner); } diff --git a/include/zenoh-pico/transport/common/tx.h b/include/zenoh-pico/transport/common/tx.h index 1eb4abac1..5a7b78b4d 100644 --- a/include/zenoh-pico/transport/common/tx.h +++ b/include/zenoh-pico/transport/common/tx.h @@ -26,7 +26,11 @@ void __unsafe_z_finalize_wbuf(_z_wbuf_t *buf, uint8_t link_flow_capability); z_result_t __unsafe_z_serialize_zenoh_fragment(_z_wbuf_t *dst, _z_wbuf_t *src, z_reliability_t reliability, size_t sn); /*------------------ Transmission and Reception helpers ------------------*/ +z_result_t _z_transport_tx_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg); z_result_t _z_send_t_msg(_z_transport_t *zt, const _z_transport_message_t *t_msg); z_result_t _z_link_send_t_msg(const _z_link_t *zl, const _z_transport_message_t *t_msg); +z_result_t _z_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, + z_congestion_control_t cong_ctrl); +z_result_t _z_send_n_batch(_z_session_t *zn, z_congestion_control_t cong_ctrl); #endif /* ZENOH_PICO_TRANSPORT_TX_H */ diff --git a/include/zenoh-pico/transport/multicast/transport.h b/include/zenoh-pico/transport/multicast/transport.h index 802393e53..4947ac894 100644 --- a/include/zenoh-pico/transport/multicast/transport.h +++ b/include/zenoh-pico/transport/multicast/transport.h @@ -28,31 +28,10 @@ z_result_t _z_multicast_transport_close(_z_transport_multicast_t *ztm, uint8_t r void _z_multicast_transport_clear(_z_transport_t *zt); #if (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) && Z_FEATURE_MULTI_THREAD == 1 -static inline z_result_t _z_multicast_tx_mutex_lock(_z_transport_multicast_t *ztm, bool block) { - if (block) { - _z_mutex_lock(&ztm->_mutex_tx); - return _Z_RES_OK; - } else { - return _z_mutex_try_lock(&ztm->_mutex_tx); - } -} -static inline void _z_multicast_tx_mutex_unlock(_z_transport_multicast_t *ztm) { _z_mutex_unlock(&ztm->_mutex_tx); } -static inline void _z_multicast_rx_mutex_lock(_z_transport_multicast_t *ztm) { _z_mutex_lock(&ztm->_mutex_rx); } -static inline void _z_multicast_rx_mutex_unlock(_z_transport_multicast_t *ztm) { _z_mutex_unlock(&ztm->_mutex_rx); } static inline void _z_multicast_peer_mutex_lock(_z_transport_multicast_t *ztm) { _z_mutex_lock(&ztm->_mutex_peer); } static inline void _z_multicast_peer_mutex_unlock(_z_transport_multicast_t *ztm) { _z_mutex_unlock(&ztm->_mutex_peer); } - #else -static inline z_result_t _z_multicast_tx_mutex_lock(_z_transport_multicast_t *ztm, bool block) { - _ZP_UNUSED(ztm); - _ZP_UNUSED(block); - return _Z_RES_OK; -} -static inline void _z_multicast_tx_mutex_unlock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } -static inline void _z_multicast_rx_mutex_lock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } -static inline void _z_multicast_rx_mutex_unlock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } static inline void _z_multicast_peer_mutex_lock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } static inline void _z_multicast_peer_mutex_unlock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } - #endif // (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) && Z_FEATURE_MULTI_THREAD == 1 #endif /* ZENOH_PICO_MULTICAST_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/multicast/tx.h b/include/zenoh-pico/transport/multicast/tx.h deleted file mode 100644 index 836b441b6..000000000 --- a/include/zenoh-pico/transport/multicast/tx.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#ifndef ZENOH_PICO_MULTICAST_TX_H -#define ZENOH_PICO_MULTICAST_TX_H - -#include "zenoh-pico/net/session.h" -#include "zenoh-pico/transport/transport.h" - -z_result_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl); -z_result_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg); -z_result_t _z_multicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl); - -#endif /* ZENOH_PICO_MULTICAST_TX_H */ diff --git a/include/zenoh-pico/transport/raweth/tx.h b/include/zenoh-pico/transport/raweth/tx.h index 83abdd9fb..9b18d2004 100644 --- a/include/zenoh-pico/transport/raweth/tx.h +++ b/include/zenoh-pico/transport/raweth/tx.h @@ -21,6 +21,6 @@ z_result_t _z_raweth_link_send_t_msg(const _z_link_t *zl, const _z_transport_message_t *t_msg); z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl); -z_result_t _z_raweth_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg); +z_result_t _z_raweth_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg); #endif /* ZENOH_PICO_RAWETH_TX_H */ diff --git a/include/zenoh-pico/transport/transport.h b/include/zenoh-pico/transport/transport.h index 1efc9ccd0..e6c97e5d3 100644 --- a/include/zenoh-pico/transport/transport.h +++ b/include/zenoh-pico/transport/transport.h @@ -37,25 +37,23 @@ enum _z_batching_state_e { }; typedef struct { -#if Z_FEATURE_FRAGMENTATION == 1 - // Defragmentation buffers - uint8_t _state_reliable; - uint8_t _state_best_effort; - _z_wbuf_t _dbuf_reliable; - _z_wbuf_t _dbuf_best_effort; -#endif - _z_id_t _remote_zid; _z_slice_t _remote_addr; _z_conduit_sn_list_t _sn_rx_sns; - // SN numbers _z_zint_t _sn_res; volatile _z_zint_t _lease; volatile _z_zint_t _next_lease; - uint16_t _peer_id; volatile bool _received; + +#if Z_FEATURE_FRAGMENTATION == 1 + // Defragmentation buffers + uint8_t _state_reliable; + uint8_t _state_best_effort; + _z_wbuf_t _dbuf_reliable; + _z_wbuf_t _dbuf_best_effort; +#endif } _z_transport_peer_entry_t; size_t _z_transport_peer_entry_size(const _z_transport_peer_entry_t *src); @@ -71,107 +69,64 @@ _z_transport_peer_entry_list_t *_z_transport_peer_entry_list_insert(_z_transport // Forward type declaration to avoid cyclical include typedef struct _z_session_rc_t _z_session_rc_ref_t; -// Forward declaration to be used in _zp_f_send_tmsg* -typedef struct _z_transport_multicast_t _z_transport_multicast_t; -// Send function prototype -typedef z_result_t (*_zp_f_send_tmsg)(_z_transport_multicast_t *self, const _z_transport_message_t *t_msg); - typedef struct { - // Session associated to the transport _z_session_rc_ref_t *_session; - -#if Z_FEATURE_MULTI_THREAD == 1 - // TX and RX mutexes - _z_mutex_t _mutex_rx; - _z_mutex_t _mutex_tx; -#endif // Z_FEATURE_MULTI_THREAD == 1 - _z_link_t _link; - -#if Z_FEATURE_FRAGMENTATION == 1 - // Defragmentation buffer - uint8_t _state_reliable; - uint8_t _state_best_effort; - _z_wbuf_t _dbuf_reliable; - _z_wbuf_t _dbuf_best_effort; -#endif - - // Regular Buffers + // TX and RX buffers _z_wbuf_t _wbuf; _z_zbuf_t _zbuf; - - _z_id_t _remote_zid; - // SN numbers _z_zint_t _sn_res; _z_zint_t _sn_tx_reliable; _z_zint_t _sn_tx_best_effort; - _z_zint_t _sn_rx_reliable; - _z_zint_t _sn_rx_best_effort; volatile _z_zint_t _lease; - -// Transport batching -#if Z_FEATURE_BATCHING == 1 - uint8_t _batch_state; - _z_network_message_vec_t _batch; -#endif - -#if Z_FEATURE_MULTI_THREAD == 1 - _z_task_t *_read_task; - _z_task_t *_lease_task; - volatile bool _read_task_running; - volatile bool _lease_task_running; -#endif // Z_FEATURE_MULTI_THREAD == 1 - - volatile bool _received; volatile bool _transmitted; -} _z_transport_unicast_t; - -typedef struct _z_transport_multicast_t { - // Session associated to the transport - _z_session_rc_ref_t *_session; - #if Z_FEATURE_MULTI_THREAD == 1 // TX and RX mutexes _z_mutex_t _mutex_rx; _z_mutex_t _mutex_tx; - // Peer list mutex - _z_mutex_t _mutex_peer; -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _z_task_t *_read_task; + _z_task_t *_lease_task; + volatile bool _read_task_running; + volatile bool _lease_task_running; +#endif // Transport batching #if Z_FEATURE_BATCHING == 1 uint8_t _batch_state; - _z_network_message_vec_t _batch; + size_t _batch_count; #endif +} _z_transport_common_t; - _z_link_t _link; +// Send function prototype +typedef z_result_t (*_zp_f_send_tmsg)(_z_transport_common_t *self, const _z_transport_message_t *t_msg); - // TX and RX buffers - _z_wbuf_t _wbuf; - _z_zbuf_t _zbuf; +typedef struct { + _z_transport_common_t _common; + _z_id_t _remote_zid; + _z_zint_t _sn_rx_reliable; + _z_zint_t _sn_rx_best_effort; + volatile bool _received; - // SN initial numbers - _z_zint_t _sn_res; - _z_zint_t _sn_tx_reliable; - _z_zint_t _sn_tx_best_effort; - volatile _z_zint_t _lease; +#if Z_FEATURE_FRAGMENTATION == 1 + // Defragmentation buffer + uint8_t _state_reliable; + uint8_t _state_best_effort; + _z_wbuf_t _dbuf_reliable; + _z_wbuf_t _dbuf_best_effort; +#endif +} _z_transport_unicast_t; +typedef struct _z_transport_multicast_t { + _z_transport_common_t _common; // Known valid peers _z_transport_peer_entry_list_t *_peers; - // T message send function _zp_f_send_tmsg _send_f; #if Z_FEATURE_MULTI_THREAD == 1 - _z_task_t *_read_task; - _z_task_t *_lease_task; - volatile bool _read_task_running; - volatile bool _lease_task_running; -#endif // Z_FEATURE_MULTI_THREAD == 1 - - volatile bool _transmitted; + _z_mutex_t _mutex_peer; // Peer list mutex +#endif } _z_transport_multicast_t; typedef struct { @@ -214,4 +169,26 @@ bool _z_transport_start_batching(_z_transport_t *zt); void _z_transport_stop_batching(_z_transport_t *zt); #endif -#endif /* INCLUDE_ZENOH_PICO_TRANSPORT_TRANSPORT_H */ +#if Z_FEATURE_MULTI_THREAD == 1 +static inline z_result_t _z_transport_tx_mutex_lock(_z_transport_common_t *ztc, bool block) { + if (block) { + _z_mutex_lock(&ztc->_mutex_tx); + return _Z_RES_OK; + } else { + return _z_mutex_try_lock(&ztc->_mutex_tx); + } +} +static inline void _z_transport_tx_mutex_unlock(_z_transport_common_t *ztc) { _z_mutex_unlock(&ztc->_mutex_tx); } +static inline void _z_transport_rx_mutex_lock(_z_transport_common_t *ztc) { _z_mutex_lock(&ztc->_mutex_rx); } +static inline void _z_transport_rx_mutex_unlock(_z_transport_common_t *ztc) { _z_mutex_unlock(&ztc->_mutex_rx); } +#else +static inline z_result_t _z_transport_tx_mutex_lock(_z_transport_common_t *ztc, bool block) { + _ZP_UNUSED(ztc); + _ZP_UNUSED(block); + return _Z_RES_OK; +} +static inline void _z_transport_tx_mutex_unlock(_z_transport_common_t *ztc) { _ZP_UNUSED(ztc); } +static inline void _z_transport_rx_mutex_lock(_z_transport_common_t *ztc) { _ZP_UNUSED(ztc); } +static inline void _z_transport_rx_mutex_unlock(_z_transport_common_t *ztc) { _ZP_UNUSED(ztc); } +#endif // Z_FEATURE_MULTI_THREAD == 1 +#endif /* INCLUDE_ZENOH_PICO_TRANSPORT_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/unicast/transport.h b/include/zenoh-pico/transport/unicast/transport.h index d6eeb1599..b2ab36425 100644 --- a/include/zenoh-pico/transport/unicast/transport.h +++ b/include/zenoh-pico/transport/unicast/transport.h @@ -27,27 +27,4 @@ z_result_t _z_unicast_send_close(_z_transport_unicast_t *ztu, uint8_t reason, bo z_result_t _z_unicast_transport_close(_z_transport_unicast_t *ztu, uint8_t reason); void _z_unicast_transport_clear(_z_transport_t *zt); -#if Z_FEATURE_UNICAST_TRANSPORT == 1 && Z_FEATURE_MULTI_THREAD == 1 -static inline z_result_t _z_unicast_tx_mutex_lock(_z_transport_unicast_t *ztu, bool block) { - if (block) { - _z_mutex_lock(&ztu->_mutex_tx); - return _Z_RES_OK; - } else { - return _z_mutex_try_lock(&ztu->_mutex_tx); - } -} -static inline void _z_unicast_tx_mutex_unlock(_z_transport_unicast_t *ztu) { _z_mutex_unlock(&ztu->_mutex_tx); } -static inline void _z_unicast_rx_mutex_lock(_z_transport_unicast_t *ztu) { _z_mutex_lock(&ztu->_mutex_rx); } -static inline void _z_unicast_rx_mutex_unlock(_z_transport_unicast_t *ztu) { _z_mutex_unlock(&ztu->_mutex_rx); } - -#else -static inline z_result_t _z_unicast_tx_mutex_lock(_z_transport_unicast_t *ztu, bool block) { - _ZP_UNUSED(ztu); - _ZP_UNUSED(block); - return _Z_RES_OK; -} -static inline void _z_unicast_tx_mutex_unlock(_z_transport_unicast_t *ztu) { _ZP_UNUSED(ztu); } -static inline void _z_unicast_rx_mutex_lock(_z_transport_unicast_t *ztu) { _ZP_UNUSED(ztu); } -static inline void _z_unicast_rx_mutex_unlock(_z_transport_unicast_t *ztu) { _ZP_UNUSED(ztu); } -#endif // Z_FEATURE_UNICAST_TRANSPORT == 1 && Z_FEATURE_MULTI_THREAD == 1 -#endif /* ZENOH_PICO_UNICAST_TRANSPORT_H */ +#endif /* ZENOH_PICO_UNICAST_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/unicast/tx.h b/include/zenoh-pico/transport/unicast/tx.h deleted file mode 100644 index 41c991596..000000000 --- a/include/zenoh-pico/transport/unicast/tx.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#ifndef ZENOH_PICO_UNICAST_TX_H -#define ZENOH_PICO_UNICAST_TX_H - -#include "zenoh-pico/net/session.h" -#include "zenoh-pico/transport/transport.h" - -z_result_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl); -z_result_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_message_t *t_msg); -z_result_t _z_unicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl); - -#endif /* ZENOH_PICO_TRANSPORT_LINK_TX_H */ diff --git a/src/api/api.c b/src/api/api.c index a2ed97a53..2056d956c 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -39,6 +39,7 @@ #include "zenoh-pico/session/utils.h" #include "zenoh-pico/system/platform.h" #include "zenoh-pico/system/platform_common.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/transport/multicast.h" #include "zenoh-pico/transport/unicast.h" #include "zenoh-pico/utils/endianness.h" @@ -1440,13 +1441,14 @@ z_result_t zp_batch_start(const z_loaned_session_t *zs) { return _z_transport_start_batching(&session->_tp) ? _Z_RES_OK : _Z_ERR_GENERIC; } -z_result_t zp_batch_flush(const z_loaned_session_t *zs) { +z_result_t zp_batch_stop(const z_loaned_session_t *zs) { _z_session_t *session = _Z_RC_IN_VAL(zs); if (_Z_RC_IS_NULL(zs)) { return _Z_ERR_SESSION_CLOSED; } _z_transport_stop_batching(&session->_tp); - return _z_send_n_batch(session, Z_RELIABILITY_DEFAULT, Z_CONGESTION_CONTROL_DEFAULT); + // Send remaining batch + return _z_send_n_batch(session, Z_CONGESTION_CONTROL_DEFAULT); } #endif diff --git a/src/net/primitives.c b/src/net/primitives.c index c2232d6b4..4e235d0d4 100644 --- a/src/net/primitives.c +++ b/src/net/primitives.c @@ -33,6 +33,7 @@ #include "zenoh-pico/session/resource.h" #include "zenoh-pico/session/subscription.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/result.h" diff --git a/src/net/query.c b/src/net/query.c index 9230c1dde..a4b41b6aa 100644 --- a/src/net/query.c +++ b/src/net/query.c @@ -14,6 +14,7 @@ #include "zenoh-pico/net/query.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/utils/logging.h" void _z_query_clear_inner(_z_query_t *q) { diff --git a/src/protocol/core.c b/src/protocol/core.c index de0dbf517..4dda7b57c 100644 --- a/src/protocol/core.c +++ b/src/protocol/core.c @@ -27,6 +27,8 @@ #define _Z_ID_LEN (16) +const _z_id_t empty_id = {0}; + uint8_t _z_id_len(_z_id_t id) { uint8_t len = _Z_ID_LEN; while (len > 0) { @@ -38,33 +40,6 @@ uint8_t _z_id_len(_z_id_t id) { } return len; } -bool _z_id_check(_z_id_t id) { - bool ret = false; - for (int i = 0; !ret && i < _Z_ID_LEN; i++) { - ret |= id.id[i] != 0; - } - return ret; -} -_z_id_t _z_id_empty(void) { - return (_z_id_t){.id = { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - }}; -} uint64_t _z_timestamp_ntp64_from_time(uint32_t seconds, uint32_t nanos) { const uint64_t FRAC_PER_SEC = (uint64_t)1 << 32; diff --git a/src/session/interest.c b/src/session/interest.c index 033942773..6bcdbed4c 100644 --- a/src/session/interest.c +++ b/src/session/interest.c @@ -26,6 +26,7 @@ #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/resource.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_INTEREST == 1 diff --git a/src/session/rx.c b/src/session/rx.c index 800f795e3..54dc8983f 100644 --- a/src/session/rx.c +++ b/src/session/rx.c @@ -32,6 +32,7 @@ #include "zenoh-pico/session/session.h" #include "zenoh-pico/session/subscription.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/utils/logging.h" /*------------------ Handle message ------------------*/ diff --git a/src/session/tx.c b/src/session/tx.c deleted file mode 100644 index 6401fb623..000000000 --- a/src/session/tx.c +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#include "zenoh-pico/transport/multicast/tx.h" - -#include "zenoh-pico/transport/raweth/tx.h" -#include "zenoh-pico/transport/unicast/tx.h" -#include "zenoh-pico/utils/logging.h" - -z_result_t _z_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl) { - z_result_t ret = _Z_RES_OK; - // Call transport function - switch (zn->_tp._type) { - case _Z_TRANSPORT_UNICAST_TYPE: - ret = _z_unicast_send_n_msg(zn, z_msg, reliability, cong_ctrl); - break; - case _Z_TRANSPORT_MULTICAST_TYPE: - ret = _z_multicast_send_n_msg(zn, z_msg, reliability, cong_ctrl); - break; - case _Z_TRANSPORT_RAWETH_TYPE: - ret = _z_raweth_send_n_msg(zn, z_msg, reliability, cong_ctrl); - break; - default: - ret = _Z_ERR_TRANSPORT_NOT_AVAILABLE; - break; - } - return ret; -} - -z_result_t _z_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { - z_result_t ret = _Z_RES_OK; - // Call transport function - switch (zn->_tp._type) { - case _Z_TRANSPORT_UNICAST_TYPE: - ret = _z_unicast_send_n_batch(zn, reliability, cong_ctrl); - break; - case _Z_TRANSPORT_MULTICAST_TYPE: - ret = _z_multicast_send_n_batch(zn, reliability, cong_ctrl); - break; - case _Z_TRANSPORT_RAWETH_TYPE: - _Z_INFO("Batching not yet supported on raweth transport"); - ret = _Z_ERR_TRANSPORT_TX_FAILED; - break; - default: - ret = _Z_ERR_TRANSPORT_NOT_AVAILABLE; - break; - } - return ret; -} diff --git a/src/session/utils.c b/src/session/utils.c index f88fcf03d..0a2cff984 100644 --- a/src/session/utils.c +++ b/src/session/utils.c @@ -80,13 +80,13 @@ z_result_t _z_session_init(_z_session_rc_t *zsrc, _z_id_t *zid) { // Note session in transport switch (zn->_tp._type) { case _Z_TRANSPORT_UNICAST_TYPE: - zn->_tp._transport._unicast._session = zsrc; + zn->_tp._transport._unicast._common._session = zsrc; break; case _Z_TRANSPORT_MULTICAST_TYPE: - zn->_tp._transport._multicast._session = zsrc; + zn->_tp._transport._multicast._common._session = zsrc; break; case _Z_TRANSPORT_RAWETH_TYPE: - zn->_tp._transport._raweth._session = zsrc; + zn->_tp._transport._raweth._common._session = zsrc; break; default: break; diff --git a/src/transport/common/tx.c b/src/transport/common/tx.c index 75a837cbe..4b6d9bf32 100644 --- a/src/transport/common/tx.c +++ b/src/transport/common/tx.c @@ -16,15 +16,244 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/protocol/codec/core.h" +#include "zenoh-pico/protocol/codec/network.h" #include "zenoh-pico/protocol/codec/transport.h" #include "zenoh-pico/protocol/definitions/transport.h" -#include "zenoh-pico/transport/multicast/tx.h" #include "zenoh-pico/transport/raweth/tx.h" -#include "zenoh-pico/transport/unicast/tx.h" +#include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/endianness.h" #include "zenoh-pico/utils/logging.h" /*------------------ Transmission helper ------------------*/ + +static _z_zint_t _z_transport_tx_get_sn(_z_transport_common_t *ztc, z_reliability_t reliability) { + _z_zint_t sn; + if (reliability == Z_RELIABILITY_RELIABLE) { + sn = ztc->_sn_tx_reliable; + ztc->_sn_tx_reliable = _z_sn_increment(ztc->_sn_res, ztc->_sn_tx_reliable); + } else { + sn = ztc->_sn_tx_best_effort; + ztc->_sn_tx_best_effort = _z_sn_increment(ztc->_sn_res, ztc->_sn_tx_best_effort); + } + return sn; +} + +#if Z_FEATURE_FRAGMENTATION == 1 +static z_result_t _z_transport_tx_send_fragment_inner(_z_transport_common_t *ztc, _z_wbuf_t *frag_buff, + const _z_network_message_t *n_msg, z_reliability_t reliability, + _z_zint_t first_sn) { + bool is_first = true; + _z_zint_t sn = first_sn; + // Encode message on temp buffer + _Z_RETURN_IF_ERR(_z_network_message_encode(frag_buff, n_msg)); + // Fragment message + while (_z_wbuf_len(frag_buff) > 0) { + // Get fragment sequence number + if (!is_first) { + sn = _z_transport_tx_get_sn(ztc, reliability); + } + is_first = false; + // Serialize fragment + __unsafe_z_prepare_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + z_result_t ret = __unsafe_z_serialize_zenoh_fragment(&ztc->_wbuf, frag_buff, reliability, sn); + if (ret != _Z_RES_OK) { + _Z_ERROR("Fragment serialization failed with err %d", ret); + return ret; + } + // Send fragment + __unsafe_z_finalize_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztc->_link, &ztc->_wbuf)); + ztc->_transmitted = true; // Tell session we transmitted data + } + return _Z_RES_OK; +} + +static z_result_t _z_transport_tx_send_fragment(_z_transport_common_t *ztc, const _z_network_message_t *n_msg, + z_reliability_t reliability, _z_zint_t first_sn) { + // Create an expandable wbuf for fragmentation + _z_wbuf_t frag_buff = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); + // Send message as fragments + z_result_t ret = _z_transport_tx_send_fragment_inner(ztc, &frag_buff, n_msg, reliability, first_sn); + // Clear the buffer as it's no longer required + _z_wbuf_clear(&frag_buff); + return ret; +} + +#else +static z_result_t _z_transport_tx_send_fragment(_z_transport_common_t *ztc, const _z_network_message_t *n_msg, + z_reliability_t reliability, _z_zint_t first_sn) { + _ZP_UNUSED(ztc); + _ZP_UNUSED(fbf); + _ZP_UNUSED(n_msg); + _ZP_UNUSED(reliability); + _ZP_UNUSED(first_sn); + _Z_INFO("Sending the message required fragmentation feature that is deactivated."); + return _Z_RES_OK; +} +#endif + +static inline bool _z_transport_tx_batch_has_data(_z_transport_common_t *ztc) { +#if Z_FEATURE_BATCHING == 1 + return (ztc->_batch_state == _Z_BATCHING_ACTIVE) && (ztc->_batch_count > 0); +#else + _ZP_UNUSED(ztc); + return false; +#endif +} + +static z_result_t _z_transport_tx_flush_buffer(_z_transport_common_t *ztc) { + // Send network message + __unsafe_z_finalize_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztc->_link, &ztc->_wbuf)); + ztc->_transmitted = true; // Tell session we transmitted data +#if Z_FEATURE_BATCHING == 1 + ztc->_batch_count = 0; +#endif + return _Z_RES_OK; +} + +static z_result_t _z_transport_tx_flush_or_incr_batch(_z_transport_common_t *ztc) { +#if Z_FEATURE_BATCHING == 1 + if (ztc->_batch_state == _Z_BATCHING_ACTIVE) { + // Increment batch count + ztc->_batch_count++; + return _Z_RES_OK; + } else { + return _z_transport_tx_flush_buffer(ztc); + } +#else + return _z_transport_tx_flush_buffer(ztc); +#endif +} + +static z_result_t _z_transport_tx_batch_overflow(_z_transport_common_t *ztc, const _z_network_message_t *n_msg, + z_reliability_t reliability, _z_zint_t sn, size_t prev_wpos) { +#if Z_FEATURE_BATCHING == 1 + // Remove partially encoded data + _z_wbuf_set_wpos(&ztc->_wbuf, prev_wpos); + // Send batch + _Z_RETURN_IF_ERR(_z_transport_tx_flush_buffer(ztc)); + // Init buffer + __unsafe_z_prepare_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + sn = _z_transport_tx_get_sn(ztc, reliability); + _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); + _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztc->_wbuf, &t_msg)); + // Retry encode + z_result_t ret = _z_network_message_encode(&ztc->_wbuf, n_msg); + if (ret != _Z_RES_OK) { + // Message still doesn't fit in buffer, send as fragments + return _z_transport_tx_send_fragment(ztc, n_msg, reliability, sn); + } else { + // Increment batch + ztc->_batch_count++; + } + return _Z_RES_OK; +#else + _ZP_UNUSED(ztc); + _ZP_UNUSED(n_msg); + _ZP_UNUSED(reliability); + _ZP_UNUSED(sn); + _ZP_UNUSED(prev_wpos); + return _Z_RES_OK; +#endif +} + +static size_t _z_transport_tx_save_wpos(_z_wbuf_t *wbuf) { +#if Z_FEATURE_BATCHING == 1 + return _z_wbuf_get_wpos(wbuf); +#else + _ZP_UNUSED(wbuf); + return 0; +#endif +} + +static z_result_t _z_transport_tx_send_n_msg_inner(_z_transport_common_t *ztc, const _z_network_message_t *n_msg, + z_reliability_t reliability) { + // Init buffer + _z_zint_t sn = 0; + bool batch_has_data = _z_transport_tx_batch_has_data(ztc); + if (!batch_has_data) { + __unsafe_z_prepare_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + sn = _z_transport_tx_get_sn(ztc, reliability); + _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); + _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztc->_wbuf, &t_msg)); + } + // Try encoding the network message + size_t prev_wpos = _z_transport_tx_save_wpos(&ztc->_wbuf); + z_result_t ret = _z_network_message_encode(&ztc->_wbuf, n_msg); + if (ret == _Z_RES_OK) { + // Flush buffer or increase batch + return _z_transport_tx_flush_or_incr_batch(ztc); + } else if (!batch_has_data) { + // Message doesn't fit in buffer, send as fragments + return _z_transport_tx_send_fragment(ztc, n_msg, reliability, sn); + } else { + // Buffer is too full for message + return _z_transport_tx_batch_overflow(ztc, n_msg, reliability, sn, prev_wpos); + } +} + +z_result_t _z_transport_tx_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg) { + z_result_t ret = _Z_RES_OK; + _Z_DEBUG("Send session message"); + _z_transport_tx_mutex_lock(ztc, true); + + // Encode transport message + __unsafe_z_prepare_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + ret = _z_transport_message_encode(&ztc->_wbuf, t_msg); + if (ret == _Z_RES_OK) { + // Send message + __unsafe_z_finalize_wbuf(&ztc->_wbuf, ztc->_link._cap._flow); + ret = _z_link_send_wbuf(&ztc->_link, &ztc->_wbuf); + if (ret == _Z_RES_OK) { + ztc->_transmitted = true; // Tell session we transmitted data + } + } + _z_transport_tx_mutex_unlock(ztc); + return ret; +} + +static z_result_t _z_transport_tx_send_n_msg(_z_transport_common_t *ztc, const _z_network_message_t *n_msg, + z_reliability_t reliability, z_congestion_control_t cong_ctrl) { + z_result_t ret = _Z_RES_OK; + _Z_DEBUG("Send network message"); + + // Acquire the lock and drop the message if needed + ret = _z_transport_tx_mutex_lock(ztc, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); + if (ret != _Z_RES_OK) { + _Z_INFO("Dropping zenoh message because of congestion control"); + return ret; + } + // Process message + ret = _z_transport_tx_send_n_msg_inner(ztc, n_msg, reliability); + _z_transport_tx_mutex_unlock(ztc); + return ret; +} + +static z_result_t _z_transport_tx_send_n_batch(_z_transport_common_t *ztc, z_congestion_control_t cong_ctrl) { +#if Z_FEATURE_BATCHING == 1 + // Check batch size + if (ztc->_batch_count > 0) { + // Acquire the lock and drop the message if needed + z_result_t ret = _z_transport_tx_mutex_lock(ztc, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); + if (ret != _Z_RES_OK) { + _Z_INFO("Dropping zenoh batch because of congestion control"); + return ret; + } + // Send batch + _Z_DEBUG("Send network batch"); + ret = _z_transport_tx_flush_buffer(ztc); + _z_transport_tx_mutex_unlock(ztc); + return ret; + } + return _Z_RES_OK; +#else + _ZP_UNUSED(ztc); + _ZP_UNUSED(cong_ctrl); + return _Z_RES_OK; +#endif +} + /** * This function is unsafe because it operates in potentially concurrent data. * Make sure that the following mutexes are locked before calling this function: @@ -74,13 +303,13 @@ z_result_t _z_send_t_msg(_z_transport_t *zt, const _z_transport_message_t *t_msg z_result_t ret = _Z_RES_OK; switch (zt->_type) { case _Z_TRANSPORT_UNICAST_TYPE: - ret = _z_unicast_send_t_msg(&zt->_transport._unicast, t_msg); + ret = _z_transport_tx_send_t_msg(&zt->_transport._unicast._common, t_msg); break; case _Z_TRANSPORT_MULTICAST_TYPE: - ret = _z_multicast_send_t_msg(&zt->_transport._multicast, t_msg); + ret = _z_transport_tx_send_t_msg(&zt->_transport._multicast._common, t_msg); break; case _Z_TRANSPORT_RAWETH_TYPE: - ret = _z_raweth_send_t_msg(&zt->_transport._raweth, t_msg); + ret = _z_raweth_send_t_msg(&zt->_transport._raweth._common, t_msg); break; default: ret = _Z_ERR_TRANSPORT_NOT_AVAILABLE; @@ -164,3 +393,45 @@ z_result_t __unsafe_z_serialize_zenoh_fragment(_z_wbuf_t *dst, _z_wbuf_t *src, z return ret; } + +z_result_t _z_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, + z_congestion_control_t cong_ctrl) { + z_result_t ret = _Z_RES_OK; + // Call transport function + switch (zn->_tp._type) { + case _Z_TRANSPORT_UNICAST_TYPE: + ret = _z_transport_tx_send_n_msg(&zn->_tp._transport._unicast._common, z_msg, reliability, cong_ctrl); + break; + case _Z_TRANSPORT_MULTICAST_TYPE: + ret = _z_transport_tx_send_n_msg(&zn->_tp._transport._multicast._common, z_msg, reliability, cong_ctrl); + break; + case _Z_TRANSPORT_RAWETH_TYPE: + ret = _z_raweth_send_n_msg(zn, z_msg, reliability, cong_ctrl); + break; + default: + ret = _Z_ERR_TRANSPORT_NOT_AVAILABLE; + break; + } + return ret; +} + +z_result_t _z_send_n_batch(_z_session_t *zn, z_congestion_control_t cong_ctrl) { + z_result_t ret = _Z_RES_OK; + // Call transport function + switch (zn->_tp._type) { + case _Z_TRANSPORT_UNICAST_TYPE: + ret = _z_transport_tx_send_n_batch(&zn->_tp._transport._unicast._common, cong_ctrl); + break; + case _Z_TRANSPORT_MULTICAST_TYPE: + ret = _z_transport_tx_send_n_batch(&zn->_tp._transport._multicast._common, cong_ctrl); + break; + case _Z_TRANSPORT_RAWETH_TYPE: + _Z_INFO("Batching not yet supported on raweth transport"); + ret = _Z_ERR_TRANSPORT_TX_FAILED; + break; + default: + ret = _Z_ERR_TRANSPORT_NOT_AVAILABLE; + break; + } + return ret; +} diff --git a/src/transport/multicast.c b/src/transport/multicast.c index 42059f6dc..8425131df 100644 --- a/src/transport/multicast.c +++ b/src/transport/multicast.c @@ -24,7 +24,6 @@ #include "zenoh-pico/transport/common/read.h" #include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/transport/multicast/rx.h" -#include "zenoh-pico/transport/multicast/tx.h" #include "zenoh-pico/transport/unicast/rx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" diff --git a/src/transport/multicast/lease.c b/src/transport/multicast/lease.c index b97663c8f..b8f98cd19 100644 --- a/src/transport/multicast/lease.c +++ b/src/transport/multicast/lease.c @@ -27,18 +27,18 @@ z_result_t _zp_multicast_send_join(_z_transport_multicast_t *ztm) { _z_conduit_sn_list_t next_sn; next_sn._is_qos = false; - next_sn._val._plain._best_effort = ztm->_sn_tx_best_effort; - next_sn._val._plain._reliable = ztm->_sn_tx_reliable; + next_sn._val._plain._best_effort = ztm->_common._sn_tx_best_effort; + next_sn._val._plain._reliable = ztm->_common._sn_tx_reliable; - _z_id_t zid = _Z_RC_IN_VAL(ztm->_session)->_local_zid; + _z_id_t zid = _Z_RC_IN_VAL(ztm->_common._session)->_local_zid; _z_transport_message_t jsm = _z_t_msg_make_join(Z_WHATAMI_PEER, Z_TRANSPORT_LEASE, zid, next_sn); - return ztm->_send_f(ztm, &jsm); + return ztm->_send_f(&ztm->_common, &jsm); } z_result_t _zp_multicast_send_keep_alive(_z_transport_multicast_t *ztm) { _z_transport_message_t t_msg = _z_t_msg_make_keep_alive(); - return ztm->_send_f(ztm, &t_msg); + return ztm->_send_f(&ztm->_common, &t_msg); } #else @@ -91,15 +91,15 @@ static _z_zint_t _z_get_next_lease(_z_transport_peer_entry_list_t *peers) { void *_zp_multicast_lease_task(void *ztm_arg) { _z_transport_multicast_t *ztm = (_z_transport_multicast_t *)ztm_arg; - ztm->_transmitted = false; + ztm->_common._transmitted = false; // From all peers, get the next lease time (minimum) - int next_lease = (int)_z_get_minimum_lease(ztm->_peers, ztm->_lease); + int next_lease = (int)_z_get_minimum_lease(ztm->_peers, ztm->_common._lease); int next_keep_alive = (int)(next_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); int next_join = Z_JOIN_INTERVAL; _z_transport_peer_entry_list_t *it = NULL; - while (ztm->_lease_task_running == true) { + while (ztm->_common._lease_task_running == true) { _z_mutex_lock(&ztm->_mutex_peer); if (next_lease <= 0) { @@ -122,7 +122,7 @@ void *_zp_multicast_lease_task(void *ztm_arg) { if (next_join <= 0) { _zp_multicast_send_join(ztm); - ztm->_transmitted = true; + ztm->_common._transmitted = true; // Reset the join parameters next_join = Z_JOIN_INTERVAL; @@ -130,17 +130,18 @@ void *_zp_multicast_lease_task(void *ztm_arg) { if (next_keep_alive <= 0) { // Check if need to send a keep alive - if (ztm->_transmitted == false) { + if (ztm->_common._transmitted == false) { if (_zp_multicast_send_keep_alive(ztm) < 0) { _Z_INFO("Send keep alive failed."); } } // Reset the keep alive parameters - ztm->_transmitted = false; - next_keep_alive = (int)(_z_get_minimum_lease(ztm->_peers, ztm->_lease) / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); + ztm->_common._transmitted = false; + next_keep_alive = + (int)(_z_get_minimum_lease(ztm->_peers, ztm->_common._lease) / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); } // Query timeout process - _z_pending_query_process_timeout(_Z_RC_IN_VAL(ztm->_session)); + _z_pending_query_process_timeout(_Z_RC_IN_VAL(ztm->_common._session)); // Compute the target interval to sleep int interval; @@ -191,19 +192,19 @@ void *_zp_multicast_lease_task(void *ztm_arg) { z_result_t _zp_multicast_start_lease_task(_z_transport_multicast_t *ztm, z_task_attr_t *attr, _z_task_t *task) { // Init memory (void)memset(task, 0, sizeof(_z_task_t)); - ztm->_lease_task_running = true; // Init before z_task_init for concurrency issue + ztm->_common._lease_task_running = true; // Init before z_task_init for concurrency issue // Init task if (_z_task_init(task, attr, _zp_multicast_lease_task, ztm) != _Z_RES_OK) { - ztm->_lease_task_running = false; + ztm->_common._lease_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task - ztm->_lease_task = task; + ztm->_common._lease_task = task; return _Z_RES_OK; } z_result_t _zp_multicast_stop_lease_task(_z_transport_multicast_t *ztm) { - ztm->_lease_task_running = false; + ztm->_common._lease_task_running = false; return _Z_RES_OK; } #else diff --git a/src/transport/multicast/read.c b/src/transport/multicast/read.c index 5cc377c5e..ad7a1eb1c 100644 --- a/src/transport/multicast/read.c +++ b/src/transport/multicast/read.c @@ -58,41 +58,42 @@ void *_zp_multicast_read_task(void *ztm_arg) { _z_transport_multicast_t *ztm = (_z_transport_multicast_t *)ztm_arg; // Acquire and keep the lock - _z_mutex_lock(&ztm->_mutex_rx); + _z_mutex_lock(&ztm->_common._mutex_rx); // Prepare the buffer - _z_zbuf_reset(&ztm->_zbuf); + _z_zbuf_reset(&ztm->_common._zbuf); uint8_t addr_buff[_Z_MULTICAST_ADDR_BUFF_SIZE] = {0}; _z_slice_t addr = _z_slice_alias_buf(addr_buff, sizeof(addr_buff)); - while (ztm->_read_task_running == true) { + while (ztm->_common._read_task_running == true) { size_t to_read = 0; // Read bytes from socket to the main buffer - switch (ztm->_link._cap._flow) { + switch (ztm->_common._link._cap._flow) { case Z_LINK_CAP_FLOW_STREAM: - if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, &addr); - if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_zbuf_compact(&ztm->_zbuf); + if (_z_zbuf_len(&ztm->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, &addr); + if (_z_zbuf_len(&ztm->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_zbuf_compact(&ztm->_common._zbuf); continue; } } // Get stream size - to_read = _z_read_stream_size(&ztm->_zbuf); + to_read = _z_read_stream_size(&ztm->_common._zbuf); // Read data - if (_z_zbuf_len(&ztm->_zbuf) < to_read) { - _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, NULL); - if (_z_zbuf_len(&ztm->_zbuf) < to_read) { - _z_zbuf_set_rpos(&ztm->_zbuf, _z_zbuf_get_rpos(&ztm->_zbuf) - _Z_MSG_LEN_ENC_SIZE); - _z_zbuf_compact(&ztm->_zbuf); + if (_z_zbuf_len(&ztm->_common._zbuf) < to_read) { + _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, NULL); + if (_z_zbuf_len(&ztm->_common._zbuf) < to_read) { + _z_zbuf_set_rpos(&ztm->_common._zbuf, + _z_zbuf_get_rpos(&ztm->_common._zbuf) - _Z_MSG_LEN_ENC_SIZE); + _z_zbuf_compact(&ztm->_common._zbuf); continue; } } break; case Z_LINK_CAP_FLOW_DATAGRAM: - _z_zbuf_compact(&ztm->_zbuf); - to_read = _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, &addr); + _z_zbuf_compact(&ztm->_common._zbuf); + to_read = _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, &addr); if (to_read == SIZE_MAX) { continue; } @@ -101,7 +102,7 @@ void *_zp_multicast_read_task(void *ztm_arg) { break; } // Wrap the main buffer to_read bytes - _z_zbuf_t zbuf = _z_zbuf_view(&ztm->_zbuf, to_read); + _z_zbuf_t zbuf = _z_zbuf_view(&ztm->_common._zbuf, to_read); while (_z_zbuf_len(&zbuf) > 0) { // Decode one session message @@ -118,37 +119,37 @@ void *_zp_multicast_read_task(void *ztm_arg) { } } else { _Z_ERROR("Connection closed due to malformed message: %d", ret); - ztm->_read_task_running = false; + ztm->_common._read_task_running = false; continue; } } // Move the read position of the read buffer - _z_zbuf_set_rpos(&ztm->_zbuf, _z_zbuf_get_rpos(&ztm->_zbuf) + to_read); + _z_zbuf_set_rpos(&ztm->_common._zbuf, _z_zbuf_get_rpos(&ztm->_common._zbuf) + to_read); if (_z_multicast_update_rx_buffer(ztm) != _Z_RES_OK) { _Z_ERROR("Connection closed due to lack of memory to allocate rx buffer"); - ztm->_read_task_running = false; + ztm->_common._read_task_running = false; } } - _z_mutex_unlock(&ztm->_mutex_rx); + _z_mutex_unlock(&ztm->_common._mutex_rx); return NULL; } z_result_t _zp_multicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task) { // Init memory (void)memset(task, 0, sizeof(_z_task_t)); - zt->_transport._multicast._read_task_running = true; // Init before z_task_init for concurrency issue + zt->_transport._multicast._common._read_task_running = true; // Init before z_task_init for concurrency issue // Init task if (_z_task_init(task, attr, _zp_multicast_read_task, &zt->_transport._multicast) != _Z_RES_OK) { - zt->_transport._multicast._read_task_running = false; + zt->_transport._multicast._common._read_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task - zt->_transport._multicast._read_task = task; + zt->_transport._multicast._common._read_task = task; return _Z_RES_OK; } z_result_t _zp_multicast_stop_read_task(_z_transport_t *zt) { - zt->_transport._multicast._read_task_running = false; + zt->_transport._multicast._common._read_task_running = false; return _Z_RES_OK; } #else diff --git a/src/transport/multicast/rx.c b/src/transport/multicast/rx.c index 4fb823e46..d10d9709f 100644 --- a/src/transport/multicast/rx.c +++ b/src/transport/multicast/rx.c @@ -35,27 +35,28 @@ static z_result_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_t _Z_DEBUG(">> recv session msg"); z_result_t ret = _Z_RES_OK; - _z_multicast_rx_mutex_lock(ztm); + _z_transport_rx_mutex_lock(&ztm->_common); size_t to_read = 0; do { - switch (ztm->_link._cap._flow) { + switch (ztm->_common._link._cap._flow) { case Z_LINK_CAP_FLOW_STREAM: - if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, addr); - if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_zbuf_compact(&ztm->_zbuf); + if (_z_zbuf_len(&ztm->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, addr); + if (_z_zbuf_len(&ztm->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_zbuf_compact(&ztm->_common._zbuf); ret = _Z_ERR_TRANSPORT_NOT_ENOUGH_BYTES; break; } } // Get stream size - to_read = _z_read_stream_size(&ztm->_zbuf); + to_read = _z_read_stream_size(&ztm->_common._zbuf); // Read data - if (_z_zbuf_len(&ztm->_zbuf) < to_read) { - _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, addr); - if (_z_zbuf_len(&ztm->_zbuf) < to_read) { - _z_zbuf_set_rpos(&ztm->_zbuf, _z_zbuf_get_rpos(&ztm->_zbuf) - _Z_MSG_LEN_ENC_SIZE); - _z_zbuf_compact(&ztm->_zbuf); + if (_z_zbuf_len(&ztm->_common._zbuf) < to_read) { + _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, addr); + if (_z_zbuf_len(&ztm->_common._zbuf) < to_read) { + _z_zbuf_set_rpos(&ztm->_common._zbuf, + _z_zbuf_get_rpos(&ztm->_common._zbuf) - _Z_MSG_LEN_ENC_SIZE); + _z_zbuf_compact(&ztm->_common._zbuf); ret = _Z_ERR_TRANSPORT_NOT_ENOUGH_BYTES; break; } @@ -63,8 +64,8 @@ static z_result_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_t break; // Datagram capable links case Z_LINK_CAP_FLOW_DATAGRAM: - _z_zbuf_compact(&ztm->_zbuf); - to_read = _z_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, addr); + _z_zbuf_compact(&ztm->_common._zbuf); + to_read = _z_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, addr); if (to_read == SIZE_MAX) { ret = _Z_ERR_TRANSPORT_RX_FAILED; } @@ -75,10 +76,10 @@ static z_result_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_t } while (false); // The 1-iteration loop to use continue to break the entire loop on error if (ret == _Z_RES_OK) { - _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_zbuf)); - ret = _z_transport_message_decode(t_msg, &ztm->_zbuf); + _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_common._zbuf)); + ret = _z_transport_message_decode(t_msg, &ztm->_common._zbuf); } - _z_multicast_rx_mutex_unlock(ztm); + _z_transport_rx_mutex_unlock(&ztm->_common); return ret; } @@ -167,7 +168,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, zm->_reliability = _z_t_msg_get_reliability(t_msg); _z_msg_fix_mapping(zm, mapping); - _z_handle_network_message(ztm->_session, zm, mapping); + _z_handle_network_message(ztm->_common._session, zm, mapping); } break; @@ -239,7 +240,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, if (ret == _Z_RES_OK) { uint16_t mapping = entry->_peer_id; _z_msg_fix_mapping(&zm, mapping); - _z_handle_network_message(ztm->_session, &zm, mapping); + _z_handle_network_message(ztm->_common._session, &zm, mapping); } else { _Z_INFO("Failed to decode defragmented message"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; @@ -364,20 +365,20 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, z_result_t _z_multicast_update_rx_buffer(_z_transport_multicast_t *ztm) { // Check if user or defragment buffer took ownership of buffer - if (_z_zbuf_get_ref_count(&ztm->_zbuf) != 1) { + if (_z_zbuf_get_ref_count(&ztm->_common._zbuf) != 1) { // Allocate a new buffer _z_zbuf_t new_zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); if (_z_zbuf_capacity(&new_zbuf) != Z_BATCH_MULTICAST_SIZE) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } // Recopy leftover bytes - size_t leftovers = _z_zbuf_len(&ztm->_zbuf); + size_t leftovers = _z_zbuf_len(&ztm->_common._zbuf); if (leftovers > 0) { - _z_zbuf_copy_bytes(&new_zbuf, &ztm->_zbuf); + _z_zbuf_copy_bytes(&new_zbuf, &ztm->_common._zbuf); } // Drop buffer & update - _z_zbuf_clear(&ztm->_zbuf); - ztm->_zbuf = new_zbuf; + _z_zbuf_clear(&ztm->_common._zbuf); + ztm->_common._zbuf = new_zbuf; } return _Z_RES_OK; } diff --git a/src/transport/multicast/transport.c b/src/transport/multicast/transport.c index 4ff1f3717..776d007fb 100644 --- a/src/transport/multicast/transport.c +++ b/src/transport/multicast/transport.c @@ -25,7 +25,6 @@ #include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/transport/multicast.h" #include "zenoh-pico/transport/multicast/rx.h" -#include "zenoh-pico/transport/multicast/tx.h" #include "zenoh-pico/transport/raweth/tx.h" #include "zenoh-pico/transport/unicast/rx.h" #include "zenoh-pico/transport/utils.h" @@ -42,7 +41,7 @@ z_result_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, case Z_LINK_CAP_TRANSPORT_MULTICAST: zt->_type = _Z_TRANSPORT_MULTICAST_TYPE; ztm = &zt->_transport._multicast; - ztm->_send_f = _z_multicast_send_t_msg; + ztm->_send_f = _z_transport_tx_send_t_msg; break; case Z_LINK_CAP_TRANSPORT_RAWETH: zt->_type = _Z_TRANSPORT_RAWETH_TYPE; @@ -55,23 +54,23 @@ z_result_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, // Initialize batching data #if Z_FEATURE_BATCHING == 1 - ztm->_batch_state = _Z_BATCHING_IDLE; - ztm->_batch = _z_network_message_vec_make(0); + ztm->_common._batch_state = _Z_BATCHING_IDLE; + ztm->_common._batch_count = 0; #endif #if Z_FEATURE_MULTI_THREAD == 1 // Initialize the mutexes - ret = _z_mutex_init(&ztm->_mutex_tx); + ret = _z_mutex_init(&ztm->_common._mutex_tx); if (ret == _Z_RES_OK) { - ret = _z_mutex_init(&ztm->_mutex_rx); + ret = _z_mutex_init(&ztm->_common._mutex_rx); if (ret == _Z_RES_OK) { ret = _z_mutex_init(&ztm->_mutex_peer); if (ret != _Z_RES_OK) { - _z_mutex_drop(&ztm->_mutex_tx); - _z_mutex_drop(&ztm->_mutex_rx); + _z_mutex_drop(&ztm->_common._mutex_tx); + _z_mutex_drop(&ztm->_common._mutex_rx); } } else { - _z_mutex_drop(&ztm->_mutex_tx); + _z_mutex_drop(&ztm->_common._mutex_tx); } } #endif // Z_FEATURE_MULTI_THREAD == 1 @@ -79,51 +78,52 @@ z_result_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, // Initialize the read and write buffers if (ret == _Z_RES_OK) { uint16_t mtu = (zl->_mtu < Z_BATCH_MULTICAST_SIZE) ? zl->_mtu : Z_BATCH_MULTICAST_SIZE; - ztm->_wbuf = _z_wbuf_make(mtu, false); - ztm->_zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); + ztm->_common._wbuf = _z_wbuf_make(mtu, false); + ztm->_common._zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); // Clean up the buffers if one of them failed to be allocated - if ((_z_wbuf_capacity(&ztm->_wbuf) != mtu) || (_z_zbuf_capacity(&ztm->_zbuf) != Z_BATCH_MULTICAST_SIZE)) { + if ((_z_wbuf_capacity(&ztm->_common._wbuf) != mtu) || + (_z_zbuf_capacity(&ztm->_common._zbuf) != Z_BATCH_MULTICAST_SIZE)) { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; _Z_ERROR("Not enough memory to allocate transport tx rx buffers!"); #if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_drop(&ztm->_mutex_tx); - _z_mutex_drop(&ztm->_mutex_rx); + _z_mutex_drop(&ztm->_common._mutex_tx); + _z_mutex_drop(&ztm->_common._mutex_rx); _z_mutex_drop(&ztm->_mutex_peer); #endif // Z_FEATURE_MULTI_THREAD == 1 - _z_wbuf_clear(&ztm->_wbuf); - _z_zbuf_clear(&ztm->_zbuf); + _z_wbuf_clear(&ztm->_common._wbuf); + _z_zbuf_clear(&ztm->_common._zbuf); } } if (ret == _Z_RES_OK) { // Set default SN resolution - ztm->_sn_res = _z_sn_max(param->_seq_num_res); + ztm->_common._sn_res = _z_sn_max(param->_seq_num_res); // The initial SN at TX side - ztm->_sn_tx_reliable = param->_initial_sn_tx._val._plain._reliable; - ztm->_sn_tx_best_effort = param->_initial_sn_tx._val._plain._best_effort; + ztm->_common._sn_tx_reliable = param->_initial_sn_tx._val._plain._reliable; + ztm->_common._sn_tx_best_effort = param->_initial_sn_tx._val._plain._best_effort; // Initialize peer list ztm->_peers = _z_transport_peer_entry_list_new(); #if Z_FEATURE_MULTI_THREAD == 1 // Tasks - ztm->_read_task_running = false; - ztm->_read_task = NULL; - ztm->_lease_task_running = false; - ztm->_lease_task = NULL; + ztm->_common._read_task_running = false; + ztm->_common._read_task = NULL; + ztm->_common._lease_task_running = false; + ztm->_common._lease_task = NULL; #endif // Z_FEATURE_MULTI_THREAD == 1 - ztm->_lease = Z_TRANSPORT_LEASE; + ztm->_common._lease = Z_TRANSPORT_LEASE; // Notifiers - ztm->_transmitted = false; + ztm->_common._transmitted = false; // Transport link for multicast - ztm->_link = *zl; + ztm->_common._link = *zl; } return ret; } @@ -179,7 +179,7 @@ z_result_t _z_multicast_send_close(_z_transport_multicast_t *ztm, uint8_t reason z_result_t ret = _Z_RES_OK; // Send and clear message _z_transport_message_t cm = _z_t_msg_make_close(reason, link_only); - ret = ztm->_send_f(ztm, &cm); + ret = ztm->_send_f(&ztm->_common, &cm); _z_t_msg_clear(&cm); return ret; } @@ -192,31 +192,27 @@ void _z_multicast_transport_clear(_z_transport_t *zt) { _z_transport_multicast_t *ztm = &zt->_transport._multicast; #if Z_FEATURE_MULTI_THREAD == 1 // Clean up tasks - if (ztm->_read_task != NULL) { - _z_task_join(ztm->_read_task); - _z_task_free(&ztm->_read_task); + if (ztm->_common._read_task != NULL) { + _z_task_join(ztm->_common._read_task); + _z_task_free(&ztm->_common._read_task); } - if (ztm->_lease_task != NULL) { - _z_task_join(ztm->_lease_task); - _z_task_free(&ztm->_lease_task); + if (ztm->_common._lease_task != NULL) { + _z_task_join(ztm->_common._lease_task); + _z_task_free(&ztm->_common._lease_task); } // Clean up the mutexes - _z_mutex_drop(&ztm->_mutex_tx); - _z_mutex_drop(&ztm->_mutex_rx); + _z_mutex_drop(&ztm->_common._mutex_tx); + _z_mutex_drop(&ztm->_common._mutex_rx); _z_mutex_drop(&ztm->_mutex_peer); #endif // Z_FEATURE_MULTI_THREAD == 1 -#if Z_FEATURE_BATCHING == 1 - _z_network_message_vec_clear(&ztm->_batch); -#endif - // Clean up the buffers - _z_wbuf_clear(&ztm->_wbuf); - _z_zbuf_clear(&ztm->_zbuf); + _z_wbuf_clear(&ztm->_common._wbuf); + _z_zbuf_clear(&ztm->_common._zbuf); // Clean up peer list _z_transport_peer_entry_list_free(&ztm->_peers); - _z_link_clear(&ztm->_link); + _z_link_clear(&ztm->_common._link); } #else diff --git a/src/transport/multicast/tx.c b/src/transport/multicast/tx.c deleted file mode 100644 index 572134c11..000000000 --- a/src/transport/multicast/tx.c +++ /dev/null @@ -1,287 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#include "zenoh-pico/transport/common/tx.h" - -#include "zenoh-pico/config.h" -#include "zenoh-pico/protocol/codec/network.h" -#include "zenoh-pico/protocol/codec/transport.h" -#include "zenoh-pico/transport/multicast/transport.h" -#include "zenoh-pico/transport/multicast/tx.h" -#include "zenoh-pico/transport/utils.h" -#include "zenoh-pico/utils/logging.h" - -#if Z_FEATURE_MULTICAST_TRANSPORT == 1 - -/** - * This function is unsafe because it operates in potentially concurrent data. - * Make sure that the following mutexes are locked before calling this function: - * - ztm->_mutex_inner - */ -static _z_zint_t __unsafe_z_multicast_get_sn(_z_transport_multicast_t *ztm, z_reliability_t reliability) { - _z_zint_t sn; - if (reliability == Z_RELIABILITY_RELIABLE) { - sn = ztm->_sn_tx_reliable; - ztm->_sn_tx_reliable = _z_sn_increment(ztm->_sn_res, ztm->_sn_tx_reliable); - } else { - sn = ztm->_sn_tx_best_effort; - ztm->_sn_tx_best_effort = _z_sn_increment(ztm->_sn_res, ztm->_sn_tx_best_effort); - } - return sn; -} - -#if Z_FEATURE_FRAGMENTATION == 1 -static z_result_t __unsafe_z_multicast_send_fragment(_z_transport_multicast_t *ztm, _z_wbuf_t *fbf, - const _z_network_message_t *n_msg, z_reliability_t reliability, - _z_zint_t first_sn) { - bool is_first = true; - _z_zint_t sn = first_sn; - // Encode message on temp buffer - _Z_RETURN_IF_ERR(_z_network_message_encode(fbf, n_msg)); - // Fragment message - while (_z_wbuf_len(fbf) > 0) { - // Get fragment sequence number - if (!is_first) { - sn = __unsafe_z_multicast_get_sn(ztm, reliability); - } - is_first = false; - // Serialize fragment - __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - z_result_t ret = __unsafe_z_serialize_zenoh_fragment(&ztm->_wbuf, fbf, reliability, sn); - if (ret != _Z_RES_OK) { - _Z_ERROR("Fragment serialization failed with err %d", ret); - return ret; - } - // Send fragment - __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztm->_link, &ztm->_wbuf)); - ztm->_transmitted = true; // Tell session we have transmitted data - } - return _Z_RES_OK; -} -#else -static z_result_t __unsafe_z_multicast_send_fragment(_z_transport_multicast_t *ztm, _z_wbuf_t *fbf, - const _z_network_message_t *n_msg, z_reliability_t reliability, - _z_zint_t first_sn) { - _ZP_UNUSED(ztm); - _ZP_UNUSED(fbf); - _ZP_UNUSED(n_msg); - _ZP_UNUSED(reliability); - _ZP_UNUSED(first_sn); - _Z_INFO("Sending the message required fragmentation feature that is deactivated."); - return _Z_RES_OK; -} -#endif // Z_FEATURE_FRAGMENTATION == 1 - -static z_result_t __unsafe_z_multicast_message_send(_z_transport_multicast_t *ztm, const _z_network_message_t *n_msg, - z_reliability_t reliability) { - _Z_DEBUG("Send network message"); - // Encode frame header - __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - _z_zint_t sn = __unsafe_z_multicast_get_sn(ztm, reliability); - _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); - _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, &t_msg)); - // Encode network message - z_result_t ret = _z_network_message_encode(&ztm->_wbuf, n_msg); - // The message does not fit in the current batch, let's fragment it - if (ret != _Z_RES_OK) { - // Create an expandable wbuf for fragmentation - _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); - // Send message as fragments - ret = __unsafe_z_multicast_send_fragment(ztm, &fbf, n_msg, reliability, sn); - // Clear the buffer as it's no longer required - _z_wbuf_clear(&fbf); - return ret; - } - // Send network message - __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztm->_link, &ztm->_wbuf)); - ztm->_transmitted = true; // Tell session we transmitted data - return _Z_RES_OK; -} - -#if Z_FEATURE_BATCHING == 1 -static z_result_t __unsafe_z_multicast_message_batch(_z_transport_multicast_t *ztm, const _z_network_message_t *n_msg) { - _Z_DEBUG("Batching network message"); - // Copy network message - _z_network_message_t *batch_msg = z_malloc(sizeof(_z_network_message_t)); - if (batch_msg == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - if (_z_n_msg_copy(batch_msg, n_msg) != _Z_RES_OK) { - z_free(batch_msg); - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - _z_network_message_vec_append(&ztm->_batch, batch_msg); - return _Z_RES_OK; -} - -static z_result_t __unsafe_multicast_batch_send(_z_transport_multicast_t *ztm, z_reliability_t reliability) { - z_result_t ret = _Z_RES_OK; - // Get network message number - size_t msg_nb = _z_network_message_vec_len(&ztm->_batch); - size_t msg_idx = 0; - size_t curr_msg_nb = 0; - if (msg_nb == 0) { - return _Z_RES_OK; - } - // Encode the frame header - __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - _z_zint_t sn = __unsafe_z_multicast_get_sn(ztm, reliability); - _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); - _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, &t_msg)); - size_t curr_wpos = _z_wbuf_get_wpos(&ztm->_wbuf); - // Process batch - while (msg_idx < msg_nb) { - // Encode a network message - _z_network_message_t *n_msg = _z_network_message_vec_get(&ztm->_batch, msg_idx); - assert(n_msg != NULL); - if (_z_network_message_encode(&ztm->_wbuf, n_msg) != _Z_RES_OK) { - // Remove partially encoded data - _z_wbuf_set_wpos(&ztm->_wbuf, curr_wpos); - // Handle case where one message is too big to fit in frame - if (curr_msg_nb == 0) { - _Z_INFO("Batch sending interrupted by a message needing to be fragmented."); - // Create an expandable wbuf for fragmentation - _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); - // Send message as fragments - ret = __unsafe_z_multicast_send_fragment(ztm, &fbf, n_msg, reliability, sn); - // Clear the buffer as it's no longer required - _z_wbuf_clear(&fbf); - if (ret != _Z_RES_OK) { - _Z_ERROR("Send fragmented message failed with err %d.", ret); - } - // Message is sent or skipped - msg_idx++; - } else { // Frame has messages but is full - _Z_INFO("Sending batch in multiple frames because it is too big for one"); - // Send frame - __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztm->_link, &ztm->_wbuf)); - ztm->_transmitted = true; - curr_msg_nb = 0; - } - // Reset frame - __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - sn = __unsafe_z_multicast_get_sn(ztm, reliability); - t_msg = _z_t_msg_make_frame_header(sn, reliability); - _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, &t_msg)); - } else { - curr_wpos = _z_wbuf_get_wpos(&ztm->_wbuf); - msg_idx++; - curr_msg_nb++; - } - } - // Send frame - __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztm->_link, &ztm->_wbuf)); - ztm->_transmitted = true; // Tell session we transmitted data - return ret; -} -#endif - -z_result_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg) { - z_result_t ret = _Z_RES_OK; - _Z_DEBUG("Send session message"); - _z_multicast_tx_mutex_lock(ztm, true); - - // Encode transport message - __unsafe_z_prepare_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - ret = _z_transport_message_encode(&ztm->_wbuf, t_msg); - if (ret == _Z_RES_OK) { - // Send message - __unsafe_z_finalize_wbuf(&ztm->_wbuf, ztm->_link._cap._flow); - ret = _z_link_send_wbuf(&ztm->_link, &ztm->_wbuf); - if (ret == _Z_RES_OK) { - ztm->_transmitted = true; // Tell session we transmitted data - } - } - _z_multicast_tx_mutex_unlock(ztm); - return ret; -} - -z_result_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl) { - z_result_t ret = _Z_RES_OK; - _z_transport_multicast_t *ztm = &zn->_tp._transport._multicast; - - // Acquire the lock and drop the message if needed - ret = _z_multicast_tx_mutex_lock(ztm, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); - if (ret != _Z_RES_OK) { - _Z_INFO("Dropping zenoh message because of congestion control"); - return ret; - } - // Process batching -#if Z_FEATURE_BATCHING == 1 - if (ztm->_batch_state == _Z_BATCHING_ACTIVE) { - ret = __unsafe_z_multicast_message_batch(ztm, n_msg); - } else { - ret = __unsafe_z_multicast_message_send(ztm, n_msg, reliability); - } -#else - ret = __unsafe_z_multicast_message_send(ztm, n_msg, reliability); -#endif - _z_multicast_tx_mutex_unlock(ztm); - return ret; -} - -z_result_t _z_multicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { -#if Z_FEATURE_BATCHING == 1 - _Z_DEBUG("Send network batch"); - _z_transport_multicast_t *ztm = &zn->_tp._transport._multicast; - // Acquire the lock and drop the message if needed - z_result_t ret = _z_multicast_tx_mutex_lock(ztm, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); - if (ret != _Z_RES_OK) { - _Z_INFO("Dropping zenoh batch because of congestion control"); - return ret; - } - // Send batch - ret = __unsafe_multicast_batch_send(ztm, reliability); - // Clean up - _z_network_message_vec_clear(&ztm->_batch); - _z_multicast_tx_mutex_unlock(ztm); - return ret; -#else - _ZP_UNUSED(zn); - _ZP_UNUSED(reliability); - _ZP_UNUSED(cong_ctrl); - _Z_ERROR("Tried to send batch but batching feature is deactivated."); - return _Z_ERR_TRANSPORT_TX_FAILED; -#endif -} - -#else -z_result_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg) { - _ZP_UNUSED(ztm); - _ZP_UNUSED(t_msg); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} - -z_result_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl) { - _ZP_UNUSED(zn); - _ZP_UNUSED(n_msg); - _ZP_UNUSED(reliability); - _ZP_UNUSED(cong_ctrl); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} - -z_result_t _z_multicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { - _ZP_UNUSED(zn); - _ZP_UNUSED(reliability); - _ZP_UNUSED(cong_ctrl); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} - -#endif // Z_FEATURE_MULTICAST_TRANSPORT == 1 diff --git a/src/transport/raweth/read.c b/src/transport/raweth/read.c index 4c49d7b64..aa9995562 100644 --- a/src/transport/raweth/read.c +++ b/src/transport/raweth/read.c @@ -59,7 +59,7 @@ void *_zp_raweth_read_task(void *ztm_arg) { _z_slice_t addr = _z_slice_alias_buf(NULL, 0); // Task loop - while (ztm->_read_task_running == true) { + while (ztm->_common._read_task_running == true) { // Read message from link z_result_t ret = _z_raweth_recv_t_msg(ztm, &t_msg, &addr); switch (ret) { @@ -74,7 +74,7 @@ void *_zp_raweth_read_task(void *ztm_arg) { default: // Drop message & stop task _Z_ERROR("Connection closed due to malformed message: %d", ret); - ztm->_read_task_running = false; + ztm->_common._read_task_running = false; _z_slice_clear(&addr); continue; break; @@ -83,7 +83,7 @@ void *_zp_raweth_read_task(void *ztm_arg) { ret = _z_multicast_handle_transport_message(ztm, &t_msg, &addr); if (ret != _Z_RES_OK) { _Z_ERROR("Connection closed due to message processing error: %d", ret); - ztm->_read_task_running = false; + ztm->_common._read_task_running = false; _z_slice_clear(&addr); continue; } @@ -91,7 +91,7 @@ void *_zp_raweth_read_task(void *ztm_arg) { _z_slice_clear(&addr); if (_z_raweth_update_rx_buff(ztm) != _Z_RES_OK) { _Z_ERROR("Connection closed due to lack of memory to allocate rx buffer"); - ztm->_read_task_running = false; + ztm->_common._read_task_running = false; } } return NULL; @@ -100,19 +100,19 @@ void *_zp_raweth_read_task(void *ztm_arg) { z_result_t _zp_raweth_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task) { // Init memory (void)memset(task, 0, sizeof(_z_task_t)); - zt->_transport._unicast._lease_task_running = true; // Init before z_task_init for concurrency issue + zt->_transport._unicast._common._lease_task_running = true; // Init before z_task_init for concurrency issue // Init task if (_z_task_init(task, attr, _zp_raweth_read_task, &zt->_transport._raweth) != _Z_RES_OK) { - zt->_transport._unicast._lease_task_running = false; + zt->_transport._unicast._common._lease_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task - zt->_transport._raweth._read_task = task; + zt->_transport._raweth._common._read_task = task; return _Z_RES_OK; } z_result_t _zp_raweth_stop_read_task(_z_transport_t *zt) { - zt->_transport._raweth._read_task_running = false; + zt->_transport._raweth._common._read_task_running = false; return _Z_RES_OK; } #else diff --git a/src/transport/raweth/rx.c b/src/transport/raweth/rx.c index 296bbe5fb..389b57c70 100644 --- a/src/transport/raweth/rx.c +++ b/src/transport/raweth/rx.c @@ -78,16 +78,16 @@ z_result_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_m _Z_DEBUG(">> recv session msg"); z_result_t ret = _Z_RES_OK; - _z_multicast_rx_mutex_lock(ztm); + _z_transport_rx_mutex_lock(&ztm->_common); // Prepare the buffer - _z_zbuf_reset(&ztm->_zbuf); + _z_zbuf_reset(&ztm->_common._zbuf); - switch (ztm->_link._cap._flow) { + switch (ztm->_common._link._cap._flow) { // Datagram capable links case Z_LINK_CAP_FLOW_DATAGRAM: { - _z_zbuf_compact(&ztm->_zbuf); + _z_zbuf_compact(&ztm->_common._zbuf); // Read from link - size_t to_read = _z_raweth_link_recv_zbuf(&ztm->_link, &ztm->_zbuf, addr); + size_t to_read = _z_raweth_link_recv_zbuf(&ztm->_common._link, &ztm->_common._zbuf, addr); if (to_read == SIZE_MAX) { ret = _Z_ERR_TRANSPORT_RX_FAILED; } @@ -99,10 +99,10 @@ z_result_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_m } // Decode message if (ret == _Z_RES_OK) { - _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_zbuf)); - ret = _z_transport_message_decode(t_msg, &ztm->_zbuf); + _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_common._zbuf)); + ret = _z_transport_message_decode(t_msg, &ztm->_common._zbuf); } - _z_multicast_rx_mutex_unlock(ztm); + _z_transport_rx_mutex_unlock(&ztm->_common); return ret; } @@ -112,20 +112,20 @@ z_result_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_mess z_result_t _z_raweth_update_rx_buff(_z_transport_multicast_t *ztm) { // Check if user or defragment buffer took ownership of buffer - if (_z_zbuf_get_ref_count(&ztm->_zbuf) != 1) { + if (_z_zbuf_get_ref_count(&ztm->_common._zbuf) != 1) { // Allocate a new buffer _z_zbuf_t new_zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); if (_z_zbuf_capacity(&new_zbuf) != Z_BATCH_MULTICAST_SIZE) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } // Recopy leftover bytes - size_t leftovers = _z_zbuf_len(&ztm->_zbuf); + size_t leftovers = _z_zbuf_len(&ztm->_common._zbuf); if (leftovers > 0) { - _z_zbuf_copy_bytes(&new_zbuf, &ztm->_zbuf); + _z_zbuf_copy_bytes(&new_zbuf, &ztm->_common._zbuf); } // Drop buffer & update - _z_zbuf_clear(&ztm->_zbuf); - ztm->_zbuf = new_zbuf; + _z_zbuf_clear(&ztm->_common._zbuf); + ztm->_common._zbuf = new_zbuf; } return _Z_RES_OK; } diff --git a/src/transport/raweth/tx.c b/src/transport/raweth/tx.c index 87b5693ab..e44d5bdab 100644 --- a/src/transport/raweth/tx.c +++ b/src/transport/raweth/tx.c @@ -87,11 +87,11 @@ static z_result_t _zp_raweth_set_socket(const _z_keyexpr_t *keyexpr, _z_raweth_s static _z_zint_t __unsafe_z_raweth_get_sn(_z_transport_multicast_t *ztm, z_reliability_t reliability) { _z_zint_t sn; if (reliability == Z_RELIABILITY_RELIABLE) { - sn = ztm->_sn_tx_reliable; - ztm->_sn_tx_reliable = _z_sn_increment(ztm->_sn_res, ztm->_sn_tx_reliable); + sn = ztm->_common._sn_tx_reliable; + ztm->_common._sn_tx_reliable = _z_sn_increment(ztm->_common._sn_res, ztm->_common._sn_tx_reliable); } else { - sn = ztm->_sn_tx_best_effort; - ztm->_sn_tx_best_effort = _z_sn_increment(ztm->_sn_res, ztm->_sn_tx_best_effort); + sn = ztm->_common._sn_tx_best_effort; + ztm->_common._sn_tx_best_effort = _z_sn_increment(ztm->_common._sn_res, ztm->_common._sn_tx_best_effort); } return sn; } @@ -187,26 +187,26 @@ z_result_t _z_raweth_link_send_t_msg(const _z_link_t *zl, const _z_transport_mes return ret; } -z_result_t _z_raweth_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg) { +z_result_t _z_raweth_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg) { z_result_t ret = _Z_RES_OK; _Z_DEBUG(">> send session message"); - _z_multicast_tx_mutex_lock(ztm, true); + _z_transport_tx_mutex_lock(ztc, true); // Reset wbuf - _z_wbuf_reset(&ztm->_wbuf); + _z_wbuf_reset(&ztc->_wbuf); // Set socket info - _Z_CLEAN_RETURN_IF_ERR(_zp_raweth_set_socket(NULL, &ztm->_link._socket._raweth), _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_zp_raweth_set_socket(NULL, &ztc->_link._socket._raweth), _z_transport_tx_mutex_unlock(ztc)); // Prepare buff - __unsafe_z_raweth_prepare_header(&ztm->_link, &ztm->_wbuf); + __unsafe_z_raweth_prepare_header(&ztc->_link, &ztc->_wbuf); // Encode the session message - _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, t_msg), _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztc->_wbuf, t_msg), _z_transport_tx_mutex_unlock(ztc)); // Write the message header - _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_link, &ztm->_wbuf), _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztc->_link, &ztc->_wbuf), _z_transport_tx_mutex_unlock(ztc)); // Send the wbuf on the socket - _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztc->_link, &ztc->_wbuf), _z_transport_tx_mutex_unlock(ztc)); // Mark the session that we have transmitted data - ztm->_transmitted = true; - _z_multicast_tx_mutex_unlock(ztm); + ztc->_transmitted = true; + _z_transport_tx_mutex_unlock(ztc); return ret; } @@ -217,7 +217,7 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ _Z_DEBUG(">> send network message"); // Acquire the lock and drop the message if needed - ret = _z_multicast_tx_mutex_lock(ztm, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); + ret = _z_transport_tx_mutex_lock(&ztm->_common, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); if (ret != _Z_RES_OK) { _Z_INFO("Dropping zenoh message because of congestion control"); return ret; @@ -239,32 +239,34 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ break; } // Reset wbuf - _z_wbuf_reset(&ztm->_wbuf); + _z_wbuf_reset(&ztm->_common._wbuf); // Set socket info - _Z_CLEAN_RETURN_IF_ERR(_zp_raweth_set_socket(keyexpr, &ztm->_link._socket._raweth), - _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_zp_raweth_set_socket(keyexpr, &ztm->_common._link._socket._raweth), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Prepare buff - __unsafe_z_raweth_prepare_header(&ztm->_link, &ztm->_wbuf); + __unsafe_z_raweth_prepare_header(&ztm->_common._link, &ztm->_common._wbuf); // Set the frame header _z_zint_t sn = __unsafe_z_raweth_get_sn(ztm, reliability); _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); // Encode the frame header - _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_wbuf, &t_msg), _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_transport_message_encode(&ztm->_common._wbuf, &t_msg), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Encode the network message - if (_z_network_message_encode(&ztm->_wbuf, n_msg) == _Z_RES_OK) { + if (_z_network_message_encode(&ztm->_common._wbuf, n_msg) == _Z_RES_OK) { // Write the eth header - _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_link, &ztm->_wbuf), - _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_common._link, &ztm->_common._wbuf), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Send the wbuf on the socket - _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_common._link, &ztm->_common._wbuf), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Mark the session that we have transmitted data - ztm->_transmitted = true; + ztm->_common._transmitted = true; } else { // The message does not fit in the current batch, let's fragment it #if Z_FEATURE_FRAGMENTATION == 1 // Create an expandable wbuf for fragmentation _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); // Encode the message on the expandable wbuf - _Z_CLEAN_RETURN_IF_ERR(_z_network_message_encode(&fbf, n_msg), _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_network_message_encode(&fbf, n_msg), _z_transport_tx_mutex_unlock(&ztm->_common)); // Fragment and send the message bool is_first = true; while (_z_wbuf_len(&fbf) > 0) { @@ -274,20 +276,20 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ } is_first = false; // Reset wbuf - _z_wbuf_reset(&ztm->_wbuf); + _z_wbuf_reset(&ztm->_common._wbuf); // Prepare buff - __unsafe_z_raweth_prepare_header(&ztm->_link, &ztm->_wbuf); + __unsafe_z_raweth_prepare_header(&ztm->_common._link, &ztm->_common._wbuf); // Serialize one fragment - _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_serialize_zenoh_fragment(&ztm->_wbuf, &fbf, reliability, sn), - _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_serialize_zenoh_fragment(&ztm->_common._wbuf, &fbf, reliability, sn), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Write the eth header - _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_link, &ztm->_wbuf), - _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(__unsafe_z_raweth_write_header(&ztm->_common._link, &ztm->_common._wbuf), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Send the wbuf on the socket - _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_link, &ztm->_wbuf), - _z_multicast_tx_mutex_unlock(ztm)); + _Z_CLEAN_RETURN_IF_ERR(_z_raweth_link_send_wbuf(&ztm->_common._link, &ztm->_common._wbuf), + _z_transport_tx_mutex_unlock(&ztm->_common)); // Mark the session that we have transmitted data - ztm->_transmitted = true; + ztm->_common._transmitted = true; } // Clear the expandable buffer _z_wbuf_clear(&fbf); @@ -295,9 +297,7 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_ _Z_INFO("Sending the message required fragmentation feature that is deactivated."); #endif } -#if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_unlock(&ztm->_mutex_tx); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _z_transport_tx_mutex_unlock(&ztm->_common); return ret; } @@ -307,8 +307,8 @@ z_result_t _z_raweth_link_send_t_msg(const _z_link_t *zl, const _z_transport_mes _ZP_UNUSED(t_msg); return _Z_ERR_TRANSPORT_NOT_AVAILABLE; } -z_result_t _z_raweth_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg) { - _ZP_UNUSED(ztm); +z_result_t _z_raweth_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg) { + _ZP_UNUSED(ztc); _ZP_UNUSED(t_msg); return _Z_ERR_TRANSPORT_NOT_AVAILABLE; } diff --git a/src/transport/transport.c b/src/transport/transport.c index 28cc1eb48..2540ec5ac 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -22,13 +22,11 @@ #include "zenoh-pico/link/link.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/transport/multicast/rx.h" -#include "zenoh-pico/transport/multicast/tx.h" #include "zenoh-pico/transport/raweth/rx.h" #include "zenoh-pico/transport/raweth/tx.h" #include "zenoh-pico/transport/transport.h" #include "zenoh-pico/transport/unicast/rx.h" #include "zenoh-pico/transport/unicast/transport.h" -#include "zenoh-pico/transport/unicast/tx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -81,15 +79,19 @@ void _z_transport_free(_z_transport_t **zt) { #if Z_FEATURE_BATCHING == 1 bool _z_transport_start_batching(_z_transport_t *zt) { uint8_t *batch_state = NULL; + size_t *batch_count = NULL; switch (zt->_type) { case _Z_TRANSPORT_UNICAST_TYPE: - batch_state = &zt->_transport._unicast._batch_state; + batch_state = &zt->_transport._unicast._common._batch_state; + batch_count = &zt->_transport._unicast._common._batch_count; break; case _Z_TRANSPORT_MULTICAST_TYPE: - batch_state = &zt->_transport._multicast._batch_state; + batch_state = &zt->_transport._multicast._common._batch_state; + batch_count = &zt->_transport._multicast._common._batch_count; break; case _Z_TRANSPORT_RAWETH_TYPE: - batch_state = &zt->_transport._raweth._batch_state; + batch_state = &zt->_transport._raweth._common._batch_state; + batch_count = &zt->_transport._raweth._common._batch_count; break; default: break; @@ -97,6 +99,7 @@ bool _z_transport_start_batching(_z_transport_t *zt) { if (*batch_state == _Z_BATCHING_ACTIVE) { return false; } + *batch_count = 0; *batch_state = _Z_BATCHING_ACTIVE; return true; } @@ -105,13 +108,13 @@ void _z_transport_stop_batching(_z_transport_t *zt) { uint8_t *batch_state = NULL; switch (zt->_type) { case _Z_TRANSPORT_UNICAST_TYPE: - batch_state = &zt->_transport._unicast._batch_state; + batch_state = &zt->_transport._unicast._common._batch_state; break; case _Z_TRANSPORT_MULTICAST_TYPE: - batch_state = &zt->_transport._multicast._batch_state; + batch_state = &zt->_transport._multicast._common._batch_state; break; case _Z_TRANSPORT_RAWETH_TYPE: - batch_state = &zt->_transport._raweth._batch_state; + batch_state = &zt->_transport._raweth._common._batch_state; break; default: break; diff --git a/src/transport/unicast.c b/src/transport/unicast.c index dca9ae0ea..3c771a126 100644 --- a/src/transport/unicast.c +++ b/src/transport/unicast.c @@ -26,7 +26,6 @@ #include "zenoh-pico/transport/unicast/lease.h" #include "zenoh-pico/transport/unicast/read.h" #include "zenoh-pico/transport/unicast/rx.h" -#include "zenoh-pico/transport/unicast/tx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" diff --git a/src/transport/unicast/lease.c b/src/transport/unicast/lease.c index 1e3da00cd..c4cd362f1 100644 --- a/src/transport/unicast/lease.c +++ b/src/transport/unicast/lease.c @@ -16,8 +16,8 @@ #include "zenoh-pico/session/query.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/transport/unicast/transport.h" -#include "zenoh-pico/transport/unicast/tx.h" #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_UNICAST_TRANSPORT == 1 @@ -26,7 +26,7 @@ z_result_t _zp_unicast_send_keep_alive(_z_transport_unicast_t *ztu) { z_result_t ret = _Z_RES_OK; _z_transport_message_t t_msg = _z_t_msg_make_keep_alive(); - ret = _z_unicast_send_t_msg(ztu, &t_msg); + ret = _z_transport_tx_send_t_msg(&ztu->_common, &t_msg); return ret; } @@ -44,11 +44,11 @@ void *_zp_unicast_lease_task(void *ztu_arg) { _z_transport_unicast_t *ztu = (_z_transport_unicast_t *)ztu_arg; ztu->_received = false; - ztu->_transmitted = false; + ztu->_common._transmitted = false; - int next_lease = (int)ztu->_lease; - int next_keep_alive = (int)(ztu->_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); - while (ztu->_lease_task_running == true) { + int next_lease = (int)ztu->_common._lease; + int next_keep_alive = (int)(ztu->_common._lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); + while (ztu->_common._lease_task_running == true) { // Next lease process if (next_lease <= 0) { // Check if received data @@ -56,27 +56,27 @@ void *_zp_unicast_lease_task(void *ztu_arg) { // Reset the lease parameters ztu->_received = false; } else { - _Z_INFO("Closing session because it has expired after %zums", ztu->_lease); - ztu->_lease_task_running = false; + _Z_INFO("Closing session because it has expired after %zums", ztu->_common._lease); + ztu->_common._lease_task_running = false; _z_unicast_transport_close(ztu, _Z_CLOSE_EXPIRED); break; } - next_lease = (int)ztu->_lease; + next_lease = (int)ztu->_common._lease; } // Next keep alive process if (next_keep_alive <= 0) { // Check if need to send a keep alive - if (ztu->_transmitted == false) { + if (ztu->_common._transmitted == false) { if (_zp_unicast_send_keep_alive(ztu) < 0) { _Z_INFO("Send keep alive failed."); } } // Reset the keep alive parameters - ztu->_transmitted = false; - next_keep_alive = (int)(ztu->_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); + ztu->_common._transmitted = false; + next_keep_alive = (int)(ztu->_common._lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); } // Query timeout process - _z_pending_query_process_timeout(_Z_RC_IN_VAL(ztu->_session)); + _z_pending_query_process_timeout(_Z_RC_IN_VAL(ztu->_common._session)); // Compute the target interval int interval; @@ -101,18 +101,18 @@ void *_zp_unicast_lease_task(void *ztu_arg) { z_result_t _zp_unicast_start_lease_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task) { // Init memory (void)memset(task, 0, sizeof(_z_task_t)); - zt->_transport._unicast._lease_task_running = true; // Init before z_task_init for concurrency issue + zt->_transport._unicast._common._lease_task_running = true; // Init before z_task_init for concurrency issue // Init task if (_z_task_init(task, attr, _zp_unicast_lease_task, &zt->_transport._unicast) != _Z_RES_OK) { return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task - zt->_transport._unicast._lease_task = task; + zt->_transport._unicast._common._lease_task = task; return _Z_RES_OK; } z_result_t _zp_unicast_stop_lease_task(_z_transport_t *zt) { - zt->_transport._unicast._lease_task_running = false; + zt->_transport._unicast._common._lease_task_running = false; return _Z_RES_OK; } #else diff --git a/src/transport/unicast/read.c b/src/transport/unicast/read.c index 738de4c02..ab347251d 100644 --- a/src/transport/unicast/read.c +++ b/src/transport/unicast/read.c @@ -53,38 +53,39 @@ void *_zp_unicast_read_task(void *ztu_arg) { _z_transport_unicast_t *ztu = (_z_transport_unicast_t *)ztu_arg; // Acquire and keep the lock - _z_mutex_lock(&ztu->_mutex_rx); + _z_mutex_lock(&ztu->_common._mutex_rx); // Prepare the buffer - _z_zbuf_reset(&ztu->_zbuf); + _z_zbuf_reset(&ztu->_common._zbuf); - while (ztu->_read_task_running == true) { + while (ztu->_common._read_task_running == true) { // Read bytes from socket to the main buffer size_t to_read = 0; - switch (ztu->_link._cap._flow) { + switch (ztu->_common._link._cap._flow) { case Z_LINK_CAP_FLOW_STREAM: - if (_z_zbuf_len(&ztu->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); - if (_z_zbuf_len(&ztu->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_zbuf_compact(&ztu->_zbuf); + if (_z_zbuf_len(&ztu->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); + if (_z_zbuf_len(&ztu->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_zbuf_compact(&ztu->_common._zbuf); continue; } } // Get stream size - to_read = _z_read_stream_size(&ztu->_zbuf); + to_read = _z_read_stream_size(&ztu->_common._zbuf); // Read data - if (_z_zbuf_len(&ztu->_zbuf) < to_read) { - _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); - if (_z_zbuf_len(&ztu->_zbuf) < to_read) { - _z_zbuf_set_rpos(&ztu->_zbuf, _z_zbuf_get_rpos(&ztu->_zbuf) - _Z_MSG_LEN_ENC_SIZE); - _z_zbuf_compact(&ztu->_zbuf); + if (_z_zbuf_len(&ztu->_common._zbuf) < to_read) { + _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); + if (_z_zbuf_len(&ztu->_common._zbuf) < to_read) { + _z_zbuf_set_rpos(&ztu->_common._zbuf, + _z_zbuf_get_rpos(&ztu->_common._zbuf) - _Z_MSG_LEN_ENC_SIZE); + _z_zbuf_compact(&ztu->_common._zbuf); continue; } } break; case Z_LINK_CAP_FLOW_DATAGRAM: - _z_zbuf_compact(&ztu->_zbuf); - to_read = _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); + _z_zbuf_compact(&ztu->_common._zbuf); + to_read = _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); if (to_read == SIZE_MAX) { continue; } @@ -93,7 +94,7 @@ void *_zp_unicast_read_task(void *ztu_arg) { break; } // Wrap the main buffer for to_read bytes - _z_zbuf_t zbuf = _z_zbuf_view(&ztu->_zbuf, to_read); + _z_zbuf_t zbuf = _z_zbuf_view(&ztu->_common._zbuf, to_read); // Mark the session that we have received data ztu->_received = true; @@ -111,43 +112,43 @@ void *_zp_unicast_read_task(void *ztu_arg) { if (ret != _Z_ERR_CONNECTION_CLOSED) { _Z_ERROR("Connection closed due to message processing error: %d", ret); } - ztu->_read_task_running = false; + ztu->_common._read_task_running = false; continue; } } else { _Z_ERROR("Connection closed due to malformed message: %d", ret); - ztu->_read_task_running = false; + ztu->_common._read_task_running = false; continue; } } // Move the read position of the read buffer - _z_zbuf_set_rpos(&ztu->_zbuf, _z_zbuf_get_rpos(&ztu->_zbuf) + to_read); + _z_zbuf_set_rpos(&ztu->_common._zbuf, _z_zbuf_get_rpos(&ztu->_common._zbuf) + to_read); if (_z_unicast_update_rx_buffer(ztu) != _Z_RES_OK) { _Z_ERROR("Connection closed due to lack of memory to allocate rx buffer"); - ztu->_read_task_running = false; + ztu->_common._read_task_running = false; } } - _z_mutex_unlock(&ztu->_mutex_rx); + _z_mutex_unlock(&ztu->_common._mutex_rx); return NULL; } z_result_t _zp_unicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task) { // Init memory (void)memset(task, 0, sizeof(_z_task_t)); - zt->_transport._unicast._read_task_running = true; // Init before z_task_init for concurrency issue + zt->_transport._unicast._common._read_task_running = true; // Init before z_task_init for concurrency issue // Init task if (_z_task_init(task, attr, _zp_unicast_read_task, &zt->_transport._unicast) != _Z_RES_OK) { - zt->_transport._unicast._read_task_running = false; + zt->_transport._unicast._common._read_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task - zt->_transport._unicast._read_task = task; + zt->_transport._unicast._common._read_task = task; return _Z_RES_OK; } z_result_t _zp_unicast_stop_read_task(_z_transport_t *zt) { - zt->_transport._unicast._read_task_running = false; + zt->_transport._unicast._common._read_task_running = false; return _Z_RES_OK; } diff --git a/src/transport/unicast/rx.c b/src/transport/unicast/rx.c index d109ae513..ca9591bba 100644 --- a/src/transport/unicast/rx.c +++ b/src/transport/unicast/rx.c @@ -32,28 +32,29 @@ z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg) { _Z_DEBUG(">> recv session msg"); z_result_t ret = _Z_RES_OK; - _z_unicast_rx_mutex_lock(ztu); + _z_transport_rx_mutex_lock(&ztu->_common); size_t to_read = 0; do { - switch (ztu->_link._cap._flow) { + switch (ztu->_common._link._cap._flow) { // Stream capable links case Z_LINK_CAP_FLOW_STREAM: - if (_z_zbuf_len(&ztu->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); - if (_z_zbuf_len(&ztu->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { - _z_zbuf_compact(&ztu->_zbuf); + if (_z_zbuf_len(&ztu->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); + if (_z_zbuf_len(&ztu->_common._zbuf) < _Z_MSG_LEN_ENC_SIZE) { + _z_zbuf_compact(&ztu->_common._zbuf); ret = _Z_ERR_TRANSPORT_NOT_ENOUGH_BYTES; continue; } } // Get stream size - to_read = _z_read_stream_size(&ztu->_zbuf); + to_read = _z_read_stream_size(&ztu->_common._zbuf); // Read data - if (_z_zbuf_len(&ztu->_zbuf) < to_read) { - _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); - if (_z_zbuf_len(&ztu->_zbuf) < to_read) { - _z_zbuf_set_rpos(&ztu->_zbuf, _z_zbuf_get_rpos(&ztu->_zbuf) - _Z_MSG_LEN_ENC_SIZE); - _z_zbuf_compact(&ztu->_zbuf); + if (_z_zbuf_len(&ztu->_common._zbuf) < to_read) { + _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); + if (_z_zbuf_len(&ztu->_common._zbuf) < to_read) { + _z_zbuf_set_rpos(&ztu->_common._zbuf, + _z_zbuf_get_rpos(&ztu->_common._zbuf) - _Z_MSG_LEN_ENC_SIZE); + _z_zbuf_compact(&ztu->_common._zbuf); ret = _Z_ERR_TRANSPORT_NOT_ENOUGH_BYTES; continue; } @@ -61,8 +62,8 @@ z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_me break; // Datagram capable links case Z_LINK_CAP_FLOW_DATAGRAM: - _z_zbuf_compact(&ztu->_zbuf); - to_read = _z_link_recv_zbuf(&ztu->_link, &ztu->_zbuf, NULL); + _z_zbuf_compact(&ztu->_common._zbuf); + to_read = _z_link_recv_zbuf(&ztu->_common._link, &ztu->_common._zbuf, NULL); if (to_read == SIZE_MAX) { ret = _Z_ERR_TRANSPORT_RX_FAILED; } @@ -74,14 +75,14 @@ z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_me if (ret == _Z_RES_OK) { _Z_DEBUG(">> \t transport_message_decode"); - ret = _z_transport_message_decode(t_msg, &ztu->_zbuf); + ret = _z_transport_message_decode(t_msg, &ztu->_common._zbuf); // Mark the session that we have received data if (ret == _Z_RES_OK) { ztu->_received = true; } } - _z_unicast_rx_mutex_unlock(ztu); + _z_transport_rx_mutex_unlock(&ztu->_common); return ret; } @@ -99,7 +100,7 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAME_R) == true) { // @TODO: amend once reliability is in place. For the time being only // monotonic SNs are ensured - if (_z_sn_precedes(ztu->_sn_res, ztu->_sn_rx_reliable, t_msg->_body._frame._sn) == true) { + if (_z_sn_precedes(ztu->_common._sn_res, ztu->_sn_rx_reliable, t_msg->_body._frame._sn) == true) { ztu->_sn_rx_reliable = t_msg->_body._frame._sn; } else { #if Z_FEATURE_FRAGMENTATION == 1 @@ -110,7 +111,7 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t break; } } else { - if (_z_sn_precedes(ztu->_sn_res, ztu->_sn_rx_best_effort, t_msg->_body._frame._sn) == true) { + if (_z_sn_precedes(ztu->_common._sn_res, ztu->_sn_rx_best_effort, t_msg->_body._frame._sn) == true) { ztu->_sn_rx_best_effort = t_msg->_body._frame._sn; } else { #if Z_FEATURE_FRAGMENTATION == 1 @@ -127,7 +128,7 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t for (size_t i = 0; i < len; i++) { _z_network_message_t *zm = _z_network_message_vec_get(&t_msg->_body._frame._messages, i); zm->_reliability = _z_t_msg_get_reliability(t_msg); - _z_handle_network_message(ztu->_session, zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); + _z_handle_network_message(ztu->_common._session, zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); } break; @@ -190,7 +191,7 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t ret = _z_network_message_decode(&zm, &zbf); zm._reliability = _z_t_msg_get_reliability(t_msg); if (ret == _Z_RES_OK) { - _z_handle_network_message(ztu->_session, &zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); + _z_handle_network_message(ztu->_common._session, &zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); } else { _Z_INFO("Failed to decode defragmented message"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; @@ -239,21 +240,21 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t z_result_t _z_unicast_update_rx_buffer(_z_transport_unicast_t *ztu) { // Check if user or defragment buffer took ownership of buffer - if (_z_zbuf_get_ref_count(&ztu->_zbuf) != 1) { + if (_z_zbuf_get_ref_count(&ztu->_common._zbuf) != 1) { // Allocate a new buffer - size_t buff_capacity = _z_zbuf_capacity(&ztu->_zbuf); + size_t buff_capacity = _z_zbuf_capacity(&ztu->_common._zbuf); _z_zbuf_t new_zbuf = _z_zbuf_make(buff_capacity); if (_z_zbuf_capacity(&new_zbuf) != buff_capacity) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } // Recopy leftover bytes - size_t leftovers = _z_zbuf_len(&ztu->_zbuf); + size_t leftovers = _z_zbuf_len(&ztu->_common._zbuf); if (leftovers > 0) { - _z_zbuf_copy_bytes(&new_zbuf, &ztu->_zbuf); + _z_zbuf_copy_bytes(&new_zbuf, &ztu->_common._zbuf); } // Drop buffer & update - _z_zbuf_clear(&ztu->_zbuf); - ztu->_zbuf = new_zbuf; + _z_zbuf_clear(&ztu->_common._zbuf); + ztu->_common._zbuf = new_zbuf; } return _Z_RES_OK; } diff --git a/src/transport/unicast/transport.c b/src/transport/unicast/transport.c index 99357c1ba..fe48e3f24 100644 --- a/src/transport/unicast/transport.c +++ b/src/transport/unicast/transport.c @@ -25,7 +25,6 @@ #include "zenoh-pico/transport/unicast/lease.h" #include "zenoh-pico/transport/unicast/read.h" #include "zenoh-pico/transport/unicast/rx.h" -#include "zenoh-pico/transport/unicast/tx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -40,17 +39,17 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, // Initialize batching data #if Z_FEATURE_BATCHING == 1 - ztu->_batch_state = _Z_BATCHING_IDLE; - ztu->_batch = _z_network_message_vec_make(0); + ztu->_common._batch_state = _Z_BATCHING_IDLE; + ztu->_common._batch_count = 0; #endif #if Z_FEATURE_MULTI_THREAD == 1 // Initialize the mutexes - ret = _z_mutex_init(&ztu->_mutex_tx); + ret = _z_mutex_init(&ztu->_common._mutex_tx); if (ret == _Z_RES_OK) { - ret = _z_mutex_init(&ztu->_mutex_rx); + ret = _z_mutex_init(&ztu->_common._mutex_rx); if (ret != _Z_RES_OK) { - _z_mutex_drop(&ztu->_mutex_tx); + _z_mutex_drop(&ztu->_common._mutex_tx); } } #endif // Z_FEATURE_MULTI_THREAD == 1 @@ -62,21 +61,22 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, size_t zbuf_size = param->_batch_size; // Initialize tx rx buffers - ztu->_wbuf = _z_wbuf_make(wbuf_size, false); - ztu->_zbuf = _z_zbuf_make(zbuf_size); + ztu->_common._wbuf = _z_wbuf_make(wbuf_size, false); + ztu->_common._zbuf = _z_zbuf_make(zbuf_size); // Clean up the buffers if one of them failed to be allocated - if ((_z_wbuf_capacity(&ztu->_wbuf) != wbuf_size) || (_z_zbuf_capacity(&ztu->_zbuf) != zbuf_size)) { + if ((_z_wbuf_capacity(&ztu->_common._wbuf) != wbuf_size) || + (_z_zbuf_capacity(&ztu->_common._zbuf) != zbuf_size)) { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; _Z_ERROR("Not enough memory to allocate transport tx rx buffers!"); #if Z_FEATURE_MULTI_THREAD == 1 - _z_mutex_drop(&ztu->_mutex_tx); - _z_mutex_drop(&ztu->_mutex_rx); + _z_mutex_drop(&ztu->_common._mutex_tx); + _z_mutex_drop(&ztu->_common._mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 - _z_wbuf_clear(&ztu->_wbuf); - _z_zbuf_clear(&ztu->_zbuf); + _z_wbuf_clear(&ztu->_common._wbuf); + _z_zbuf_clear(&ztu->_common._zbuf); } #if Z_FEATURE_FRAGMENTATION == 1 @@ -90,34 +90,34 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, if (ret == _Z_RES_OK) { // Set default SN resolution - ztu->_sn_res = _z_sn_max(param->_seq_num_res); + ztu->_common._sn_res = _z_sn_max(param->_seq_num_res); // The initial SN at TX side - ztu->_sn_tx_reliable = param->_initial_sn_tx; - ztu->_sn_tx_best_effort = param->_initial_sn_tx; + ztu->_common._sn_tx_reliable = param->_initial_sn_tx; + ztu->_common._sn_tx_best_effort = param->_initial_sn_tx; // The initial SN at RX side - _z_zint_t initial_sn_rx = _z_sn_decrement(ztu->_sn_res, param->_initial_sn_rx); + _z_zint_t initial_sn_rx = _z_sn_decrement(ztu->_common._sn_res, param->_initial_sn_rx); ztu->_sn_rx_reliable = initial_sn_rx; ztu->_sn_rx_best_effort = initial_sn_rx; #if Z_FEATURE_MULTI_THREAD == 1 // Tasks - ztu->_read_task_running = false; - ztu->_read_task = NULL; - ztu->_lease_task_running = false; - ztu->_lease_task = NULL; + ztu->_common._read_task_running = false; + ztu->_common._read_task = NULL; + ztu->_common._lease_task_running = false; + ztu->_common._lease_task = NULL; #endif // Z_FEATURE_MULTI_THREAD == 1 // Notifiers ztu->_received = 0; - ztu->_transmitted = 0; + ztu->_common._transmitted = 0; // Transport lease - ztu->_lease = param->_lease; + ztu->_common._lease = param->_lease; // Transport link for unicast - ztu->_link = *zl; + ztu->_common._link = *zl; // Remote peer PID ztu->_remote_zid = param->_remote_zid; @@ -309,7 +309,7 @@ z_result_t _z_unicast_send_close(_z_transport_unicast_t *ztu, uint8_t reason, bo z_result_t ret = _Z_RES_OK; // Send and clear message _z_transport_message_t cm = _z_t_msg_make_close(reason, link_only); - ret = _z_unicast_send_t_msg(ztu, &cm); + ret = _z_transport_tx_send_t_msg(&ztu->_common, &cm); _z_t_msg_clear(&cm); return ret; } @@ -322,27 +322,23 @@ void _z_unicast_transport_clear(_z_transport_t *zt) { _z_transport_unicast_t *ztu = &zt->_transport._unicast; #if Z_FEATURE_MULTI_THREAD == 1 // Clean up tasks - if (ztu->_read_task != NULL) { - _z_task_join(ztu->_read_task); - _z_task_free(&ztu->_read_task); + if (ztu->_common._read_task != NULL) { + _z_task_join(ztu->_common._read_task); + _z_task_free(&ztu->_common._read_task); } - if (ztu->_lease_task != NULL) { - _z_task_join(ztu->_lease_task); - _z_task_free(&ztu->_lease_task); + if (ztu->_common._lease_task != NULL) { + _z_task_join(ztu->_common._lease_task); + _z_task_free(&ztu->_common._lease_task); } // Clean up the mutexes - _z_mutex_drop(&ztu->_mutex_tx); - _z_mutex_drop(&ztu->_mutex_rx); + _z_mutex_drop(&ztu->_common._mutex_tx); + _z_mutex_drop(&ztu->_common._mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 -#if Z_FEATURE_BATCHING == 1 - _z_network_message_vec_clear(&ztu->_batch); -#endif - // Clean up the buffers - _z_wbuf_clear(&ztu->_wbuf); - _z_zbuf_clear(&ztu->_zbuf); + _z_wbuf_clear(&ztu->_common._wbuf); + _z_zbuf_clear(&ztu->_common._zbuf); #if Z_FEATURE_FRAGMENTATION == 1 _z_wbuf_clear(&ztu->_dbuf_reliable); _z_wbuf_clear(&ztu->_dbuf_best_effort); @@ -350,7 +346,7 @@ void _z_unicast_transport_clear(_z_transport_t *zt) { // Clean up PIDs ztu->_remote_zid = _z_id_empty(); - _z_link_clear(&ztu->_link); + _z_link_clear(&ztu->_common._link); } #else diff --git a/src/transport/unicast/tx.c b/src/transport/unicast/tx.c deleted file mode 100644 index 78bc04f86..000000000 --- a/src/transport/unicast/tx.c +++ /dev/null @@ -1,289 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#include "zenoh-pico/transport/common/tx.h" - -#include - -#include "zenoh-pico/config.h" -#include "zenoh-pico/protocol/codec/network.h" -#include "zenoh-pico/protocol/codec/transport.h" -#include "zenoh-pico/protocol/iobuf.h" -#include "zenoh-pico/transport/unicast/transport.h" -#include "zenoh-pico/transport/unicast/tx.h" -#include "zenoh-pico/transport/utils.h" -#include "zenoh-pico/utils/logging.h" - -#if Z_FEATURE_UNICAST_TRANSPORT == 1 - -/** - * This function is unsafe because it operates in potentially concurrent data. - * Make sure that the following mutexes are locked before calling this function: - * - ztu->_mutex_inner - */ -static _z_zint_t __unsafe_z_unicast_get_sn(_z_transport_unicast_t *ztu, z_reliability_t reliability) { - _z_zint_t sn; - if (reliability == Z_RELIABILITY_RELIABLE) { - sn = ztu->_sn_tx_reliable; - ztu->_sn_tx_reliable = _z_sn_increment(ztu->_sn_res, ztu->_sn_tx_reliable); - } else { - sn = ztu->_sn_tx_best_effort; - ztu->_sn_tx_best_effort = _z_sn_increment(ztu->_sn_res, ztu->_sn_tx_best_effort); - } - return sn; -} - -#if Z_FEATURE_FRAGMENTATION == 1 -static z_result_t __unsafe_z_unicast_send_fragment(_z_transport_unicast_t *ztu, _z_wbuf_t *fbf, - const _z_network_message_t *n_msg, z_reliability_t reliability, - _z_zint_t first_sn) { - bool is_first = true; - _z_zint_t sn = first_sn; - // Encode message on temp buffer - _Z_RETURN_IF_ERR(_z_network_message_encode(fbf, n_msg)); - // Fragment message - while (_z_wbuf_len(fbf) > 0) { - // Get fragment sequence number - if (!is_first) { - sn = __unsafe_z_unicast_get_sn(ztu, reliability); - } - is_first = false; - // Serialize fragment - __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - z_result_t ret = __unsafe_z_serialize_zenoh_fragment(&ztu->_wbuf, fbf, reliability, sn); - if (ret != _Z_RES_OK) { - _Z_ERROR("Fragment serialization failed with err %d", ret); - return ret; - } - // Send fragment - __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztu->_link, &ztu->_wbuf)); - ztu->_transmitted = true; // Tell session we transmitted data - } - return _Z_RES_OK; -} -#else -static z_result_t __unsafe_z_unicast_send_fragment(_z_transport_unicast_t *ztu, _z_wbuf_t *fbf, - const _z_network_message_t *n_msg, z_reliability_t reliability, - _z_zint_t first_sn) { - _ZP_UNUSED(ztu); - _ZP_UNUSED(fbf); - _ZP_UNUSED(n_msg); - _ZP_UNUSED(reliability); - _ZP_UNUSED(first_sn); - _Z_INFO("Sending the message required fragmentation feature that is deactivated."); - return _Z_RES_OK; -} -#endif - -static z_result_t __unsafe_z_unicast_message_send(_z_transport_unicast_t *ztu, const _z_network_message_t *n_msg, - z_reliability_t reliability) { - _Z_DEBUG("Send network message"); - // Encode frame header - __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - _z_zint_t sn = __unsafe_z_unicast_get_sn(ztu, reliability); - _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); - _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztu->_wbuf, &t_msg)); - // Encode the network message - z_result_t ret = _z_network_message_encode(&ztu->_wbuf, n_msg); - // The message does not fit in the current batch, let's fragment it - if (ret != _Z_RES_OK) { - // Create an expandable wbuf for fragmentation - _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); - // Send message as fragments - ret = __unsafe_z_unicast_send_fragment(ztu, &fbf, n_msg, reliability, sn); - // Clear the buffer as it's no longer required - _z_wbuf_clear(&fbf); - return ret; - } - // Send network message - __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztu->_link, &ztu->_wbuf)); - ztu->_transmitted = true; // Tell session we transmitted data - return _Z_RES_OK; -} - -#if Z_FEATURE_BATCHING == 1 -static z_result_t __unsafe_z_unicast_message_batch(_z_transport_unicast_t *ztu, const _z_network_message_t *n_msg) { - _Z_DEBUG("Batching network message"); - // Copy network message - _z_network_message_t *batch_msg = z_malloc(sizeof(_z_network_message_t)); - if (batch_msg == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - if (_z_n_msg_copy(batch_msg, n_msg) != _Z_RES_OK) { - z_free(batch_msg); - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - _z_network_message_vec_append(&ztu->_batch, batch_msg); - return _Z_RES_OK; -} - -static z_result_t __unsafe_unicast_batch_send(_z_transport_unicast_t *ztu, z_reliability_t reliability) { - z_result_t ret = _Z_RES_OK; - // Get network message number - size_t msg_nb = _z_network_message_vec_len(&ztu->_batch); - size_t msg_idx = 0; - size_t curr_msg_nb = 0; - if (msg_nb == 0) { - return _Z_RES_OK; - } - // Encode the frame header - __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - _z_zint_t sn = __unsafe_z_unicast_get_sn(ztu, reliability); - _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); - _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztu->_wbuf, &t_msg)); - size_t curr_wpos = _z_wbuf_get_wpos(&ztu->_wbuf); - // Process batch - while (msg_idx < msg_nb) { - // Encode a network message - _z_network_message_t *n_msg = _z_network_message_vec_get(&ztu->_batch, msg_idx); - assert(n_msg != NULL); - if (_z_network_message_encode(&ztu->_wbuf, n_msg) != _Z_RES_OK) { - // Remove partially encoded data - _z_wbuf_set_wpos(&ztu->_wbuf, curr_wpos); - // Handle case where one message is too big to fit in frame - if (curr_msg_nb == 0) { - _Z_INFO("Batch sending interrupted by a message needing to be fragmented."); - // Create an expandable wbuf for fragmentation - _z_wbuf_t fbf = _z_wbuf_make(_Z_FRAG_BUFF_BASE_SIZE, true); - // Send message as fragments - ret = __unsafe_z_unicast_send_fragment(ztu, &fbf, n_msg, reliability, sn); - // Clear the buffer as it's no longer required - _z_wbuf_clear(&fbf); - if (ret != _Z_RES_OK) { - _Z_ERROR("Send fragmented message failed with err %d.", ret); - } - // Message is sent or skipped - msg_idx++; - } else { // Frame has messages but is full - _Z_INFO("Sending batch in multiple frames because it is too big for one"); - // Send frame - __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztu->_link, &ztu->_wbuf)); - ztu->_transmitted = true; - curr_msg_nb = 0; - } - // Reset frame - __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - sn = __unsafe_z_unicast_get_sn(ztu, reliability); - t_msg = _z_t_msg_make_frame_header(sn, reliability); - _Z_RETURN_IF_ERR(_z_transport_message_encode(&ztu->_wbuf, &t_msg)); - } else { - curr_wpos = _z_wbuf_get_wpos(&ztu->_wbuf); - msg_idx++; - curr_msg_nb++; - } - } - // Send frame - __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - _Z_RETURN_IF_ERR(_z_link_send_wbuf(&ztu->_link, &ztu->_wbuf)); - ztu->_transmitted = true; // Tell session we transmitted data - return ret; -} -#endif - -z_result_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_message_t *t_msg) { - z_result_t ret = _Z_RES_OK; - _Z_DEBUG("Send session message"); - _z_unicast_tx_mutex_lock(ztu, true); - - // Encode transport message - __unsafe_z_prepare_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - ret = _z_transport_message_encode(&ztu->_wbuf, t_msg); - if (ret == _Z_RES_OK) { - // Send message - __unsafe_z_finalize_wbuf(&ztu->_wbuf, ztu->_link._cap._flow); - ret = _z_link_send_wbuf(&ztu->_link, &ztu->_wbuf); - if (ret == _Z_RES_OK) { - ztu->_transmitted = true; // Tell session we transmitted data - } - } - _z_unicast_tx_mutex_unlock(ztu); - return ret; -} - -z_result_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl) { - z_result_t ret = _Z_RES_OK; - _z_transport_unicast_t *ztu = &zn->_tp._transport._unicast; - - // Acquire the lock and drop the message if needed - ret = _z_unicast_tx_mutex_lock(ztu, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); - if (ret != _Z_RES_OK) { - _Z_INFO("Dropping zenoh message because of congestion control"); - return ret; - } - // Process batching -#if Z_FEATURE_BATCHING == 1 - if (ztu->_batch_state == _Z_BATCHING_ACTIVE) { - ret = __unsafe_z_unicast_message_batch(ztu, n_msg); - } else { - ret = __unsafe_z_unicast_message_send(ztu, n_msg, reliability); - } -#else - ret = __unsafe_z_unicast_message_send(ztu, n_msg, reliability); -#endif - _z_unicast_tx_mutex_unlock(ztu); - return ret; -} - -z_result_t _z_unicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { -#if Z_FEATURE_BATCHING == 1 - _Z_DEBUG("Send network batch"); - _z_transport_unicast_t *ztu = &zn->_tp._transport._unicast; - // Acquire the lock and drop the message if needed - z_result_t ret = _z_unicast_tx_mutex_lock(ztu, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK); - if (ret != _Z_RES_OK) { - _Z_INFO("Dropping zenoh batch because of congestion control"); - return ret; - } - // Send batch - ret = __unsafe_unicast_batch_send(ztu, reliability); - // Clean up - _z_network_message_vec_clear(&ztu->_batch); - _z_unicast_tx_mutex_unlock(ztu); - return ret; -#else - _ZP_UNUSED(zn); - _ZP_UNUSED(reliability); - _ZP_UNUSED(cong_ctrl); - _Z_ERROR("Tried to send batch but batching feature is deactivated."); - return _Z_ERR_TRANSPORT_TX_FAILED; -#endif -} - -#else -z_result_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_message_t *t_msg) { - _ZP_UNUSED(ztu); - _ZP_UNUSED(t_msg); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} - -z_result_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, - z_congestion_control_t cong_ctrl) { - _ZP_UNUSED(zn); - _ZP_UNUSED(n_msg); - _ZP_UNUSED(reliability); - _ZP_UNUSED(cong_ctrl); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} - -z_result_t _z_unicast_send_n_batch(_z_session_t *zn, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { - _ZP_UNUSED(zn); - _ZP_UNUSED(reliability); - _ZP_UNUSED(cong_ctrl); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} -#endif // Z_FEATURE_UNICAST_TRANSPORT == 1 From de430cbf07037f2b741b4828ce23cefcbf6712ea Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Fri, 8 Nov 2024 17:51:49 +0100 Subject: [PATCH 10/17] Improve sub frame decode performance (#777) * feat: alias string decode * fix: alias keyexpr only on rx buffer * feat: add svec release function * feat: remove duplicate message clear * feat: remove unused subscription function * fix: missing const qualifier * feat: remove encoding null value * feat: improve sample create perf * feat: init string in encoding move * feat: replace rc sub list with sub info vec * feat: check before encoding clear * feat: avoid rechecking msg reliability * feat: add sub memoization * fix: alias cache if suffix * feat: move z_bytes instead of copy * feat: add svec move function * feat: add memoization config token * feat: add vec alias function * feat: switch sub cache to session level * feat: add svec expand function * fix: missing function args * fix: don't use _z_noop_move in svec * feat: svec ops return error instead of bool * feat: svec functions * feat: add use elem f in svec * feat: switch frame nmsg to svec * feat: add config value for initial frame size evaluation * feat: remove superfluous init * fix: rename cache token * fix: remove superfluous initialization --- CMakeLists.txt | 1 + include/zenoh-pico/collections/bytes.h | 7 +- include/zenoh-pico/collections/element.h | 5 +- include/zenoh-pico/collections/string.h | 8 +- include/zenoh-pico/collections/vec.h | 43 +++-- include/zenoh-pico/config.h | 6 + include/zenoh-pico/config.h.in | 6 + include/zenoh-pico/link/endpoint.h | 2 +- include/zenoh-pico/net/reply.h | 4 +- include/zenoh-pico/net/sample.h | 6 +- include/zenoh-pico/net/session.h | 4 + include/zenoh-pico/protocol/codec/transport.h | 1 - include/zenoh-pico/protocol/core.h | 2 +- .../zenoh-pico/protocol/definitions/network.h | 4 +- .../protocol/definitions/transport.h | 4 +- include/zenoh-pico/protocol/ext.h | 2 +- include/zenoh-pico/protocol/iobuf.h | 2 +- include/zenoh-pico/session/resource.h | 2 +- include/zenoh-pico/session/session.h | 20 +- include/zenoh-pico/session/subscription.h | 36 +++- include/zenoh-pico/system/link/raweth.h | 5 +- include/zenoh-pico/transport/transport.h | 4 +- src/api/api.c | 10 +- src/collections/bytes.c | 14 +- src/collections/vec.c | 106 +++++----- src/net/encoding.c | 8 +- src/net/sample.c | 36 ++-- src/protocol/codec.c | 12 +- src/protocol/codec/message.c | 6 - src/protocol/codec/network.c | 6 - src/protocol/codec/transport.c | 73 ++++--- src/protocol/core.c | 2 +- src/protocol/definitions/message.c | 1 + src/protocol/definitions/transport.c | 8 +- src/session/interest.c | 2 +- src/session/query.c | 2 +- src/session/queryable.c | 4 +- src/session/resource.c | 18 +- src/session/rx.c | 1 - src/session/subscription.c | 181 +++++++++++------- src/session/utils.c | 6 + src/transport/multicast/rx.c | 17 +- src/transport/unicast/rx.c | 16 +- tests/z_msgcodec_test.c | 46 ++--- 44 files changed, 435 insertions(+), 314 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ab40bf08..b34b73c75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -207,6 +207,7 @@ set(Z_FEATURE_TCP_NODELAY 1 CACHE STRING "Toggle TCP_NODELAY") set(Z_FEATURE_LOCAL_SUBSCRIBER 0 CACHE STRING "Toggle local subscriptions") set(Z_FEATURE_PUBLISHER_SESSION_CHECK 1 CACHE STRING "Toggle publisher session check") set(Z_FEATURE_BATCHING 1 CACHE STRING "Toggle batching") +set(Z_FEATURE_RX_CACHE 0 CACHE STRING "Toggle RX_CACHE") add_compile_definitions("Z_BUILD_DEBUG=$") message(STATUS "Building with feature confing:\n\ diff --git a/include/zenoh-pico/collections/bytes.h b/include/zenoh-pico/collections/bytes.h index 2496520c1..9f3ad16ef 100644 --- a/include/zenoh-pico/collections/bytes.h +++ b/include/zenoh-pico/collections/bytes.h @@ -27,11 +27,8 @@ inline size_t _z_arc_slice_size(const _z_arc_slice_t *s) { (void)s; return sizeof(_z_arc_slice_t); } -static inline void _z_arc_slice_elem_move(void *dst, void *src) { - _z_arc_slice_move((_z_arc_slice_t *)dst, (_z_arc_slice_t *)src); -} -_Z_ELEM_DEFINE(_z_arc_slice, _z_arc_slice_t, _z_arc_slice_size, _z_arc_slice_drop, _z_arc_slice_copy) -_Z_SVEC_DEFINE(_z_arc_slice, _z_arc_slice_t) +_Z_ELEM_DEFINE(_z_arc_slice, _z_arc_slice_t, _z_arc_slice_size, _z_arc_slice_drop, _z_arc_slice_copy, _z_arc_slice_move) +_Z_SVEC_DEFINE(_z_arc_slice, _z_arc_slice_t, true) /*-------- Bytes --------*/ /** diff --git a/include/zenoh-pico/collections/element.h b/include/zenoh-pico/collections/element.h index ef5178ad1..7a435abb3 100644 --- a/include/zenoh-pico/collections/element.h +++ b/include/zenoh-pico/collections/element.h @@ -30,7 +30,7 @@ typedef void (*z_element_move_f)(void *dst, void *src); typedef void *(*z_element_clone_f)(const void *e); typedef bool (*z_element_eq_f)(const void *left, const void *right); -#define _Z_ELEM_DEFINE(name, type, elem_size_f, elem_clear_f, elem_copy_f) \ +#define _Z_ELEM_DEFINE(name, type, elem_size_f, elem_clear_f, elem_copy_f, elem_move_f) \ typedef bool (*name##_eq_f)(const type *left, const type *right); \ static inline void name##_elem_clear(void *e) { elem_clear_f((type *)e); } \ static inline void name##_elem_free(void **e) { \ @@ -41,6 +41,7 @@ typedef bool (*z_element_eq_f)(const void *left, const void *right); *e = NULL; \ } \ } \ + static inline void name##_elem_move(void *dst, void *src) { elem_move_f((type *)dst, (type *)src); } \ static inline void name##_elem_copy(void *dst, const void *src) { elem_copy_f((type *)dst, (type *)src); } \ static inline void *name##_elem_clone(const void *src) { \ type *dst = (type *)z_malloc(elem_size_f((type *)src)); \ @@ -72,6 +73,6 @@ static inline void _z_noop_move(void *dst, void *src) { _ZP_UNUSED(src); } -_Z_ELEM_DEFINE(_z_noop, _z_noop_t, _z_noop_size, _z_noop_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_noop, _z_noop_t, _z_noop_size, _z_noop_clear, _z_noop_copy, _z_noop_move) #endif /* ZENOH_PICO_COLLECTIONS_ELEMENT_H */ diff --git a/include/zenoh-pico/collections/string.h b/include/zenoh-pico/collections/string.h index 167604774..37c1a218b 100644 --- a/include/zenoh-pico/collections/string.h +++ b/include/zenoh-pico/collections/string.h @@ -33,7 +33,7 @@ bool _z_str_eq(const char *left, const char *right); size_t _z_str_size(const char *src); void _z_str_copy(char *dst, const char *src); void _z_str_n_copy(char *dst, const char *src, size_t size); -_Z_ELEM_DEFINE(_z_str, char, _z_str_size, _z_noop_clear, _z_str_copy) +_Z_ELEM_DEFINE(_z_str, char, _z_str_size, _z_noop_clear, _z_str_copy, _z_noop_move) _Z_VEC_DEFINE(_z_str, char) _Z_LIST_DEFINE(_z_str, char) @@ -97,10 +97,8 @@ bool _z_string_equals(const _z_string_t *left, const _z_string_t *right); _z_string_t _z_string_convert_bytes(const _z_slice_t *bs); _z_string_t _z_string_preallocate(const size_t len); -_Z_ELEM_DEFINE(_z_string, _z_string_t, _z_string_len, _z_string_clear, _z_string_copy) - -static inline void _z_string_elem_move(void *dst, void *src) { _z_string_move((_z_string_t *)dst, (_z_string_t *)src); } -_Z_SVEC_DEFINE(_z_string, _z_string_t) +_Z_ELEM_DEFINE(_z_string, _z_string_t, _z_string_len, _z_string_clear, _z_string_copy, _z_string_move) +_Z_SVEC_DEFINE(_z_string, _z_string_t, true) _Z_LIST_DEFINE(_z_string, _z_string_t) _Z_INT_MAP_DEFINE(_z_string, _z_string_t) diff --git a/include/zenoh-pico/collections/vec.h b/include/zenoh-pico/collections/vec.h index 36af17dcc..3d5e48605 100644 --- a/include/zenoh-pico/collections/vec.h +++ b/include/zenoh-pico/collections/vec.h @@ -30,9 +30,10 @@ typedef struct { } _z_vec_t; static inline _z_vec_t _z_vec_null(void) { return (_z_vec_t){0}; } +static inline _z_vec_t _z_vec_alias(const _z_vec_t *src) { return *src; } _z_vec_t _z_vec_make(size_t capacity); void _z_vec_copy(_z_vec_t *dst, const _z_vec_t *src, z_element_clone_f f); -void _z_vec_steal(_z_vec_t *dst, _z_vec_t *src); +void _z_vec_move(_z_vec_t *dst, _z_vec_t *src); size_t _z_vec_len(const _z_vec_t *v); bool _z_vec_is_empty(const _z_vec_t *v); @@ -61,7 +62,8 @@ void _z_vec_release(_z_vec_t *v); static inline void name##_vec_copy(name##_vec_t *dst, const name##_vec_t *src) { \ _z_vec_copy(dst, src, name##_elem_clone); \ } \ - static inline void name##_vec_steal(name##_vec_t *dst, name##_vec_t *src) { _z_vec_steal(dst, src); } \ + static inline name##_vec_t name##_vec_alias(const name##_vec_t *v) { return _z_vec_alias(v); } \ + static inline void name##_vec_move(name##_vec_t *dst, name##_vec_t *src) { _z_vec_move(dst, src); } \ static inline void name##_vec_reset(name##_vec_t *v) { _z_vec_reset(v, name##_elem_free); } \ static inline void name##_vec_clear(name##_vec_t *v) { _z_vec_clear(v, name##_elem_free); } \ static inline void name##_vec_free(name##_vec_t **v) { _z_vec_free(v, name##_elem_free); } \ @@ -77,44 +79,63 @@ typedef struct { void *_val; } _z_svec_t; +static inline _z_svec_t _z_svec_null(void) { return (_z_svec_t){0}; } +static inline _z_svec_t _z_svec_alias(const _z_svec_t *src) { return *src; } +void _z_svec_init(_z_svec_t *dst, size_t element_size); _z_svec_t _z_svec_make(size_t capacity, size_t element_size); -bool _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size); +z_result_t _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size, + bool use_elem_f); +void _z_svec_move(_z_svec_t *dst, _z_svec_t *src); size_t _z_svec_len(const _z_svec_t *v); bool _z_svec_is_empty(const _z_svec_t *v); -bool _z_svec_append(_z_svec_t *v, const void *e, z_element_move_f m, size_t element_size); +z_result_t _z_svec_expand(_z_svec_t *v, z_element_move_f move, size_t element_size, bool use_elem_f); +z_result_t _z_svec_append(_z_svec_t *v, const void *e, z_element_move_f m, size_t element_size, bool use_elem_f); void *_z_svec_get(const _z_svec_t *v, size_t pos, size_t element_size); +void *_z_svec_get_mut(_z_svec_t *v, size_t i, size_t element_size); void _z_svec_set(_z_svec_t *sv, size_t pos, void *e, z_element_clear_f f, size_t element_size); -void _z_svec_remove(_z_svec_t *sv, size_t pos, z_element_clear_f f, z_element_move_f m, size_t element_size); +void _z_svec_remove(_z_svec_t *sv, size_t pos, z_element_clear_f f, z_element_move_f m, size_t element_size, + bool use_elem_f); void _z_svec_reset(_z_svec_t *v, z_element_clear_f f, size_t element_size); void _z_svec_clear(_z_svec_t *v, z_element_clear_f f, size_t element_size); void _z_svec_free(_z_svec_t **v, z_element_clear_f f, size_t element_size); void _z_svec_release(_z_svec_t *v); -#define _Z_SVEC_DEFINE(name, type) \ +#define _Z_SVEC_DEFINE(name, type, use_elem_f) \ typedef _z_svec_t name##_svec_t; \ + static inline name##_svec_t name##_svec_null(void) { return _z_svec_null(); } \ static inline name##_svec_t name##_svec_make(size_t capacity) { return _z_svec_make(capacity, sizeof(type)); } \ + static inline void name##_svec_init(name##_svec_t *v) { _z_svec_init(v, sizeof(type)); } \ static inline size_t name##_svec_len(const name##_svec_t *v) { return _z_svec_len(v); } \ static inline bool name##_svec_is_empty(const name##_svec_t *v) { return _z_svec_is_empty(v); } \ - static inline bool name##_svec_append(name##_svec_t *v, type *e) { \ - return _z_svec_append(v, e, name##_elem_move, sizeof(type)); \ + static inline z_result_t name##_svec_expand(name##_svec_t *v) { \ + return _z_svec_expand(v, name##_elem_move, sizeof(type), use_elem_f); \ + } \ + static inline z_result_t name##_svec_append(name##_svec_t *v, const type *e) { \ + return _z_svec_append(v, e, name##_elem_move, sizeof(type), use_elem_f); \ } \ static inline type *name##_svec_get(const name##_svec_t *v, size_t pos) { \ return (type *)_z_svec_get(v, pos, sizeof(type)); \ } \ + static inline type *name##_svec_get_mut(name##_svec_t *v, size_t pos) { \ + return (type *)_z_svec_get_mut(v, pos, sizeof(type)); \ + } \ static inline void name##_svec_set(name##_svec_t *v, size_t pos, type *e) { \ _z_svec_set(v, pos, e, name##_elem_clear, sizeof(type)); \ } \ static inline void name##_svec_remove(name##_svec_t *v, size_t pos) { \ - _z_svec_remove(v, pos, name##_elem_clear, name##_elem_move, sizeof(type)); \ + _z_svec_remove(v, pos, name##_elem_clear, name##_elem_move, sizeof(type), use_elem_f); \ } \ - static inline bool name##_svec_copy(name##_svec_t *dst, const name##_svec_t *src) { \ - return _z_svec_copy(dst, src, name##_elem_copy, sizeof(type)); \ + static inline z_result_t name##_svec_copy(name##_svec_t *dst, const name##_svec_t *src) { \ + return _z_svec_copy(dst, src, name##_elem_copy, sizeof(type), use_elem_f); \ } \ + static inline name##_svec_t name##_svec_alias(const name##_svec_t *v) { return _z_svec_alias(v); } \ + static inline void name##_svec_move(name##_svec_t *dst, name##_svec_t *src) { _z_svec_move(dst, src); } \ static inline void name##_svec_reset(name##_svec_t *v) { _z_svec_reset(v, name##_elem_clear, sizeof(type)); } \ static inline void name##_svec_clear(name##_svec_t *v) { _z_svec_clear(v, name##_elem_clear, sizeof(type)); } \ + static inline void name##_svec_release(name##_svec_t *v) { _z_svec_release(v); } \ static inline void name##_svec_free(name##_svec_t **v) { _z_svec_free(v, name##_elem_clear, sizeof(type)); } #endif /* ZENOH_PICO_COLLECTIONS_VECTOR_H */ diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index e3a76d963..2449535fe 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -45,6 +45,7 @@ #define Z_FEATURE_LOCAL_SUBSCRIBER 0 #define Z_FEATURE_PUBLISHER_SESSION_CHECK 1 #define Z_FEATURE_BATCHING 1 +#define Z_FEATURE_RX_CACHE 0 // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ @@ -176,6 +177,11 @@ */ #define Z_GET_TIMEOUT_DEFAULT 10000 +/** + * Average size of a frame message (bytes). Used to evaluate initial decoding frame size. + */ +#define Z_CONFIG_FRAME_AVG_MSG_SIZE 32 + /** * Default "nop" instruction */ diff --git a/include/zenoh-pico/config.h.in b/include/zenoh-pico/config.h.in index a8738d6a4..d6f43e3d3 100644 --- a/include/zenoh-pico/config.h.in +++ b/include/zenoh-pico/config.h.in @@ -45,6 +45,7 @@ #define Z_FEATURE_LOCAL_SUBSCRIBER @Z_FEATURE_LOCAL_SUBSCRIBER@ #define Z_FEATURE_PUBLISHER_SESSION_CHECK @Z_FEATURE_PUBLISHER_SESSION_CHECK@ #define Z_FEATURE_BATCHING @Z_FEATURE_BATCHING@ +#define Z_FEATURE_RX_CACHE @Z_FEATURE_RX_CACHE@ // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ @@ -176,6 +177,11 @@ */ #define Z_GET_TIMEOUT_DEFAULT 10000 +/** + * Average size of a frame message (bytes). Used to evaluate initial decoding frame size. + */ +#define Z_CONFIG_FRAME_AVG_MSG_SIZE 32 + /** * Default "nop" instruction */ diff --git a/include/zenoh-pico/link/endpoint.h b/include/zenoh-pico/link/endpoint.h index 4868f4d44..4003608e5 100644 --- a/include/zenoh-pico/link/endpoint.h +++ b/include/zenoh-pico/link/endpoint.h @@ -54,7 +54,7 @@ z_result_t _z_locator_from_string(_z_locator_t *lc, _z_string_t *s); size_t _z_locator_size(_z_locator_t *lc); void _z_locator_clear(_z_locator_t *lc); -_Z_ELEM_DEFINE(_z_locator, _z_locator_t, _z_locator_size, _z_locator_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_locator, _z_locator_t, _z_locator_size, _z_locator_clear, _z_noop_copy, _z_noop_move) /*------------------ Locator array ------------------*/ _Z_ARRAY_DEFINE(_z_locator, _z_locator_t) diff --git a/include/zenoh-pico/net/reply.h b/include/zenoh-pico/net/reply.h index 3e1a1994b..fcc8876c8 100644 --- a/include/zenoh-pico/net/reply.h +++ b/include/zenoh-pico/net/reply.h @@ -67,7 +67,7 @@ static inline _z_reply_data_t _z_reply_data_init(void) { void _z_reply_data_clear(_z_reply_data_t *rd); z_result_t _z_reply_data_copy(_z_reply_data_t *dst, const _z_reply_data_t *src); -_Z_ELEM_DEFINE(_z_reply_data, _z_reply_data_t, _z_noop_size, _z_reply_data_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_reply_data, _z_reply_data_t, _z_noop_size, _z_reply_data_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_reply_data, _z_reply_data_t) /** @@ -102,7 +102,7 @@ typedef struct _z_pending_reply_t { bool _z_pending_reply_eq(const _z_pending_reply_t *one, const _z_pending_reply_t *two); void _z_pending_reply_clear(_z_pending_reply_t *res); -_Z_ELEM_DEFINE(_z_pending_reply, _z_pending_reply_t, _z_noop_size, _z_pending_reply_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_pending_reply, _z_pending_reply_t, _z_noop_size, _z_pending_reply_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_pending_reply, _z_pending_reply_t) #endif /* ZENOH_PICO_REPLY_NETAPI_H */ diff --git a/include/zenoh-pico/net/sample.h b/include/zenoh-pico/net/sample.h index 0b7eeb43f..ab42e6985 100644 --- a/include/zenoh-pico/net/sample.h +++ b/include/zenoh-pico/net/sample.h @@ -59,8 +59,8 @@ void _z_sample_free(_z_sample_t **sample); z_result_t _z_sample_copy(_z_sample_t *dst, const _z_sample_t *src); _z_sample_t _z_sample_duplicate(const _z_sample_t *src); -_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t *payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, - const _z_bytes_t *attachment, z_reliability_t reliability); +void _z_sample_create(_z_sample_t *s, _z_keyexpr_t *key, _z_bytes_t *payload, const _z_timestamp_t *timestamp, + _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, _z_bytes_t *attachment, + z_reliability_t reliability); #endif /* ZENOH_PICO_SAMPLE_NETAPI_H */ diff --git a/include/zenoh-pico/net/session.h b/include/zenoh-pico/net/session.h index 6d7ede3a4..b2bdd8fec 100644 --- a/include/zenoh-pico/net/session.h +++ b/include/zenoh-pico/net/session.h @@ -22,6 +22,7 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/session/session.h" +#include "zenoh-pico/session/subscription.h" #include "zenoh-pico/utils/config.h" /** @@ -52,6 +53,9 @@ typedef struct _z_session_t { #if Z_FEATURE_SUBSCRIPTION == 1 _z_subscription_rc_list_t *_local_subscriptions; _z_subscription_rc_list_t *_remote_subscriptions; +#if Z_FEATURE_RX_CACHE == 1 + _z_subscription_cache_t _subscription_cache; +#endif #endif // Session queryables diff --git a/include/zenoh-pico/protocol/codec/transport.h b/include/zenoh-pico/protocol/codec/transport.h index cd0e4a2c5..06bb26327 100644 --- a/include/zenoh-pico/protocol/codec/transport.h +++ b/include/zenoh-pico/protocol/codec/transport.h @@ -17,7 +17,6 @@ #include "zenoh-pico/protocol/definitions/transport.h" #include "zenoh-pico/protocol/iobuf.h" -#define _ZENOH_PICO_FRAME_MESSAGES_VEC_SIZE 32 z_result_t _z_scouting_message_encode(_z_wbuf_t *buf, const _z_scouting_message_t *msg); z_result_t _z_scouting_message_decode(_z_scouting_message_t *msg, _z_zbuf_t *buf); diff --git a/include/zenoh-pico/protocol/core.h b/include/zenoh-pico/protocol/core.h index 366659e39..e66e3745e 100644 --- a/include/zenoh-pico/protocol/core.h +++ b/include/zenoh-pico/protocol/core.h @@ -199,7 +199,7 @@ z_result_t _z_hello_copy(_z_hello_t *dst, const _z_hello_t *src); bool _z_hello_check(const _z_hello_t *hello); -_Z_ELEM_DEFINE(_z_hello, _z_hello_t, _z_noop_size, _z_hello_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_hello, _z_hello_t, _z_noop_size, _z_hello_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_hello, _z_hello_t) typedef struct { diff --git a/include/zenoh-pico/protocol/definitions/network.h b/include/zenoh-pico/protocol/definitions/network.h index de203eb7e..c3ea611f8 100644 --- a/include/zenoh-pico/protocol/definitions/network.h +++ b/include/zenoh-pico/protocol/definitions/network.h @@ -289,8 +289,8 @@ void _z_n_msg_clear(_z_network_message_t *m); void _z_n_msg_free(_z_network_message_t **m); inline static void _z_msg_clear(_z_zenoh_message_t *msg) { _z_n_msg_clear(msg); } inline static void _z_msg_free(_z_zenoh_message_t **msg) { _z_n_msg_free(msg); } -_Z_ELEM_DEFINE(_z_network_message, _z_network_message_t, _z_noop_size, _z_n_msg_clear, _z_noop_copy) -_Z_VEC_DEFINE(_z_network_message, _z_network_message_t) +_Z_ELEM_DEFINE(_z_network_message, _z_network_message_t, _z_noop_size, _z_n_msg_clear, _z_noop_copy, _z_noop_move) +_Z_SVEC_DEFINE(_z_network_message, _z_network_message_t, false) void _z_msg_fix_mapping(_z_zenoh_message_t *msg, uint16_t mapping); _z_network_message_t _z_msg_make_query(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_slice_t) parameters, _z_zint_t qid, diff --git a/include/zenoh-pico/protocol/definitions/transport.h b/include/zenoh-pico/protocol/definitions/transport.h index 7334f391a..d2d6ae726 100644 --- a/include/zenoh-pico/protocol/definitions/transport.h +++ b/include/zenoh-pico/protocol/definitions/transport.h @@ -444,7 +444,7 @@ void _z_t_msg_keep_alive_clear(_z_t_msg_keep_alive_t *msg); // - if R==1 then the FRAME is sent on the reliable channel, best-effort otherwise. // typedef struct { - _z_network_message_vec_t _messages; + _z_network_message_svec_t _messages; _z_zint_t _sn; } _z_t_msg_frame_t; void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg); @@ -507,7 +507,7 @@ _z_transport_message_t _z_t_msg_make_open_syn(_z_zint_t lease, _z_zint_t initial _z_transport_message_t _z_t_msg_make_open_ack(_z_zint_t lease, _z_zint_t initial_sn); _z_transport_message_t _z_t_msg_make_close(uint8_t reason, bool link_only); _z_transport_message_t _z_t_msg_make_keep_alive(void); -_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_vec_t messages, +_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_svec_t messages, z_reliability_t reliability); _z_transport_message_t _z_t_msg_make_frame_header(_z_zint_t sn, z_reliability_t reliability); _z_transport_message_t _z_t_msg_make_fragment_header(_z_zint_t sn, z_reliability_t reliability, bool is_last); diff --git a/include/zenoh-pico/protocol/ext.h b/include/zenoh-pico/protocol/ext.h index cba1ab55d..3ec4198bb 100644 --- a/include/zenoh-pico/protocol/ext.h +++ b/include/zenoh-pico/protocol/ext.h @@ -96,7 +96,7 @@ void _z_msg_ext_copy_unit(_z_msg_ext_unit_t *clone, const _z_msg_ext_unit_t *ext void _z_msg_ext_copy_zint(_z_msg_ext_zint_t *clone, const _z_msg_ext_zint_t *ext); void _z_msg_ext_copy_zbuf(_z_msg_ext_zbuf_t *clone, const _z_msg_ext_zbuf_t *ext); -_Z_ELEM_DEFINE(_z_msg_ext, _z_msg_ext_t, _z_noop_size, _z_msg_ext_clear, _z_msg_ext_copy) +_Z_ELEM_DEFINE(_z_msg_ext, _z_msg_ext_t, _z_noop_size, _z_msg_ext_clear, _z_msg_ext_copy, _z_noop_move) _Z_VEC_DEFINE(_z_msg_ext, _z_msg_ext_t) #endif /* ZENOH_PICO_PROTOCOL_EXTENSION_H */ diff --git a/include/zenoh-pico/protocol/iobuf.h b/include/zenoh-pico/protocol/iobuf.h index 44cace0d7..f2617b897 100644 --- a/include/zenoh-pico/protocol/iobuf.h +++ b/include/zenoh-pico/protocol/iobuf.h @@ -60,7 +60,7 @@ void _z_iosli_free(_z_iosli_t **ios); void _z_iosli_copy(_z_iosli_t *dst, const _z_iosli_t *src); _z_iosli_t *_z_iosli_clone(const _z_iosli_t *src); -_Z_ELEM_DEFINE(_z_iosli, _z_iosli_t, _z_iosli_size, _z_iosli_clear, _z_iosli_copy) +_Z_ELEM_DEFINE(_z_iosli, _z_iosli_t, _z_iosli_size, _z_iosli_clear, _z_iosli_copy, _z_noop_move) _Z_VEC_DEFINE(_z_iosli, _z_iosli_t) /*------------------ ZBuf ------------------*/ diff --git a/include/zenoh-pico/session/resource.h b/include/zenoh-pico/session/resource.h index 3702a86cd..e1d9c1c62 100644 --- a/include/zenoh-pico/session/resource.h +++ b/include/zenoh-pico/session/resource.h @@ -32,7 +32,7 @@ void _z_unregister_resource(_z_session_t *zn, uint16_t id, uint16_t mapping); void _z_unregister_resources_for_peer(_z_session_t *zn, uint16_t mapping); void _z_flush_resources(_z_session_t *zn); -_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr); +_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr, bool force_alias); _z_resource_t *__unsafe_z_get_resource_by_id(_z_session_t *zn, uint16_t mapping, _z_zint_t id); _z_resource_t *__unsafe_z_get_resource_matching_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr); diff --git a/include/zenoh-pico/session/session.h b/include/zenoh-pico/session/session.h index 194b7f898..d2aa10129 100644 --- a/include/zenoh-pico/session/session.h +++ b/include/zenoh-pico/session/session.h @@ -45,7 +45,7 @@ void _z_resource_clear(_z_resource_t *res); void _z_resource_copy(_z_resource_t *dst, const _z_resource_t *src); void _z_resource_free(_z_resource_t **res); -_Z_ELEM_DEFINE(_z_resource, _z_resource_t, _z_noop_size, _z_resource_clear, _z_resource_copy) +_Z_ELEM_DEFINE(_z_resource, _z_resource_t, _z_noop_size, _z_resource_clear, _z_resource_copy, _z_noop_move) _Z_LIST_DEFINE(_z_resource, _z_resource_t) // Forward declaration to avoid cyclical include @@ -69,9 +69,9 @@ bool _z_subscription_eq(const _z_subscription_t *one, const _z_subscription_t *t void _z_subscription_clear(_z_subscription_t *sub); _Z_REFCOUNT_DEFINE(_z_subscription, _z_subscription) -_Z_ELEM_DEFINE(_z_subscriber, _z_subscription_t, _z_noop_size, _z_subscription_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_subscriber, _z_subscription_t, _z_noop_size, _z_subscription_clear, _z_noop_copy, _z_noop_move) _Z_ELEM_DEFINE(_z_subscription_rc, _z_subscription_rc_t, _z_subscription_rc_size, _z_subscription_rc_drop, - _z_subscription_rc_copy) + _z_subscription_rc_copy, _z_noop_move) _Z_LIST_DEFINE(_z_subscription_rc, _z_subscription_rc_t) typedef struct { @@ -100,9 +100,10 @@ bool _z_session_queryable_eq(const _z_session_queryable_t *one, const _z_session void _z_session_queryable_clear(_z_session_queryable_t *res); _Z_REFCOUNT_DEFINE(_z_session_queryable, _z_session_queryable) -_Z_ELEM_DEFINE(_z_session_queryable, _z_session_queryable_t, _z_noop_size, _z_session_queryable_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_session_queryable, _z_session_queryable_t, _z_noop_size, _z_session_queryable_clear, _z_noop_copy, + _z_noop_move) _Z_ELEM_DEFINE(_z_session_queryable_rc, _z_session_queryable_rc_t, _z_noop_size, _z_session_queryable_rc_drop, - _z_noop_copy) + _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_session_queryable_rc, _z_session_queryable_rc_t) // Forward declaration to avoid cyclical includes @@ -133,7 +134,7 @@ typedef struct { bool _z_pending_query_eq(const _z_pending_query_t *one, const _z_pending_query_t *two); void _z_pending_query_clear(_z_pending_query_t *res); -_Z_ELEM_DEFINE(_z_pending_query, _z_pending_query_t, _z_noop_size, _z_pending_query_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_pending_query, _z_pending_query_t, _z_noop_size, _z_pending_query_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_pending_query, _z_pending_query_t) typedef struct { @@ -184,9 +185,10 @@ bool _z_session_interest_eq(const _z_session_interest_t *one, const _z_session_i void _z_session_interest_clear(_z_session_interest_t *res); _Z_REFCOUNT_DEFINE(_z_session_interest, _z_session_interest) -_Z_ELEM_DEFINE(_z_session_interest, _z_session_interest_t, _z_noop_size, _z_session_interest_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_session_interest, _z_session_interest_t, _z_noop_size, _z_session_interest_clear, _z_noop_copy, + _z_noop_move) _Z_ELEM_DEFINE(_z_session_interest_rc, _z_session_interest_rc_t, _z_noop_size, _z_session_interest_rc_drop, - _z_noop_copy) + _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_session_interest_rc, _z_session_interest_rc_t) typedef enum { @@ -202,7 +204,7 @@ typedef struct { } _z_declare_data_t; void _z_declare_data_clear(_z_declare_data_t *data); -_Z_ELEM_DEFINE(_z_declare_data, _z_declare_data_t, _z_noop_size, _z_declare_data_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_declare_data, _z_declare_data_t, _z_noop_size, _z_declare_data_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_declare_data, _z_declare_data_t) #endif /* INCLUDE_ZENOH_PICO_SESSION_SESSION_H */ diff --git a/include/zenoh-pico/session/subscription.h b/include/zenoh-pico/session/subscription.h index f47df8c41..2d7e1187a 100644 --- a/include/zenoh-pico/session/subscription.h +++ b/include/zenoh-pico/session/subscription.h @@ -16,21 +16,43 @@ #define INCLUDE_ZENOH_PICO_SESSION_SUBSCRIPTION_H #include "zenoh-pico/net/encoding.h" -#include "zenoh-pico/net/session.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/session/session.h" + +// Forward declaration to avoid cyclical include +typedef struct _z_session_t _z_session_t; + +// Subscription infos +typedef struct { + _z_sample_handler_t callback; + void *arg; +} _z_subscription_infos_t; + +_Z_ELEM_DEFINE(_z_subscription_infos, _z_subscription_infos_t, _z_noop_size, _z_noop_clear, _z_noop_copy, _z_noop_move) +_Z_SVEC_DEFINE(_z_subscription_infos, _z_subscription_infos_t, false) + +typedef struct { + _z_keyexpr_t ke_in; + _z_keyexpr_t ke_out; + _z_subscription_infos_svec_t infos; +} _z_subscription_cache_t; /*------------------ Subscription ------------------*/ -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, const _z_bytes_t *payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - const _z_bytes_t *attachment, z_reliability_t reliability); + _z_bytes_t *attachment, z_reliability_t reliability); #if Z_FEATURE_SUBSCRIPTION == 1 -_z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id); -_z_subscription_rc_list_t *_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr); +#if Z_FEATURE_RX_CACHE == 1 +void _z_subscription_cache_clear(_z_subscription_cache_t *cache); +#endif + +_z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id); _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_t *sub); -z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, const _z_bytes_t *payload, +z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, - const _z_n_qos_t qos, const _z_bytes_t *attachment, z_reliability_t reliability); + const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability); void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub); void _z_flush_subscriptions(_z_session_t *zn); #endif diff --git a/include/zenoh-pico/system/link/raweth.h b/include/zenoh-pico/system/link/raweth.h index d48bf1fa4..c9c58381e 100644 --- a/include/zenoh-pico/system/link/raweth.h +++ b/include/zenoh-pico/system/link/raweth.h @@ -43,14 +43,15 @@ typedef struct { void _z_raweth_clear_mapping_entry(_zp_raweth_mapping_entry_t *entry); _Z_ELEM_DEFINE(_zp_raweth_mapping, _zp_raweth_mapping_entry_t, _z_noop_size, _z_raweth_clear_mapping_entry, - _z_noop_copy) + _z_noop_copy, _z_noop_move) _Z_ARRAY_DEFINE(_zp_raweth_mapping, _zp_raweth_mapping_entry_t) typedef struct { uint8_t _mac[_ZP_MAC_ADDR_LENGTH]; } _zp_raweth_whitelist_entry_t; -_Z_ELEM_DEFINE(_zp_raweth_whitelist, _zp_raweth_whitelist_entry_t, _z_noop_size, _z_noop_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_zp_raweth_whitelist, _zp_raweth_whitelist_entry_t, _z_noop_size, _z_noop_clear, _z_noop_copy, + _z_noop_move) _Z_ARRAY_DEFINE(_zp_raweth_whitelist, _zp_raweth_whitelist_entry_t) // Ethernet header structure type diff --git a/include/zenoh-pico/transport/transport.h b/include/zenoh-pico/transport/transport.h index e6c97e5d3..678bf2022 100644 --- a/include/zenoh-pico/transport/transport.h +++ b/include/zenoh-pico/transport/transport.h @@ -61,7 +61,7 @@ void _z_transport_peer_entry_clear(_z_transport_peer_entry_t *src); void _z_transport_peer_entry_copy(_z_transport_peer_entry_t *dst, const _z_transport_peer_entry_t *src); bool _z_transport_peer_entry_eq(const _z_transport_peer_entry_t *left, const _z_transport_peer_entry_t *right); _Z_ELEM_DEFINE(_z_transport_peer_entry, _z_transport_peer_entry_t, _z_transport_peer_entry_size, - _z_transport_peer_entry_clear, _z_transport_peer_entry_copy) + _z_transport_peer_entry_clear, _z_transport_peer_entry_copy, _z_noop_move) _Z_LIST_DEFINE(_z_transport_peer_entry, _z_transport_peer_entry_t) _z_transport_peer_entry_list_t *_z_transport_peer_entry_list_insert(_z_transport_peer_entry_list_t *root, _z_transport_peer_entry_t *entry); @@ -139,7 +139,7 @@ typedef struct { enum { _Z_TRANSPORT_UNICAST_TYPE, _Z_TRANSPORT_MULTICAST_TYPE, _Z_TRANSPORT_RAWETH_TYPE, _Z_TRANSPORT_NONE } _type; } _z_transport_t; -_Z_ELEM_DEFINE(_z_transport, _z_transport_t, _z_noop_size, _z_noop_clear, _z_noop_copy) +_Z_ELEM_DEFINE(_z_transport, _z_transport_t, _z_noop_size, _z_noop_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_transport, _z_transport_t) typedef struct { diff --git a/src/api/api.c b/src/api/api.c index 2056d956c..d74130335 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -517,8 +517,7 @@ z_result_t z_whatami_to_view_string(z_whatami_t whatami, z_view_string_t *str_ou bool _z_string_array_check(const _z_string_svec_t *val) { return !_z_string_svec_is_empty(val); } z_result_t _z_string_array_copy(_z_string_svec_t *dst, const _z_string_svec_t *src) { - _z_string_svec_copy(dst, src); - return dst->_len == src->_len ? _Z_RES_OK : _Z_ERR_SYSTEM_OUT_OF_MEMORY; + return _z_string_svec_copy(dst, src); } _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_string_svec_t, string_array, _z_string_array_check, _z_string_array_null, _z_string_array_copy, _z_string_svec_clear) @@ -833,9 +832,10 @@ z_result_t z_put(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr // Trigger local subscriptions #if Z_FEATURE_LOCAL_SUBSCRIBER == 1 - _z_timestamp_t local_timestamp = ((opt.timestamp != NULL) ? *opt.timestamp : _z_timestamp_null()); + _z_timestamp_t local_timestamp = (opt.timestamp != NULL) ? *opt.timestamp : _z_timestamp_null(); + _z_encoding_t local_encoding = (opt.encoding != NULL) ? &opt.encoding->_this._val : _z_encoding_null(); _z_trigger_local_subscriptions( - _Z_RC_IN_VAL(zs), &keyexpr_aliased, &payload_bytes, opt.encoding == NULL ? NULL : &opt.encoding->_this._val, + _Z_RC_IN_VAL(zs), &keyexpr_aliased, &payload_bytes, &local_encoding, _z_n_qos_make(opt.is_express, opt.congestion_control == Z_CONGESTION_CONTROL_BLOCK, opt.priority), &local_timestamp, &attachment_bytes, reliability); #endif @@ -980,7 +980,7 @@ z_result_t z_publisher_put(const z_loaned_publisher_t *pub, z_moved_bytes_t *pay } // Trigger local subscriptions #if Z_FEATURE_LOCAL_SUBSCRIBER == 1 - _z_timestamp_t local_timestamp = ((opt.timestamp != NULL) ? *opt.timestamp : _z_timestamp_null()); + _z_timestamp_t local_timestamp = (opt.timestamp != NULL) ? *opt.timestamp : _z_timestamp_null(); _z_trigger_local_subscriptions( session, &pub_keyexpr, &payload_bytes, &encoding, _z_n_qos_make(pub->_is_express, pub->_congestion_control == Z_CONGESTION_CONTROL_BLOCK, pub->_priority), diff --git a/src/collections/bytes.c b/src/collections/bytes.c index e4328cd40..deb3f8252 100644 --- a/src/collections/bytes.c +++ b/src/collections/bytes.c @@ -28,12 +28,7 @@ bool _z_bytes_check(const _z_bytes_t *bytes) { return !_z_bytes_is_empty(bytes); } z_result_t _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src) { - _z_arc_slice_svec_copy(&dst->_slices, &src->_slices); - if (_z_arc_slice_svec_len(&dst->_slices) == _z_arc_slice_svec_len(&src->_slices)) { - return _Z_RES_OK; - } else { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } + return _z_arc_slice_svec_copy(&dst->_slices, &src->_slices); } _z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src) { @@ -98,7 +93,7 @@ z_result_t _z_bytes_from_slice(_z_bytes_t *b, _z_slice_t s) { *b = _z_bytes_null(); _z_arc_slice_t arc_s = _z_arc_slice_wrap(s, 0, s.len); if (_z_arc_slice_len(&arc_s) != s.len) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - return _z_arc_slice_svec_append(&b->_slices, &arc_s) ? _Z_RES_OK : _Z_ERR_SYSTEM_OUT_OF_MEMORY; + return _z_arc_slice_svec_append(&b->_slices, &arc_s); } z_result_t _z_bytes_from_buf(_z_bytes_t *b, const uint8_t *src, size_t len) { @@ -130,8 +125,7 @@ z_result_t _z_bytes_to_slice(const _z_bytes_t *bytes, _z_slice_t *s) { } z_result_t _z_bytes_append_slice(_z_bytes_t *dst, _z_arc_slice_t *s) { - _Z_CLEAN_RETURN_IF_ERR(_z_arc_slice_svec_append(&dst->_slices, s) ? _Z_RES_OK : _Z_ERR_SYSTEM_OUT_OF_MEMORY, - _z_arc_slice_drop(s)); + _Z_CLEAN_RETURN_IF_ERR(_z_arc_slice_svec_append(&dst->_slices, s), _z_arc_slice_drop(s)); return _Z_RES_OK; } @@ -159,7 +153,7 @@ _z_slice_t _z_bytes_try_get_contiguous(const _z_bytes_t *bs) { } void _z_bytes_move(_z_bytes_t *dst, _z_bytes_t *src) { - dst->_slices = src->_slices; + *dst = *src; *src = _z_bytes_null(); } diff --git a/src/collections/vec.c b/src/collections/vec.c index d0f1a5c92..60ee8f4a1 100644 --- a/src/collections/vec.c +++ b/src/collections/vec.c @@ -41,7 +41,7 @@ void _z_vec_copy(_z_vec_t *dst, const _z_vec_t *src, z_element_clone_f d_f) { } } -void _z_vec_steal(_z_vec_t *dst, _z_vec_t *src) { +void _z_vec_move(_z_vec_t *dst, _z_vec_t *src) { *dst = *src; *src = _z_vec_null(); } @@ -145,40 +145,47 @@ _z_svec_t _z_svec_make(size_t capacity, size_t element_size) { return v; } -void __z_svec_copy_inner(void *dst, const void *src, z_element_copy_f copy, size_t num_elements, size_t element_size) { - if (copy == NULL) { - memcpy(dst, src, num_elements * element_size); - } else { - size_t offset = 0; - for (size_t i = 0; i < num_elements; i++) { - copy((uint8_t *)dst + offset, (uint8_t *)src + offset); - offset += element_size; - } - } -} +void _z_svec_init(_z_svec_t *dst, size_t element_size) { memset(dst->_val, 0, dst->_capacity * element_size); } -void __z_svec_move_inner(void *dst, void *src, z_element_move_f move, size_t num_elements, size_t element_size) { - if (move == NULL) { - memcpy(dst, src, num_elements * element_size); - } else { +static inline void __z_svec_move_inner(void *dst, void *src, z_element_move_f move, size_t num_elements, + size_t element_size, bool use_elem_f) { + if (use_elem_f) { size_t offset = 0; for (size_t i = 0; i < num_elements; i++) { move((uint8_t *)dst + offset, (uint8_t *)src + offset); offset += element_size; } + } else { + memcpy(dst, src, num_elements * element_size); } } -bool _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size) { +void _z_svec_move(_z_svec_t *dst, _z_svec_t *src) { + *dst = *src; + *src = _z_svec_null(); +} + +z_result_t _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size, + bool use_elem_f) { dst->_capacity = 0; dst->_len = 0; dst->_val = z_malloc(element_size * src->_capacity); - if (dst->_val != NULL) { - dst->_capacity = src->_capacity; - dst->_len = src->_len; - __z_svec_copy_inner(dst->_val, src->_val, copy, src->_len, element_size); + if (dst->_val == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + dst->_capacity = src->_capacity; + dst->_len = src->_len; + // Copy data to new vector + if (use_elem_f) { + size_t offset = 0; + for (size_t i = 0; i < src->_len; i++) { + copy((uint8_t *)dst->_val + offset, (uint8_t *)src->_val + offset); + offset += element_size; + } + } else { + memcpy(dst->_val, src->_val, src->_len * element_size); } - return dst->_len == src->_len; + return _Z_RES_OK; } void _z_svec_reset(_z_svec_t *v, z_element_clear_f clear, size_t element_size) { @@ -199,10 +206,7 @@ void _z_svec_clear(_z_svec_t *v, z_element_clear_f clear_f, size_t element_size) void _z_svec_release(_z_svec_t *v) { z_free(v->_val); - v->_val = NULL; - - v->_capacity = 0; - v->_len = 0; + *v = _z_svec_null(); } void _z_svec_free(_z_svec_t **v, z_element_clear_f clear, size_t element_size) { @@ -220,29 +224,30 @@ size_t _z_svec_len(const _z_svec_t *v) { return v->_len; } bool _z_svec_is_empty(const _z_svec_t *v) { return v->_len == 0; } -bool _z_svec_append(_z_svec_t *v, const void *e, z_element_move_f move, size_t element_size) { - if (v->_len == v->_capacity) { - // Allocate a new vector - size_t _capacity = v->_capacity == 0 ? 1 : (v->_capacity << 1); - void *_val = (void *)z_malloc(_capacity * element_size); - if (_val != NULL) { - __z_svec_move_inner(_val, v->_val, move, v->_len, element_size); - // Free the old data - z_free(v->_val); +z_result_t _z_svec_expand(_z_svec_t *v, z_element_move_f move, size_t element_size, bool use_elem_f) { + // Allocate a new vector + size_t _capacity = v->_capacity == 0 ? 1 : (v->_capacity << 1); + void *_val = (void *)z_malloc(_capacity * element_size); + if (_val == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + __z_svec_move_inner(_val, v->_val, move, v->_len, element_size, use_elem_f); + // Free the old data + z_free(v->_val); + // Update the current vector + v->_val = _val; + v->_capacity = _capacity; + return _Z_RES_OK; +} - // Update the current vector - v->_val = _val; - v->_capacity = _capacity; - memcpy((uint8_t *)v->_val + v->_len * element_size, e, element_size); - v->_len++; - } else { - return false; - } - } else { - memcpy((uint8_t *)v->_val + v->_len * element_size, e, element_size); - v->_len++; +z_result_t _z_svec_append(_z_svec_t *v, const void *e, z_element_move_f move, size_t element_size, bool use_elem_f) { + if (v->_len == v->_capacity) { + _Z_RETURN_IF_ERR(_z_svec_expand(v, move, element_size, use_elem_f)); } - return true; + // Append element + memcpy((uint8_t *)v->_val + v->_len * element_size, e, element_size); + v->_len++; + return _Z_RES_OK; } void *_z_svec_get(const _z_svec_t *v, size_t i, size_t element_size) { @@ -250,17 +255,20 @@ void *_z_svec_get(const _z_svec_t *v, size_t i, size_t element_size) { return (uint8_t *)v->_val + i * element_size; } +void *_z_svec_get_mut(_z_svec_t *v, size_t i, size_t element_size) { return (uint8_t *)v->_val + i * element_size; } + void _z_svec_set(_z_svec_t *v, size_t i, void *e, z_element_clear_f clear, size_t element_size) { assert(i < v->_len); clear((uint8_t *)v->_val + i * element_size); memcpy((uint8_t *)v->_val + i * element_size, e, element_size); } -void _z_svec_remove(_z_svec_t *v, size_t pos, z_element_clear_f clear, z_element_move_f move, size_t element_size) { +void _z_svec_remove(_z_svec_t *v, size_t pos, z_element_clear_f clear, z_element_move_f move, size_t element_size, + bool use_elem_f) { assert(pos < v->_len); clear((uint8_t *)v->_val + pos * element_size); __z_svec_move_inner((uint8_t *)v->_val + pos * element_size, (uint8_t *)v->_val + (pos + 1) * element_size, move, - (v->_len - pos - 1) * element_size, element_size); + (v->_len - pos - 1) * element_size, element_size, use_elem_f); v->_len--; } diff --git a/src/net/encoding.c b/src/net/encoding.c index 8bd1ec256..45b13e4d3 100644 --- a/src/net/encoding.c +++ b/src/net/encoding.c @@ -38,7 +38,11 @@ z_result_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *sc return _Z_RES_OK; } -void _z_encoding_clear(_z_encoding_t *encoding) { _z_string_clear(&encoding->schema); } +void _z_encoding_clear(_z_encoding_t *encoding) { + if (_z_string_check(&encoding->schema)) { + _z_string_clear(&encoding->schema); + } +} z_result_t _z_encoding_copy(_z_encoding_t *dst, const _z_encoding_t *src) { dst->id = src->id; @@ -55,6 +59,8 @@ void _z_encoding_move(_z_encoding_t *dst, _z_encoding_t *src) { src->id = _Z_ENCODING_ID_DEFAULT; if (_z_string_check(&src->schema)) { _z_string_move(&dst->schema, &src->schema); + } else { + dst->schema = _z_string_null(); } } diff --git a/src/net/sample.c b/src/net/sample.c index 0921a3fc2..d158398c6 100644 --- a/src/net/sample.c +++ b/src/net/sample.c @@ -58,28 +58,22 @@ _z_sample_t _z_sample_duplicate(const _z_sample_t *src) { } #if Z_FEATURE_SUBSCRIPTION == 1 -_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t *payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, - const _z_bytes_t *attachment, z_reliability_t reliability) { - _z_sample_t s = _z_sample_null(); - s.keyexpr = _z_keyexpr_steal(key); - s.kind = kind; - if (_z_timestamp_check(timestamp)) { - s.timestamp = _z_timestamp_duplicate(timestamp); - } - s.qos = qos; - s.reliability = reliability; - _z_bytes_copy(&s.payload, payload); - _z_bytes_copy(&s.attachment, attachment); - if (encoding != NULL) { - _z_encoding_move(&s.encoding, encoding); - } - return s; +void _z_sample_create(_z_sample_t *s, _z_keyexpr_t *key, _z_bytes_t *payload, const _z_timestamp_t *timestamp, + _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, _z_bytes_t *attachment, + z_reliability_t reliability) { + s->kind = kind; + s->qos = qos; + s->reliability = reliability; + s->keyexpr = _z_keyexpr_steal(key); + s->timestamp = _z_timestamp_check(timestamp) ? _z_timestamp_duplicate(timestamp) : _z_timestamp_null(); + _z_encoding_move(&s->encoding, encoding); + _z_bytes_move(&s->attachment, attachment); + _z_bytes_move(&s->payload, payload); } #else -_z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t *payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, - const _z_bytes_t *attachment, z_reliability_t reliability) { +void _z_sample_create(_z_sample_t *s, _z_keyexpr_t *key, _z_bytes_t *payload, const _z_timestamp_t *timestamp, + _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, _z_bytes_t *attachment, + z_reliability_t reliability) { _ZP_UNUSED(key); _ZP_UNUSED(payload); _ZP_UNUSED(timestamp); @@ -88,6 +82,6 @@ _z_sample_t _z_sample_create(_z_keyexpr_t *key, const _z_bytes_t *payload, const _ZP_UNUSED(qos); _ZP_UNUSED(attachment); _ZP_UNUSED(reliability); - return _z_sample_null(); + *s = _z_sample_null(); } #endif diff --git a/src/protocol/codec.c b/src/protocol/codec.c index 8574d2d89..64f22cade 100644 --- a/src/protocol/codec.c +++ b/src/protocol/codec.c @@ -282,7 +282,6 @@ z_result_t _z_slice_val_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice z_result_t _z_slice_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice_decode_na(bs, zbf); } z_result_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf) { - *bs = _z_bytes_null(); // Decode slice _z_slice_t s; _Z_RETURN_IF_ERR(_z_slice_decode(&s, zbf)); @@ -351,7 +350,6 @@ z_result_t _z_string_encode(_z_wbuf_t *wbf, const _z_string_t *s) { } z_result_t _z_string_decode(_z_string_t *str, _z_zbuf_t *zbf) { - *str = _z_string_null(); _z_zint_t len = 0; // Decode string length _Z_RETURN_IF_ERR(_z_zsize_decode(&len, zbf)); @@ -360,13 +358,9 @@ z_result_t _z_string_decode(_z_string_t *str, _z_zbuf_t *zbf) { _Z_INFO("Not enough bytes to read"); return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - // Allocate space for the string terminator - *str = _z_string_preallocate(len); - if (str->_slice.start == NULL) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - // Read bytes - _z_zbuf_read_bytes(zbf, (uint8_t *)_z_string_data(str), 0, len); + // Alias string + *str = _z_string_alias_substr((const char *)_z_zbuf_get_rptr(zbf), len); + _z_zbuf_set_rpos(zbf, _z_zbuf_get_rpos(zbf) + len); return _Z_RES_OK; } diff --git a/src/protocol/codec/message.c b/src/protocol/codec/message.c index b46dcaca0..35c8fa826 100644 --- a/src/protocol/codec/message.c +++ b/src/protocol/codec/message.c @@ -332,7 +332,6 @@ z_result_t _z_push_body_decode(_z_push_body_t *pshb, _z_zbuf_t *zbf, uint8_t hea switch (_Z_MID(header)) { case _Z_MID_Z_PUT: { pshb->_is_put = true; - pshb->_body._put = (_z_msg_put_t){0}; if (_Z_HAS_FLAG(header, _Z_FLAG_Z_P_T)) { _Z_RETURN_IF_ERR(_z_timestamp_decode(&pshb->_body._put._commons._timestamp, zbf)); } @@ -349,7 +348,6 @@ z_result_t _z_push_body_decode(_z_push_body_t *pshb, _z_zbuf_t *zbf, uint8_t hea } case _Z_MID_Z_DEL: { pshb->_is_put = false; - pshb->_body._del = (_z_msg_del_t){0}; if (_Z_HAS_FLAG(header, _Z_FLAG_Z_D_T)) { _Z_RETURN_IF_ERR(_z_timestamp_decode(&pshb->_body._put._commons._timestamp, zbf)); } @@ -470,7 +468,6 @@ z_result_t _z_query_decode_extensions(_z_msg_ext_t *extension, void *ctx) { z_result_t _z_query_decode(_z_msg_query_t *msg, _z_zbuf_t *zbf, uint8_t header) { _Z_DEBUG("Decoding _Z_MID_Z_QUERY"); - *msg = (_z_msg_query_t){0}; z_result_t ret = _Z_RES_OK; if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Q_C)) { @@ -513,7 +510,6 @@ z_result_t _z_reply_decode_extension(_z_msg_ext_t *extension, void *ctx) { return ret; } z_result_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header) { - *reply = (_z_msg_reply_t){0}; if (_Z_HAS_FLAG(header, _Z_FLAG_Z_R_C)) { _Z_RETURN_IF_ERR(_z_uint8_decode((uint8_t *)&reply->_consolidation, zbf)); } else { @@ -574,8 +570,6 @@ z_result_t _z_err_decode_extension(_z_msg_ext_t *extension, void *ctx) { return ret; } z_result_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header) { - *err = (_z_msg_err_t){0}; - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_E_E)) { _Z_RETURN_IF_ERR(_z_encoding_decode(&err->_encoding, zbf)); } diff --git a/src/protocol/codec/network.c b/src/protocol/codec/network.c index 374db4564..de453c9ae 100644 --- a/src/protocol/codec/network.c +++ b/src/protocol/codec/network.c @@ -94,7 +94,6 @@ z_result_t _z_push_decode_ext_cb(_z_msg_ext_t *extension, void *ctx) { z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header) { z_result_t ret = _Z_RES_OK; - *msg = (_z_n_msg_push_t){0}; msg->_qos = _Z_N_QOS_DEFAULT; ret |= _z_keyexpr_decode(&msg->_key, zbf, _Z_HAS_FLAG(header, _Z_FLAG_N_PUSH_N)); _z_keyexpr_set_mapping(&msg->_key, _Z_HAS_FLAG(header, _Z_FLAG_N_PUSH_M) ? _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE @@ -208,7 +207,6 @@ z_result_t _z_request_decode_extensions(_z_msg_ext_t *extension, void *ctx) { return _Z_RES_OK; } z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, const uint8_t header) { - *msg = (_z_n_msg_request_t){0}; msg->_ext_qos = _Z_N_QOS_DEFAULT; _Z_RETURN_IF_ERR(_z_zsize_decode(&msg->_rid, zbf)); _Z_RETURN_IF_ERR(_z_keyexpr_decode(&msg->_key, zbf, _Z_HAS_FLAG(header, _Z_FLAG_N_REQUEST_N))); @@ -338,7 +336,6 @@ z_result_t _z_response_decode_extension(_z_msg_ext_t *extension, void *ctx) { z_result_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t header) { _Z_DEBUG("Decoding _Z_MID_N_RESPONSE"); - *msg = (_z_n_msg_response_t){0}; msg->_ext_qos = _Z_N_QOS_DEFAULT; z_result_t ret = _Z_RES_OK; _z_keyexpr_set_mapping(&msg->_key, _Z_HAS_FLAG(header, _Z_FLAG_N_RESPONSE_M) ? _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE @@ -384,8 +381,6 @@ z_result_t _z_response_final_encode(_z_wbuf_t *wbf, const _z_n_msg_response_fina z_result_t _z_response_final_decode(_z_n_msg_response_final_t *msg, _z_zbuf_t *zbf, uint8_t header) { (void)(header); - - *msg = (_z_n_msg_response_final_t){0}; z_result_t ret = _Z_RES_OK; ret |= _z_zsize_decode(&msg->_request_id, zbf); if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { @@ -444,7 +439,6 @@ z_result_t _z_declare_decode_extensions(_z_msg_ext_t *extension, void *ctx) { return _Z_RES_OK; } z_result_t _z_declare_decode(_z_n_msg_declare_t *decl, _z_zbuf_t *zbf, uint8_t header) { - *decl = (_z_n_msg_declare_t){0}; decl->_ext_qos = _Z_N_QOS_DEFAULT; // Retrieve interest id if (_Z_HAS_FLAG(header, _Z_FLAG_N_DECLARE_I)) { diff --git a/src/protocol/codec/transport.c b/src/protocol/codec/transport.c index e77e62f88..f09b5460f 100644 --- a/src/protocol/codec/transport.c +++ b/src/protocol/codec/transport.c @@ -28,6 +28,10 @@ #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/result.h" +#define _Z_FRAME_VEC_BASE_SIZE 8 // Abritrary small value +#define _Z_FRAME_VEC_SIZE_FROM_ZBUF_LEN(len) \ + (_Z_FRAME_VEC_BASE_SIZE + (len) / Z_CONFIG_FRAME_AVG_MSG_SIZE) // Approximate number of messages in frame + uint8_t _z_whatami_to_uint8(z_whatami_t whatami) { return (whatami >> 1) & 0x03; // get set bit index; only first 3 bits can be set } @@ -339,9 +343,9 @@ z_result_t _z_frame_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_frame_ ret = _Z_ERR_MESSAGE_SERIALIZATION_FAILED; } if (ret == _Z_RES_OK) { - size_t len = _z_network_message_vec_len(&msg->_messages); + size_t len = _z_network_message_svec_len(&msg->_messages); for (size_t i = 0; i < len; i++) { - _Z_RETURN_IF_ERR(_z_network_message_encode(wbf, _z_network_message_vec_get(&msg->_messages, i))) + _Z_RETURN_IF_ERR(_z_network_message_encode(wbf, _z_network_message_svec_get(&msg->_messages, i))) } } @@ -352,38 +356,45 @@ z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header z_result_t ret = _Z_RES_OK; *msg = (_z_t_msg_frame_t){0}; - ret |= _z_zsize_decode(&msg->_sn, zbf); - if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { - ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x04); - } - if (ret == _Z_RES_OK) { - msg->_messages = _z_network_message_vec_make(_ZENOH_PICO_FRAME_MESSAGES_VEC_SIZE); - while (_z_zbuf_len(zbf) > 0) { - // Mark the reading position of the iobfer - size_t r_pos = _z_zbuf_get_rpos(zbf); - _z_network_message_t *nm = (_z_network_message_t *)z_malloc(sizeof(_z_network_message_t)); - memset(nm, 0, sizeof(_z_network_message_t)); - ret |= _z_network_message_decode(nm, zbf); - if (ret == _Z_RES_OK) { - _z_network_message_vec_append(&msg->_messages, nm); - } else { - _z_n_msg_free(&nm); - _z_network_message_vec_clear(&msg->_messages); - - _z_zbuf_set_rpos(zbf, r_pos); // Restore the reading position of the iobfer - - // FIXME: Check for the return error, since not all of them means a decoding error - // in this particular case. As of now, we roll-back the reading position - // and return to the Zenoh transport-level decoder. - // https://github.com/eclipse-zenoh/zenoh-pico/pull/132#discussion_r1045593602 - if ((ret & _Z_ERR_MESSAGE_ZENOH_UNKNOWN) == _Z_ERR_MESSAGE_ZENOH_UNKNOWN) { - ret = _Z_RES_OK; - } - break; + _Z_RETURN_IF_ERR(_z_zsize_decode(&msg->_sn, zbf)); + if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z)) { + _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, 0x04)); + } + // Create message vector + size_t var_size = _Z_FRAME_VEC_SIZE_FROM_ZBUF_LEN(_z_zbuf_len(zbf)); + msg->_messages = _z_network_message_svec_make(var_size); + if (msg->_messages._capacity == 0) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + _z_network_message_svec_init(&msg->_messages); + size_t msg_idx = 0; + while (_z_zbuf_len(zbf) > 0) { + // Expand message vector if needed + if (msg_idx >= msg->_messages._capacity) { + _Z_RETURN_IF_ERR(_z_network_message_svec_expand(&msg->_messages)); + _z_network_message_svec_init(&msg->_messages); + } + // Mark the reading position of the iobfer + size_t r_pos = _z_zbuf_get_rpos(zbf); + _z_network_message_t *nm = _z_network_message_svec_get_mut(&msg->_messages, msg_idx); + ret = _z_network_message_decode(nm, zbf); + if (ret != _Z_RES_OK) { + _z_network_message_svec_clear(&msg->_messages); + _z_zbuf_set_rpos(zbf, r_pos); // Restore the reading position of the iobfer + + // FIXME: Check for the return error, since not all of them means a decoding error + // in this particular case. As of now, we roll-back the reading position + // and return to the Zenoh transport-level decoder. + // https://github.com/eclipse-zenoh/zenoh-pico/pull/132#discussion_r1045593602 + if ((ret & _Z_ERR_MESSAGE_ZENOH_UNKNOWN) == _Z_ERR_MESSAGE_ZENOH_UNKNOWN) { + ret = _Z_RES_OK; } + return ret; } + msg->_messages._len++; + msg_idx++; } - return ret; + return _Z_RES_OK; } /*------------------ Fragment Message ------------------*/ diff --git a/src/protocol/core.c b/src/protocol/core.c index 4dda7b57c..16842f708 100644 --- a/src/protocol/core.c +++ b/src/protocol/core.c @@ -63,7 +63,7 @@ z_result_t _z_value_copy(_z_value_t *dst, const _z_value_t *src) { z_result_t _z_hello_copy(_z_hello_t *dst, const _z_hello_t *src) { *dst = _z_hello_null(); - _Z_RETURN_IF_ERR(_z_string_svec_copy(&dst->_locators, &src->_locators) ? _Z_RES_OK : _Z_ERR_SYSTEM_OUT_OF_MEMORY); + _Z_RETURN_IF_ERR(_z_string_svec_copy(&dst->_locators, &src->_locators)); dst->_version = src->_version; dst->_whatami = src->_whatami; memcpy(&dst->_zid.id, &src->_zid.id, _Z_ID_LEN); diff --git a/src/protocol/definitions/message.c b/src/protocol/definitions/message.c index 3001b3372..0c3058e0a 100644 --- a/src/protocol/definitions/message.c +++ b/src/protocol/definitions/message.c @@ -23,6 +23,7 @@ void _z_msg_reply_clear(_z_msg_reply_t *msg) { _z_push_body_clear(&msg->_body); } void _z_msg_put_clear(_z_msg_put_t *msg) { + // TODO: systematically move everything so there's nothing to clear _z_bytes_drop(&msg->_payload); _z_bytes_drop(&msg->_attachment); _z_encoding_clear(&msg->_encoding); diff --git a/src/protocol/definitions/transport.c b/src/protocol/definitions/transport.c index 2af77cb97..448951e46 100644 --- a/src/protocol/definitions/transport.c +++ b/src/protocol/definitions/transport.c @@ -40,7 +40,7 @@ void _z_t_msg_close_clear(_z_t_msg_close_t *msg) { (void)(msg); } void _z_t_msg_keep_alive_clear(_z_t_msg_keep_alive_t *msg) { (void)(msg); } -void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg) { _z_network_message_vec_clear(&msg->_messages); } +void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg) { _z_network_message_svec_clear(&msg->_messages); } void _z_t_msg_fragment_clear(_z_t_msg_fragment_t *msg) { _z_slice_clear(&msg->_payload); } @@ -216,7 +216,7 @@ _z_transport_message_t _z_t_msg_make_keep_alive(void) { return msg; } -_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_vec_t messages, +_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_svec_t messages, z_reliability_t reliability) { _z_transport_message_t msg; msg._header = _Z_MID_T_FRAME; @@ -241,7 +241,7 @@ _z_transport_message_t _z_t_msg_make_frame_header(_z_zint_t sn, z_reliability_t _Z_SET_FLAG(msg._header, _Z_FLAG_T_FRAME_R); } - msg._body._frame._messages = _z_network_message_vec_make(0); + msg._body._frame._messages = _z_network_message_svec_null(); return msg; } @@ -307,7 +307,7 @@ void _z_t_msg_copy_keep_alive(_z_t_msg_keep_alive_t *clone, _z_t_msg_keep_alive_ void _z_t_msg_copy_frame(_z_t_msg_frame_t *clone, _z_t_msg_frame_t *msg) { clone->_sn = msg->_sn; - _z_network_message_vec_copy(&clone->_messages, &msg->_messages); + _z_network_message_svec_copy(&clone->_messages, &msg->_messages); } /*------------------ Transport Message ------------------*/ diff --git a/src/session/interest.c b/src/session/interest.c index 6bcdbed4c..8faa6cc2f 100644 --- a/src/session/interest.c +++ b/src/session/interest.c @@ -271,7 +271,7 @@ z_result_t _z_interest_process_declares(_z_session_t *zn, const _z_declaration_t } // Retrieve key _z_session_mutex_lock(zn); - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, decl_key); + _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, decl_key, true); if (!_z_keyexpr_has_suffix(&key)) { _z_session_mutex_unlock(zn); return _Z_ERR_KEYEXPR_UNKNOWN; diff --git a/src/session/query.c b/src/session/query.c index 150d9c54f..241839551 100644 --- a/src/session/query.c +++ b/src/session/query.c @@ -122,7 +122,7 @@ z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, ret = _Z_ERR_ENTITY_UNKNOWN; } - _z_keyexpr_t expanded_ke = __unsafe_z_get_expanded_key_from_key(zn, &keyexpr); + _z_keyexpr_t expanded_ke = __unsafe_z_get_expanded_key_from_key(zn, &keyexpr, true); if ((ret == _Z_RES_OK) && ((pen_qry->_anykey == false) && (_z_keyexpr_suffix_intersects(&pen_qry->_key, &keyexpr) == false))) { ret = _Z_ERR_QUERY_NOT_MATCH; diff --git a/src/session/queryable.c b/src/session/queryable.c index a7a25eaee..ba04debd7 100644 --- a/src/session/queryable.c +++ b/src/session/queryable.c @@ -106,7 +106,7 @@ _z_session_queryable_rc_t *_z_get_session_queryable_by_id(_z_session_t *zn, cons _z_session_queryable_rc_list_t *_z_get_session_queryable_by_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { _z_session_mutex_lock(zn); - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr); + _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, false); _z_session_queryable_rc_list_t *qles = __unsafe_z_get_session_queryable_by_key(zn, key); _z_session_mutex_unlock(zn); @@ -139,7 +139,7 @@ z_result_t _z_trigger_queryables(_z_session_rc_t *zsrc, _z_msg_query_t *msgq, co _z_session_mutex_lock(zn); - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, &q_key); + _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, &q_key, true); if (_z_keyexpr_has_suffix(&key)) { _z_session_queryable_rc_list_t *qles = __unsafe_z_get_session_queryable_by_key(zn, key); diff --git a/src/session/resource.c b/src/session/resource.c index 37c19411a..2413a1d21 100644 --- a/src/session/resource.c +++ b/src/session/resource.c @@ -87,7 +87,8 @@ _z_resource_t *__z_get_resource_by_key(_z_resource_list_t *rl, const _z_keyexpr_ return ret; } -_z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keyexpr_t *keyexpr) { +static _z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keyexpr_t *keyexpr, + bool force_alias) { _z_zint_t id = keyexpr->_id; // Check if ke is already expanded @@ -95,7 +96,12 @@ _z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keye if (!_z_keyexpr_has_suffix(keyexpr)) { return _z_keyexpr_null(); } - return _z_keyexpr_duplicate(keyexpr); + // Keyexpr can be aliased from a rx buffer + if (force_alias) { + return _z_keyexpr_alias(*keyexpr); + } else { + return _z_keyexpr_duplicate(keyexpr); + } } // Need to build the complete resource name, by recursively look at RIDs @@ -169,9 +175,9 @@ _z_resource_t *__unsafe_z_get_resource_by_key(_z_session_t *zn, const _z_keyexpr * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { +_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr, bool force_alias) { _z_resource_list_t *decls = _z_keyexpr_is_local(keyexpr) ? zn->_local_resources : zn->_remote_resources; - return __z_get_expanded_key_from_key(decls, keyexpr); + return __z_get_expanded_key_from_key(decls, keyexpr, force_alias); } _z_resource_t *_z_get_resource_by_id(_z_session_t *zn, uint16_t mapping, _z_zint_t rid) { @@ -199,7 +205,7 @@ _z_resource_t *_z_get_resource_by_key(_z_session_t *zn, const _z_keyexpr_t *keye _z_keyexpr_t _z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { _z_session_mutex_lock(zn); - _z_keyexpr_t res = __unsafe_z_get_expanded_key_from_key(zn, keyexpr); + _z_keyexpr_t res = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, false); _z_session_mutex_unlock(zn); @@ -219,7 +225,7 @@ uint16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, u _z_resource_t *parent = __unsafe_z_get_resource_by_id(zn, parent_mapping, key._id); parent->_refcount++; } else { - key = __unsafe_z_get_expanded_key_from_key(zn, &key); + key = __unsafe_z_get_expanded_key_from_key(zn, &key, false); } } ret = key._id; diff --git a/src/session/rx.c b/src/session/rx.c index 54dc8983f..70213b898 100644 --- a/src/session/rx.c +++ b/src/session/rx.c @@ -159,6 +159,5 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * } } } - _z_msg_clear(msg); return ret; } diff --git a/src/session/subscription.c b/src/session/subscription.c index db397367f..3e6297176 100644 --- a/src/session/subscription.c +++ b/src/session/subscription.c @@ -29,6 +29,57 @@ #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_SUBSCRIPTION == 1 + +#define _Z_SUBINFOS_VEC_SIZE 4 // Arbitrary initial size + +#if Z_FEATURE_RX_CACHE == 1 +static inline bool _z_subscription_get_from_cache(_z_session_t *zn, const _z_keyexpr_t *ke, _z_keyexpr_t *ke_val, + _z_subscription_infos_svec_t *infos_val) { + if (!_z_keyexpr_equals(ke, &zn->_subscription_cache.ke_in)) { + return false; + } + *ke_val = _z_keyexpr_alias(zn->_subscription_cache.ke_out); + *infos_val = _z_subscription_infos_svec_alias(&zn->_subscription_cache.infos); + return true; +} + +static inline void _z_subscription_update_cache(_z_session_t *zn, const _z_keyexpr_t *ke_in, const _z_keyexpr_t *ke_out, + _z_subscription_infos_svec_t *infos) { + // Clear previous data + _z_subscription_cache_clear(&zn->_subscription_cache); + // Register new info + zn->_subscription_cache.ke_in = _z_keyexpr_duplicate(ke_in); + zn->_subscription_cache.ke_out = _z_keyexpr_duplicate(ke_out); + zn->_subscription_cache.infos = _z_subscription_infos_svec_alias(infos); +} + +void _z_subscription_cache_clear(_z_subscription_cache_t *cache) { + _z_subscription_infos_svec_clear(&cache->infos); + _z_keyexpr_clear(&cache->ke_in); + _z_keyexpr_clear(&cache->ke_out); +} + +#else +static inline bool _z_subscription_get_from_cache(_z_session_t *zn, const _z_keyexpr_t *ke, _z_keyexpr_t *ke_val, + _z_subscription_infos_svec_t *infos_val) { + _ZP_UNUSED(zn); + _ZP_UNUSED(ke); + _ZP_UNUSED(ke_val); + _ZP_UNUSED(infos_val); + return false; +} + +static inline void _z_subscription_update_cache(_z_session_t *zn, const _z_keyexpr_t *ke_in, const _z_keyexpr_t *ke_out, + _z_subscription_infos_svec_t *infos) { + _ZP_UNUSED(zn); + _ZP_UNUSED(ke_in); + _ZP_UNUSED(ke_out); + _ZP_UNUSED(infos); + return; +} +#endif // Z_FEATURE_RX_CACHE == 1 + +// Subscription bool _z_subscription_eq(const _z_subscription_t *other, const _z_subscription_t *this_) { return this_->_id == other->_id; } @@ -57,22 +108,6 @@ _z_subscription_rc_t *__z_get_subscription_by_id(_z_subscription_rc_list_t *subs return ret; } -_z_subscription_rc_list_t *__z_get_subscriptions_by_key(_z_subscription_rc_list_t *subs, const _z_keyexpr_t *key) { - _z_subscription_rc_list_t *ret = NULL; - - _z_subscription_rc_list_t *xs = subs; - while (xs != NULL) { - _z_subscription_rc_t *sub = _z_subscription_rc_list_head(xs); - if (_z_keyexpr_suffix_intersects(&_Z_RC_IN_VAL(sub)->_key, key) == true) { - ret = _z_subscription_rc_list_push(ret, _z_subscription_rc_clone_as_ptr(sub)); - } - - xs = _z_subscription_rc_list_tail(xs); - } - - return ret; -} - /** * This function is unsafe because it operates in potentially concurrent data. * Make sure that the following mutexes are locked before calling this function: @@ -89,11 +124,24 @@ _z_subscription_rc_t *__unsafe_z_get_subscription_by_id(_z_session_t *zn, uint8_ * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_subscription_rc_list_t *__unsafe_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, - const _z_keyexpr_t *key) { +static z_result_t __unsafe_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *key, + _z_subscription_infos_svec_t *sub_infos) { _z_subscription_rc_list_t *subs = (is_local == _Z_RESOURCE_IS_LOCAL) ? zn->_local_subscriptions : zn->_remote_subscriptions; - return __z_get_subscriptions_by_key(subs, key); + + *sub_infos = _z_subscription_infos_svec_make(_Z_SUBINFOS_VEC_SIZE); + _z_subscription_rc_list_t *xs = subs; + while (xs != NULL) { + // Parse subscription list + _z_subscription_rc_t *sub = _z_subscription_rc_list_head(xs); + if (_z_keyexpr_suffix_intersects(&_Z_RC_IN_VAL(sub)->_key, key)) { + _z_subscription_infos_t new_sub_info = {.arg = _Z_RC_IN_VAL(sub)->_arg, + .callback = _Z_RC_IN_VAL(sub)->_callback}; + _Z_RETURN_IF_ERR(_z_subscription_infos_svec_append(sub_infos, &new_sub_info)); + } + xs = _z_subscription_rc_list_tail(xs); + } + return _Z_RES_OK; } _z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id) { @@ -106,16 +154,6 @@ _z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_loc return sub; } -_z_subscription_rc_list_t *_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *key) { - _z_session_mutex_lock(zn); - - _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, is_local, key); - - _z_session_mutex_unlock(zn); - - return subs; -} - _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_t *s) { _Z_DEBUG(">>> Allocating sub decl for (%ju:%.*s)", (uintmax_t)s->_key._id, (int)_z_string_len(&s->_key._suffix), _z_string_data(&s->_key._suffix)); @@ -138,53 +176,60 @@ _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_loca return ret; } -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, const _z_bytes_t *payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - const _z_bytes_t *attachment, z_reliability_t reliability) { + _z_bytes_t *attachment, z_reliability_t reliability) { z_result_t ret = _z_trigger_subscriptions(zn, keyexpr, payload, encoding, Z_SAMPLE_KIND_PUT, timestamp, qos, attachment, reliability); (void)ret; } -z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, const _z_bytes_t *payload, +z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, - const _z_n_qos_t qos, const _z_bytes_t *attachment, z_reliability_t reliability) { - z_result_t ret = _Z_RES_OK; - - _z_session_mutex_lock(zn); - - _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr->_id, (int)_z_string_len(&keyexpr->_suffix), - _z_string_data(&keyexpr->_suffix), _z_keyexpr_mapping_id(keyexpr)); - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr); - _Z_DEBUG("Triggering subs for %d - %.*s", key._id, (int)_z_string_len(&key._suffix), _z_string_data(&key._suffix)); - if (_z_keyexpr_has_suffix(&key)) { - _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, &key); - _z_session_mutex_unlock(zn); - - // Check if there is subs - size_t sub_nb = _z_subscription_rc_list_len(subs); - if (sub_nb == 0) { - return _Z_RES_OK; - } - // Build the sample - _z_sample_t sample = _z_sample_create(&key, payload, timestamp, encoding, kind, qos, attachment, reliability); - // Parse subscription list - _z_subscription_rc_list_t *xs = subs; - _Z_DEBUG("Triggering %ju subs", (uintmax_t)sub_nb); - while (xs != NULL) { - _z_subscription_rc_t *sub = _z_subscription_rc_list_head(xs); - _Z_RC_IN_VAL(sub)->_callback(&sample, _Z_RC_IN_VAL(sub)->_arg); - xs = _z_subscription_rc_list_tail(xs); + const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability) { + _z_sample_t sample; + _z_keyexpr_t key; + _z_subscription_infos_svec_t subs; + // Check cache + if (!_z_subscription_get_from_cache(zn, keyexpr, &key, &subs)) { + _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr->_id, (int)_z_string_len(&keyexpr->_suffix), + _z_string_data(&keyexpr->_suffix), _z_keyexpr_mapping_id(keyexpr)); + _z_session_mutex_lock(zn); + key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, true); + + if (!_z_keyexpr_has_suffix(&key)) { + _z_session_mutex_unlock(zn); + return _Z_ERR_KEYEXPR_UNKNOWN; } - // Clean up - _z_sample_clear(&sample); - _z_subscription_rc_list_free(&subs); - } else { + // Get subscription list + z_result_t ret = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, &key, &subs); _z_session_mutex_unlock(zn); - ret = _Z_ERR_KEYEXPR_UNKNOWN; + if (ret != _Z_RES_OK) { + return ret; + } + // Update cache + _z_subscription_update_cache(zn, keyexpr, &key, &subs); } - - return ret; + // Check if there is subs + size_t sub_nb = _z_subscription_infos_svec_len(&subs); + _Z_DEBUG("Triggering %ju subs for key %d - %.*s", (uintmax_t)sub_nb, key._id, (int)_z_string_len(&key._suffix), + _z_string_data(&key._suffix)); + if (sub_nb == 0) { + return _Z_RES_OK; + } + // Build the sample + _z_sample_create(&sample, &key, payload, timestamp, encoding, kind, qos, attachment, reliability); + // Parse subscription infos svec + for (size_t i = 0; i < sub_nb; i++) { + _z_subscription_infos_t *sub_info = _z_subscription_infos_svec_get(&subs, i); + sub_info->callback(&sample, sub_info->arg); + } + // Clean up + _z_sample_clear(&sample); +#if Z_FEATURE_RX_CACHE != 1 + _z_subscription_infos_svec_release(&subs); // Otherwise it's released with cache +#endif + return _Z_RES_OK; } void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub) { @@ -211,9 +256,9 @@ void _z_flush_subscriptions(_z_session_t *zn) { } #else // Z_FEATURE_SUBSCRIPTION == 0 -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, const _z_bytes_t *payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - const _z_bytes_t *attachment, z_reliability_t reliability) { + _z_bytes_t *attachment, z_reliability_t reliability) { _ZP_UNUSED(zn); _ZP_UNUSED(keyexpr); _ZP_UNUSED(payload); diff --git a/src/session/utils.c b/src/session/utils.c index 0a2cff984..dde52129c 100644 --- a/src/session/utils.c +++ b/src/session/utils.c @@ -60,6 +60,9 @@ z_result_t _z_session_init(_z_session_rc_t *zsrc, _z_id_t *zid) { #if Z_FEATURE_SUBSCRIPTION == 1 zn->_local_subscriptions = NULL; zn->_remote_subscriptions = NULL; +#if Z_FEATURE_RX_CACHE == 1 + memset(&zn->_subscription_cache, 0, sizeof(zn->_subscription_cache)); +#endif #endif #if Z_FEATURE_QUERYABLE == 1 zn->_local_queryable = NULL; @@ -111,6 +114,9 @@ void _z_session_clear(_z_session_t *zn) { _z_flush_resources(zn); #if Z_FEATURE_SUBSCRIPTION == 1 _z_flush_subscriptions(zn); +#if Z_FEATURE_RX_CACHE == 1 + _z_subscription_cache_clear(&zn->_subscription_cache); +#endif #endif #if Z_FEATURE_QUERYABLE == 1 _z_flush_session_queryable(zn); diff --git a/src/transport/multicast/rx.c b/src/transport/multicast/rx.c index d10d9709f..c1f438c38 100644 --- a/src/transport/multicast/rx.c +++ b/src/transport/multicast/rx.c @@ -130,9 +130,10 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, } // Note that we receive data from peer entry->_received = true; - + z_reliability_t tmsg_reliability; // Check if the SN is correct if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAME_R) == true) { + tmsg_reliability = Z_RELIABILITY_RELIABLE; // @TODO: amend once reliability is in place. For the time being only // monotonic SNs are ensured if (_z_sn_precedes(entry->_sn_res, entry->_sn_rx_sns._val._plain._reliable, t_msg->_body._frame._sn) == @@ -147,6 +148,7 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, break; } } else { + tmsg_reliability = Z_RELIABILITY_BEST_EFFORT; if (_z_sn_precedes(entry->_sn_res, entry->_sn_rx_sns._val._plain._best_effort, t_msg->_body._frame._sn) == true) { entry->_sn_rx_sns._val._plain._best_effort = t_msg->_body._frame._sn; @@ -162,10 +164,10 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, // Handle all the zenoh message, one by one uint16_t mapping = entry->_peer_id; - size_t len = _z_vec_len(&t_msg->_body._frame._messages); + size_t len = _z_svec_len(&t_msg->_body._frame._messages); for (size_t i = 0; i < len; i++) { - _z_network_message_t *zm = _z_network_message_vec_get(&t_msg->_body._frame._messages, i); - zm->_reliability = _z_t_msg_get_reliability(t_msg); + _z_network_message_t *zm = _z_network_message_svec_get(&t_msg->_body._frame._messages, i); + zm->_reliability = tmsg_reliability; _z_msg_fix_mapping(zm, mapping); _z_handle_network_message(ztm->_common._session, zm, mapping); @@ -186,11 +188,14 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_wbuf_t *dbuf; uint8_t *dbuf_state; + z_reliability_t tmsg_reliability; // Select the right defragmentation buffer if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R)) { + tmsg_reliability = Z_RELIABILITY_RELIABLE; dbuf = &entry->_dbuf_reliable; dbuf_state = &entry->_state_reliable; } else { + tmsg_reliability = Z_RELIABILITY_BEST_EFFORT; dbuf = &entry->_dbuf_best_effort; dbuf_state = &entry->_state_best_effort; } @@ -234,9 +239,9 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, break; } // Decode message - _z_zenoh_message_t zm; + _z_zenoh_message_t zm = {0}; ret = _z_network_message_decode(&zm, &zbf); - zm._reliability = _z_t_msg_get_reliability(t_msg); + zm._reliability = tmsg_reliability; if (ret == _Z_RES_OK) { uint16_t mapping = entry->_peer_id; _z_msg_fix_mapping(&zm, mapping); diff --git a/src/transport/unicast/rx.c b/src/transport/unicast/rx.c index ca9591bba..1d30e988f 100644 --- a/src/transport/unicast/rx.c +++ b/src/transport/unicast/rx.c @@ -96,8 +96,10 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t switch (_Z_MID(t_msg->_header)) { case _Z_MID_T_FRAME: { _Z_DEBUG("Received Z_FRAME message"); + z_reliability_t tmsg_reliability; // Check if the SN is correct if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAME_R) == true) { + tmsg_reliability = Z_RELIABILITY_RELIABLE; // @TODO: amend once reliability is in place. For the time being only // monotonic SNs are ensured if (_z_sn_precedes(ztu->_common._sn_res, ztu->_sn_rx_reliable, t_msg->_body._frame._sn) == true) { @@ -111,6 +113,7 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t break; } } else { + tmsg_reliability = Z_RELIABILITY_BEST_EFFORT; if (_z_sn_precedes(ztu->_common._sn_res, ztu->_sn_rx_best_effort, t_msg->_body._frame._sn) == true) { ztu->_sn_rx_best_effort = t_msg->_body._frame._sn; } else { @@ -124,10 +127,10 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t } // Handle all the zenoh message, one by one - size_t len = _z_vec_len(&t_msg->_body._frame._messages); + size_t len = _z_svec_len(&t_msg->_body._frame._messages); for (size_t i = 0; i < len; i++) { - _z_network_message_t *zm = _z_network_message_vec_get(&t_msg->_body._frame._messages, i); - zm->_reliability = _z_t_msg_get_reliability(t_msg); + _z_network_message_t *zm = _z_network_message_svec_get(&t_msg->_body._frame._messages, i); + zm->_reliability = tmsg_reliability; _z_handle_network_message(ztu->_common._session, zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); } @@ -139,11 +142,14 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t #if Z_FEATURE_FRAGMENTATION == 1 _z_wbuf_t *dbuf; uint8_t *dbuf_state; + z_reliability_t tmsg_reliability; // Select the right defragmentation buffer if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R)) { + tmsg_reliability = Z_RELIABILITY_RELIABLE; dbuf = &ztu->_dbuf_reliable; dbuf_state = &ztu->_state_reliable; } else { + tmsg_reliability = Z_RELIABILITY_BEST_EFFORT; dbuf = &ztu->_dbuf_best_effort; dbuf_state = &ztu->_state_best_effort; } @@ -187,9 +193,9 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t break; } // Decode message - _z_zenoh_message_t zm; + _z_zenoh_message_t zm = {0}; ret = _z_network_message_decode(&zm, &zbf); - zm._reliability = _z_t_msg_get_reliability(t_msg); + zm._reliability = tmsg_reliability; if (ret == _Z_RES_OK) { _z_handle_network_message(ztu->_common._session, &zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); } else { diff --git a/tests/z_msgcodec_test.c b/tests/z_msgcodec_test.c index c881f8f4e..f3a92a77a 100644 --- a/tests/z_msgcodec_test.c +++ b/tests/z_msgcodec_test.c @@ -554,7 +554,7 @@ void payload_field(void) { // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_bytes_t d_pld; + _z_bytes_t d_pld = _z_bytes_null(); res = _z_bytes_decode(&d_pld, &zbf); assert(res == _Z_RES_OK); printf(" "); @@ -1140,7 +1140,7 @@ void interest_message(void) { // Encode assert(_z_n_interest_encode(&wbf, &expected._body._interest) == _Z_RES_OK); // Decode - _z_n_msg_interest_t decoded; + _z_n_msg_interest_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); assert(_z_n_interest_decode(&decoded, &zbf, header) == _Z_RES_OK); @@ -1236,7 +1236,7 @@ void query_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_msg_query_t expected = gen_query(); assert(_z_query_encode(&wbf, &expected) == _Z_RES_OK); - _z_msg_query_t decoded; + _z_msg_query_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); z_result_t res = _z_query_decode(&decoded, &zbf, header); @@ -1268,7 +1268,7 @@ void err_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_msg_err_t expected = gen_err(); assert(_z_err_encode(&wbf, &expected) == _Z_RES_OK); - _z_msg_err_t decoded; + _z_msg_err_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); assert(_Z_RES_OK == _z_err_decode(&decoded, &zbf, header)); @@ -1296,7 +1296,7 @@ void reply_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_msg_reply_t expected = gen_reply(); assert(_z_reply_encode(&wbf, &expected) == _Z_RES_OK); - _z_msg_reply_t decoded; + _z_msg_reply_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); assert(_Z_RES_OK == _z_reply_decode(&decoded, &zbf, header)); @@ -1328,7 +1328,7 @@ void push_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_n_msg_push_t expected = gen_push(); assert(_z_push_encode(&wbf, &expected) == _Z_RES_OK); - _z_n_msg_push_t decoded; + _z_n_msg_push_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); assert(_Z_RES_OK == _z_push_decode(&decoded, &zbf, header)); @@ -1398,7 +1398,7 @@ void request_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_n_msg_request_t expected = gen_request(); assert(_z_request_encode(&wbf, &expected) == _Z_RES_OK); - _z_n_msg_request_t decoded; + _z_n_msg_request_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); z_result_t ret = _z_request_decode(&decoded, &zbf, header); @@ -1456,7 +1456,7 @@ void response_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_n_msg_response_t expected = gen_response(); assert(_z_response_encode(&wbf, &expected) == _Z_RES_OK); - _z_n_msg_response_t decoded; + _z_n_msg_response_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); z_result_t ret = _z_response_decode(&decoded, &zbf, header); @@ -1477,7 +1477,7 @@ void response_final_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_n_msg_response_final_t expected = gen_response_final(); assert(_z_response_final_encode(&wbf, &expected) == _Z_RES_OK); - _z_n_msg_response_final_t decoded; + _z_n_msg_response_final_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); z_result_t ret = _z_response_final_decode(&decoded, &zbf, header); @@ -1526,7 +1526,7 @@ void join_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_join(); assert(_z_join_encode(&wbf, expected._header, &expected._body._join) == _Z_RES_OK); - _z_t_msg_join_t decoded; + _z_t_msg_join_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_join_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1558,7 +1558,7 @@ void init_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_init(); assert(_z_init_encode(&wbf, expected._header, &expected._body._init) == _Z_RES_OK); - _z_t_msg_init_t decoded; + _z_t_msg_init_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_init_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1586,7 +1586,7 @@ void open_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_open(); assert(_z_open_encode(&wbf, expected._header, &expected._body._open) == _Z_RES_OK); - _z_t_msg_open_t decoded; + _z_t_msg_open_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_open_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1606,7 +1606,7 @@ void close_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_close(); assert(_z_close_encode(&wbf, expected._header, &expected._body._close) == _Z_RES_OK); - _z_t_msg_close_t decoded; + _z_t_msg_close_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_close_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1627,7 +1627,7 @@ void keep_alive_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_keep_alive(); assert(_z_keep_alive_encode(&wbf, expected._header, &expected._body._keep_alive) == _Z_RES_OK); - _z_t_msg_keep_alive_t decoded; + _z_t_msg_keep_alive_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_keep_alive_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1688,13 +1688,12 @@ void assert_eq_net_msg(const _z_network_message_t *left, const _z_network_messag break; } } -_z_network_message_vec_t gen_net_msgs(size_t n) { - _z_network_message_vec_t ret = _z_network_message_vec_make(n); +_z_network_message_svec_t gen_net_msgs(size_t n) { + _z_network_message_svec_t ret = _z_network_message_svec_make(n); for (size_t i = 0; i < n; i++) { - _z_network_message_t *msg = (_z_network_message_t *)z_malloc(sizeof(_z_network_message_t)); + _z_network_message_t *msg = _z_network_message_svec_get_mut(&ret, i); memset(msg, 0, sizeof(_z_network_message_t)); *msg = gen_net_msg(); - _z_network_message_vec_append(&ret, msg); } return ret; } @@ -1706,7 +1705,8 @@ void assert_eq_frame(const _z_t_msg_frame_t *left, const _z_t_msg_frame_t *right assert(left->_sn == right->_sn); assert(left->_messages._len == right->_messages._len); for (size_t i = 0; i < left->_messages._len; i++) { - assert_eq_net_msg(left->_messages._val[i], right->_messages._val[i]); + assert_eq_net_msg(_z_network_message_svec_get(&left->_messages, i), + _z_network_message_svec_get(&right->_messages, i)); } } void frame_message(void) { @@ -1714,7 +1714,7 @@ void frame_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_frame(); assert(_z_frame_encode(&wbf, expected._header, &expected._body._frame) == _Z_RES_OK); - _z_t_msg_frame_t decoded; + _z_t_msg_frame_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_frame_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1737,7 +1737,7 @@ void fragment_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_fragment(); assert(_z_fragment_encode(&wbf, expected._header, &expected._body._fragment) == _Z_RES_OK); - _z_t_msg_fragment_t decoded; + _z_t_msg_fragment_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_fragment_decode(&decoded, &zbf, expected._header); assert(_Z_RES_OK == ret); @@ -1807,7 +1807,7 @@ void transport_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_transport_message_t expected = gen_transport(); assert(_z_transport_message_encode(&wbf, &expected) == _Z_RES_OK); - _z_transport_message_t decoded; + _z_transport_message_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_transport_message_decode(&decoded, &zbf); assert(_Z_RES_OK == ret); @@ -1849,7 +1849,7 @@ void scouting_message(void) { _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); _z_scouting_message_t expected = gen_scouting(); assert(_z_scouting_message_encode(&wbf, &expected) == _Z_RES_OK); - _z_scouting_message_t decoded; + _z_scouting_message_t decoded = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); z_result_t ret = _z_scouting_message_decode(&decoded, &zbf); assert(_Z_RES_OK == ret); From 0f1ce95635555db65edbcc83ae6e64204199703b Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Wed, 13 Nov 2024 15:19:31 +0100 Subject: [PATCH 11/17] Improve query/reply perf (#781) * fix: remove superfluous rc init * feat: lazify svec release * refactor: rename slice_empty as slice_null * feat: rework svec expand * refactor: z_bytes_append_slice * feat: lazify arc slice * feat: improve stirng/slice move * feat: lazify sample timestamp set * feat: add non-reader decode functions * feat: remove superfluous keyexpr clear * feat: add bytes alias arc * feat: add rx pool size config option * feat: use transport arc slice pool for payload decode * feat: n msg svec is now a transport resource pool * fix: add offset to svec init * feat: make svec use elem f a per call arg * feat: skip ke suffix check * fix: arc pool * feat: improve sub perf and readability * feat: add z_string_alias_slice function * feat: align queryable with subscription * feat: align reply with sub & queryables * feat: nothing to clear in frame * fix: reply clean up * feat: streamline replies * feat: query is not a rc and store a session rc * fix: ci issues * fix: attachment examples * fix: keyexpr equals * fix: flaky test --- examples/unix/c11/z_get_attachment.c | 7 +- examples/unix/c11/z_queryable_attachment.c | 7 +- examples/unix/c11/z_sub_attachment.c | 8 +- include/zenoh-pico/api/types.h | 2 +- include/zenoh-pico/collections/bytes.h | 6 +- include/zenoh-pico/collections/refcount.h | 27 +-- include/zenoh-pico/collections/slice.h | 4 +- include/zenoh-pico/collections/string.h | 3 +- include/zenoh-pico/collections/vec.h | 72 ++++--- include/zenoh-pico/config.h | 5 - include/zenoh-pico/config.h.in | 5 - include/zenoh-pico/net/query.h | 29 ++- include/zenoh-pico/net/reply.h | 26 ++- include/zenoh-pico/net/sample.h | 19 +- include/zenoh-pico/net/session.h | 4 + include/zenoh-pico/protocol/codec/core.h | 2 +- include/zenoh-pico/protocol/codec/message.h | 8 +- include/zenoh-pico/protocol/codec/network.h | 8 +- include/zenoh-pico/protocol/codec/transport.h | 8 +- include/zenoh-pico/protocol/core.h | 7 +- .../zenoh-pico/protocol/definitions/network.h | 4 +- include/zenoh-pico/session/query.h | 2 +- include/zenoh-pico/session/queryable.h | 27 ++- include/zenoh-pico/session/reply.h | 2 +- include/zenoh-pico/session/session.h | 4 +- include/zenoh-pico/session/subscription.h | 7 +- include/zenoh-pico/transport/transport.h | 4 + src/api/api.c | 54 ++--- src/collections/arc_slice.c | 5 +- src/collections/bytes.c | 16 +- src/collections/slice.c | 9 +- src/collections/string.c | 8 +- src/collections/vec.c | 18 +- src/net/query.c | 36 +--- src/net/reply.c | 53 +---- src/net/sample.c | 31 +-- src/net/session.c | 4 +- src/protocol/codec.c | 49 +++-- src/protocol/codec/message.c | 18 +- src/protocol/codec/network.c | 22 +- src/protocol/codec/transport.c | 97 ++++++--- src/protocol/core.c | 2 +- src/protocol/definitions/message.c | 5 +- src/protocol/definitions/transport.c | 6 +- src/protocol/keyexpr.c | 11 +- src/session/query.c | 132 +++++------- src/session/queryable.c | 200 +++++++++++++----- src/session/reply.c | 2 +- src/session/rx.c | 5 +- src/session/scout.c | 2 +- src/session/subscription.c | 67 ++++-- src/session/utils.c | 8 + src/transport/common/rx.c | 6 +- src/transport/multicast/read.c | 3 +- src/transport/multicast/rx.c | 6 +- src/transport/multicast/transport.c | 9 +- src/transport/raweth/rx.c | 2 +- src/transport/unicast/read.c | 3 +- src/transport/unicast/rx.c | 6 +- src/transport/unicast/transport.c | 11 +- tests/modularity.py | 18 +- tests/z_msgcodec_test.c | 38 ++-- 62 files changed, 711 insertions(+), 558 deletions(-) diff --git a/examples/unix/c11/z_get_attachment.c b/examples/unix/c11/z_get_attachment.c index 65404138b..2d7ddcccc 100644 --- a/examples/unix/c11/z_get_attachment.c +++ b/examples/unix/c11/z_get_attachment.c @@ -68,12 +68,11 @@ void reply_handler(z_loaned_reply_t *reply, void *ctx) { // Check attachment const z_loaned_bytes_t *attachment = z_sample_attachment(sample); - if (attachment == NULL) { - return; - } ze_deserializer_t deserializer = ze_deserializer_from_bytes(attachment); size_t attachment_len; - ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len); + if (ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len) < 0) { + return; + } kv_pair_t *kvp = (kv_pair_t *)malloc(sizeof(kv_pair_t) * attachment_len); for (size_t i = 0; i < attachment_len; ++i) { ze_deserializer_deserialize_string(&deserializer, &kvp[i].key); diff --git a/examples/unix/c11/z_queryable_attachment.c b/examples/unix/c11/z_queryable_attachment.c index 20a2e9ad2..ace30bb48 100644 --- a/examples/unix/c11/z_queryable_attachment.c +++ b/examples/unix/c11/z_queryable_attachment.c @@ -68,10 +68,9 @@ void query_handler(z_loaned_query_t *query, void *ctx) { // Check attachment const z_loaned_bytes_t *attachment = z_query_attachment(query); - if (attachment != NULL) { - ze_deserializer_t deserializer = ze_deserializer_from_bytes(attachment); - size_t attachment_len; - ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len); + ze_deserializer_t deserializer = ze_deserializer_from_bytes(attachment); + size_t attachment_len; + if (ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len) == Z_OK) { kv_pair_t *kvp = (kv_pair_t *)malloc(sizeof(kv_pair_t) * attachment_len); for (size_t i = 0; i < attachment_len; ++i) { ze_deserializer_deserialize_string(&deserializer, &kvp[i].key); diff --git a/examples/unix/c11/z_sub_attachment.c b/examples/unix/c11/z_sub_attachment.c index 5720f86fd..823280673 100644 --- a/examples/unix/c11/z_sub_attachment.c +++ b/examples/unix/c11/z_sub_attachment.c @@ -64,12 +64,10 @@ void data_handler(z_loaned_sample_t *sample, void *ctx) { printf(" with timestamp: %" PRIu64 "\n", z_timestamp_ntp64_time(ts)); } // Check attachment - const z_loaned_bytes_t *attachment = z_sample_attachment(sample); - if (attachment != NULL) { - ze_deserializer_t deserializer = ze_deserializer_from_bytes(attachment); - size_t attachment_len; - ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len); + ze_deserializer_t deserializer = ze_deserializer_from_bytes(attachment); + size_t attachment_len; + if (ze_deserializer_deserialize_sequence_length(&deserializer, &attachment_len) == Z_OK) { kv_pair_t *kvp = (kv_pair_t *)malloc(sizeof(kv_pair_t) * attachment_len); for (size_t i = 0; i < attachment_len; ++i) { ze_deserializer_deserialize_string(&deserializer, &kvp[i].key); diff --git a/include/zenoh-pico/api/types.h b/include/zenoh-pico/api/types.h index 53010ece7..26c703161 100644 --- a/include/zenoh-pico/api/types.h +++ b/include/zenoh-pico/api/types.h @@ -125,7 +125,7 @@ _Z_OWNED_TYPE_VALUE(_z_queryable_t, queryable) /** * Represents a Zenoh Query entity, received by Zenoh Queryable entities. */ -_Z_OWNED_TYPE_RC(_z_query_rc_t, query) +_Z_OWNED_TYPE_VALUE(_z_query_t, query) /** * Represents the encoding of a payload, in a MIME-like format. diff --git a/include/zenoh-pico/collections/bytes.h b/include/zenoh-pico/collections/bytes.h index 9f3ad16ef..fa2ea573c 100644 --- a/include/zenoh-pico/collections/bytes.h +++ b/include/zenoh-pico/collections/bytes.h @@ -28,7 +28,7 @@ inline size_t _z_arc_slice_size(const _z_arc_slice_t *s) { return sizeof(_z_arc_slice_t); } _Z_ELEM_DEFINE(_z_arc_slice, _z_arc_slice_t, _z_arc_slice_size, _z_arc_slice_drop, _z_arc_slice_copy, _z_arc_slice_move) -_Z_SVEC_DEFINE(_z_arc_slice, _z_arc_slice_t, true) +_Z_SVEC_DEFINE(_z_arc_slice, _z_arc_slice_t) /*-------- Bytes --------*/ /** @@ -44,6 +44,9 @@ typedef struct { // Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. static inline _z_bytes_t _z_bytes_null(void) { return (_z_bytes_t){0}; } +static inline void _z_bytes_alias_arc_slice(_z_bytes_t *dst, _z_arc_slice_t *s) { + dst->_slices = _z_arc_slice_svec_alias_element(s); +} bool _z_bytes_check(const _z_bytes_t *bytes); z_result_t _z_bytes_append_bytes(_z_bytes_t *dst, _z_bytes_t *src); z_result_t _z_bytes_append_slice(_z_bytes_t *dst, _z_arc_slice_t *s); @@ -51,6 +54,7 @@ z_result_t _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src); _z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src); void _z_bytes_move(_z_bytes_t *dst, _z_bytes_t *src); void _z_bytes_drop(_z_bytes_t *bytes); +void _z_bytes_aliased_drop(_z_bytes_t *bytes); void _z_bytes_free(_z_bytes_t **bs); size_t _z_bytes_num_slices(const _z_bytes_t *bs); _z_arc_slice_t *_z_bytes_get_slice(const _z_bytes_t *bs, size_t i); diff --git a/include/zenoh-pico/collections/refcount.h b/include/zenoh-pico/collections/refcount.h index bcbd8f411..f1ad023f0 100644 --- a/include/zenoh-pico/collections/refcount.h +++ b/include/zenoh-pico/collections/refcount.h @@ -76,11 +76,10 @@ size_t _z_simple_rc_strong_count(void *cnt); return p; \ } \ static inline name##_rc_t name##_rc_clone(const name##_rc_t *p) { \ - name##_rc_t c = name##_rc_null(); \ if (_z_rc_increase_strong(p->_cnt) == _Z_RES_OK) { \ - c = *p; \ + return *p; \ } \ - return c; \ + return name##_rc_null(); \ } \ static inline name##_rc_t *name##_rc_clone_as_ptr(const name##_rc_t *p) { \ name##_rc_t *c = (name##_rc_t *)z_malloc(sizeof(name##_rc_t)); \ @@ -93,12 +92,10 @@ size_t _z_simple_rc_strong_count(void *cnt); return c; \ } \ static inline name##_weak_t name##_rc_clone_as_weak(const name##_rc_t *p) { \ - name##_weak_t c = name##_weak_null(); \ if (_z_rc_increase_weak(p->_cnt) == _Z_RES_OK) { \ - c._val = p->_val; \ - c._cnt = p->_cnt; \ + return (name##_weak_t){._val = p->_val, ._cnt = p->_cnt}; \ } \ - return c; \ + return name##_weak_null(); \ } \ static inline name##_weak_t *name##_rc_clone_as_weak_ptr(const name##_rc_t *p) { \ name##_weak_t *c = (name##_weak_t *)z_malloc(sizeof(name##_weak_t)); \ @@ -137,20 +134,17 @@ size_t _z_simple_rc_strong_count(void *cnt); return res; \ } \ static inline name##_weak_t name##_weak_clone(const name##_weak_t *p) { \ - name##_weak_t c = name##_weak_null(); \ if (_z_rc_increase_weak(p->_cnt) == _Z_RES_OK) { \ - c = *p; \ + return *p; \ } \ - return c; \ + return name##_weak_null(); \ } \ static inline void name##_weak_copy(name##_weak_t *dst, const name##_weak_t *p) { *dst = name##_weak_clone(p); } \ static inline name##_rc_t name##_weak_upgrade(const name##_weak_t *p) { \ - name##_rc_t c = name##_rc_null(); \ if (_z_rc_weak_upgrade(p->_cnt) == _Z_RES_OK) { \ - c._val = p->_val; \ - c._cnt = p->_cnt; \ + return (name##_rc_t){._val = p->_val, ._cnt = p->_cnt}; \ } \ - return c; \ + return name##_rc_null(); \ } \ static inline bool name##_weak_eq(const name##_weak_t *left, const name##_weak_t *right) { \ return (left->_val == right->_val); \ @@ -200,11 +194,10 @@ size_t _z_simple_rc_strong_count(void *cnt); return p; \ } \ static inline name##_simple_rc_t name##_simple_rc_clone(const name##_simple_rc_t *p) { \ - name##_simple_rc_t c = name##_simple_rc_null(); \ if (_z_simple_rc_increase(p->_cnt) == _Z_RES_OK) { \ - c = *p; \ + return *p; \ } \ - return c; \ + return name##_simple_rc_null(); \ } \ static inline name##_simple_rc_t *name##_simple_rc_clone_as_ptr(const name##_simple_rc_t *p) { \ name##_simple_rc_t *c = (name##_simple_rc_t *)z_malloc(sizeof(name##_simple_rc_t)); \ diff --git a/include/zenoh-pico/collections/slice.h b/include/zenoh-pico/collections/slice.h index 00101c185..58bc8d610 100644 --- a/include/zenoh-pico/collections/slice.h +++ b/include/zenoh-pico/collections/slice.h @@ -51,8 +51,8 @@ typedef struct { _z_delete_context_t _delete_context; } _z_slice_t; -static inline _z_slice_t _z_slice_empty(void) { return (_z_slice_t){0}; } -static inline void _z_slice_reset(_z_slice_t *bs) { *bs = _z_slice_empty(); } +static inline _z_slice_t _z_slice_null(void) { return (_z_slice_t){0}; } +static inline void _z_slice_reset(_z_slice_t *bs) { *bs = _z_slice_null(); } static inline bool _z_slice_is_empty(const _z_slice_t *bs) { return bs->len == 0; } static inline bool _z_slice_check(const _z_slice_t *slice) { return slice->start != NULL; } static inline _z_slice_t _z_slice_alias(const _z_slice_t bs) { diff --git a/include/zenoh-pico/collections/string.h b/include/zenoh-pico/collections/string.h index 37c1a218b..6291db854 100644 --- a/include/zenoh-pico/collections/string.h +++ b/include/zenoh-pico/collections/string.h @@ -76,6 +76,7 @@ static inline _z_string_t _z_string_alias(const _z_string_t str) { _z_string_t _z_string_copy_from_str(const char *value); _z_string_t _z_string_copy_from_substr(const char *value, size_t len); _z_string_t *_z_string_copy_from_str_as_ptr(const char *value); +_z_string_t _z_string_alias_slice(const _z_slice_t *slice); _z_string_t _z_string_alias_str(const char *value); _z_string_t _z_string_alias_substr(const char *value, size_t len); _z_string_t _z_string_from_str_custom_deleter(char *value, _z_delete_context_t c); @@ -98,7 +99,7 @@ _z_string_t _z_string_convert_bytes(const _z_slice_t *bs); _z_string_t _z_string_preallocate(const size_t len); _Z_ELEM_DEFINE(_z_string, _z_string_t, _z_string_len, _z_string_clear, _z_string_copy, _z_string_move) -_Z_SVEC_DEFINE(_z_string, _z_string_t, true) +_Z_SVEC_DEFINE(_z_string, _z_string_t) _Z_LIST_DEFINE(_z_string, _z_string_t) _Z_INT_MAP_DEFINE(_z_string, _z_string_t) diff --git a/include/zenoh-pico/collections/vec.h b/include/zenoh-pico/collections/vec.h index 3d5e48605..c3d9ff525 100644 --- a/include/zenoh-pico/collections/vec.h +++ b/include/zenoh-pico/collections/vec.h @@ -81,7 +81,10 @@ typedef struct { static inline _z_svec_t _z_svec_null(void) { return (_z_svec_t){0}; } static inline _z_svec_t _z_svec_alias(const _z_svec_t *src) { return *src; } -void _z_svec_init(_z_svec_t *dst, size_t element_size); +static inline _z_svec_t _z_svec_alias_element(void *element) { + return (_z_svec_t){._capacity = 1, ._len = 1, ._val = element}; +} +void _z_svec_init(_z_svec_t *v, size_t offset, size_t element_size); _z_svec_t _z_svec_make(size_t capacity, size_t element_size); z_result_t _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size, bool use_elem_f); @@ -103,39 +106,40 @@ void _z_svec_clear(_z_svec_t *v, z_element_clear_f f, size_t element_size); void _z_svec_free(_z_svec_t **v, z_element_clear_f f, size_t element_size); void _z_svec_release(_z_svec_t *v); -#define _Z_SVEC_DEFINE(name, type, use_elem_f) \ - typedef _z_svec_t name##_svec_t; \ - static inline name##_svec_t name##_svec_null(void) { return _z_svec_null(); } \ - static inline name##_svec_t name##_svec_make(size_t capacity) { return _z_svec_make(capacity, sizeof(type)); } \ - static inline void name##_svec_init(name##_svec_t *v) { _z_svec_init(v, sizeof(type)); } \ - static inline size_t name##_svec_len(const name##_svec_t *v) { return _z_svec_len(v); } \ - static inline bool name##_svec_is_empty(const name##_svec_t *v) { return _z_svec_is_empty(v); } \ - static inline z_result_t name##_svec_expand(name##_svec_t *v) { \ - return _z_svec_expand(v, name##_elem_move, sizeof(type), use_elem_f); \ - } \ - static inline z_result_t name##_svec_append(name##_svec_t *v, const type *e) { \ - return _z_svec_append(v, e, name##_elem_move, sizeof(type), use_elem_f); \ - } \ - static inline type *name##_svec_get(const name##_svec_t *v, size_t pos) { \ - return (type *)_z_svec_get(v, pos, sizeof(type)); \ - } \ - static inline type *name##_svec_get_mut(name##_svec_t *v, size_t pos) { \ - return (type *)_z_svec_get_mut(v, pos, sizeof(type)); \ - } \ - static inline void name##_svec_set(name##_svec_t *v, size_t pos, type *e) { \ - _z_svec_set(v, pos, e, name##_elem_clear, sizeof(type)); \ - } \ - static inline void name##_svec_remove(name##_svec_t *v, size_t pos) { \ - _z_svec_remove(v, pos, name##_elem_clear, name##_elem_move, sizeof(type), use_elem_f); \ - } \ - static inline z_result_t name##_svec_copy(name##_svec_t *dst, const name##_svec_t *src) { \ - return _z_svec_copy(dst, src, name##_elem_copy, sizeof(type), use_elem_f); \ - } \ - static inline name##_svec_t name##_svec_alias(const name##_svec_t *v) { return _z_svec_alias(v); } \ - static inline void name##_svec_move(name##_svec_t *dst, name##_svec_t *src) { _z_svec_move(dst, src); } \ - static inline void name##_svec_reset(name##_svec_t *v) { _z_svec_reset(v, name##_elem_clear, sizeof(type)); } \ - static inline void name##_svec_clear(name##_svec_t *v) { _z_svec_clear(v, name##_elem_clear, sizeof(type)); } \ - static inline void name##_svec_release(name##_svec_t *v) { _z_svec_release(v); } \ +#define _Z_SVEC_DEFINE(name, type) \ + typedef _z_svec_t name##_svec_t; \ + static inline name##_svec_t name##_svec_null(void) { return _z_svec_null(); } \ + static inline name##_svec_t name##_svec_make(size_t capacity) { return _z_svec_make(capacity, sizeof(type)); } \ + static inline void name##_svec_init(name##_svec_t *v, size_t offset) { _z_svec_init(v, offset, sizeof(type)); } \ + static inline size_t name##_svec_len(const name##_svec_t *v) { return _z_svec_len(v); } \ + static inline bool name##_svec_is_empty(const name##_svec_t *v) { return _z_svec_is_empty(v); } \ + static inline z_result_t name##_svec_expand(name##_svec_t *v, bool use_elem_f) { \ + return _z_svec_expand(v, name##_elem_move, sizeof(type), use_elem_f); \ + } \ + static inline z_result_t name##_svec_append(name##_svec_t *v, const type *e, bool use_elem_f) { \ + return _z_svec_append(v, e, name##_elem_move, sizeof(type), use_elem_f); \ + } \ + static inline type *name##_svec_get(const name##_svec_t *v, size_t pos) { \ + return (type *)_z_svec_get(v, pos, sizeof(type)); \ + } \ + static inline type *name##_svec_get_mut(name##_svec_t *v, size_t pos) { \ + return (type *)_z_svec_get_mut(v, pos, sizeof(type)); \ + } \ + static inline void name##_svec_set(name##_svec_t *v, size_t pos, type *e) { \ + _z_svec_set(v, pos, e, name##_elem_clear, sizeof(type)); \ + } \ + static inline void name##_svec_remove(name##_svec_t *v, size_t pos, bool use_elem_f) { \ + _z_svec_remove(v, pos, name##_elem_clear, name##_elem_move, sizeof(type), use_elem_f); \ + } \ + static inline z_result_t name##_svec_copy(name##_svec_t *dst, const name##_svec_t *src, bool use_elem_f) { \ + return _z_svec_copy(dst, src, name##_elem_copy, sizeof(type), use_elem_f); \ + } \ + static inline name##_svec_t name##_svec_alias(const name##_svec_t *v) { return _z_svec_alias(v); } \ + static inline name##_svec_t name##_svec_alias_element(type *e) { return _z_svec_alias_element((void *)e); } \ + static inline void name##_svec_move(name##_svec_t *dst, name##_svec_t *src) { _z_svec_move(dst, src); } \ + static inline void name##_svec_reset(name##_svec_t *v) { _z_svec_reset(v, name##_elem_clear, sizeof(type)); } \ + static inline void name##_svec_clear(name##_svec_t *v) { _z_svec_clear(v, name##_elem_clear, sizeof(type)); } \ + static inline void name##_svec_release(name##_svec_t *v) { _z_svec_release(v); } \ static inline void name##_svec_free(name##_svec_t **v) { _z_svec_free(v, name##_elem_clear, sizeof(type)); } #endif /* ZENOH_PICO_COLLECTIONS_VECTOR_H */ diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index 2449535fe..5b946505f 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -177,11 +177,6 @@ */ #define Z_GET_TIMEOUT_DEFAULT 10000 -/** - * Average size of a frame message (bytes). Used to evaluate initial decoding frame size. - */ -#define Z_CONFIG_FRAME_AVG_MSG_SIZE 32 - /** * Default "nop" instruction */ diff --git a/include/zenoh-pico/config.h.in b/include/zenoh-pico/config.h.in index d6f43e3d3..4e75ac0cb 100644 --- a/include/zenoh-pico/config.h.in +++ b/include/zenoh-pico/config.h.in @@ -177,11 +177,6 @@ */ #define Z_GET_TIMEOUT_DEFAULT 10000 -/** - * Average size of a frame message (bytes). Used to evaluate initial decoding frame size. - */ -#define Z_CONFIG_FRAME_AVG_MSG_SIZE 32 - /** * Default "nop" instruction */ diff --git a/include/zenoh-pico/net/query.h b/include/zenoh-pico/net/query.h index 703688a65..4cf60a4f7 100644 --- a/include/zenoh-pico/net/query.h +++ b/include/zenoh-pico/net/query.h @@ -25,23 +25,25 @@ * The query to be answered by a queryable. */ typedef struct _z_query_t { - _z_value_t _value; _z_keyexpr_t _key; + _z_value_t _value; uint32_t _request_id; - _z_session_weak_t _zn; // Can't be an rc because of cross referencing - _z_bytes_t attachment; - char *_parameters; + _z_session_rc_t _zn; + _z_bytes_t _attachment; + _z_string_t _parameters; bool _anyke; } _z_query_t; // Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. static inline _z_query_t _z_query_null(void) { return (_z_query_t){0}; } +static inline bool _z_query_check(const _z_query_t *query) { + return _z_keyexpr_check(&query->_key) || _z_value_check(&query->_value) || _z_bytes_check(&query->_attachment) || + _z_string_check(&query->_parameters); +} void _z_query_clear(_z_query_t *q); z_result_t _z_query_copy(_z_query_t *dst, const _z_query_t *src); void _z_query_free(_z_query_t **query); -_Z_REFCOUNT_DEFINE(_z_query, _z_query) - /** * Return type when declaring a queryable. */ @@ -54,8 +56,19 @@ typedef struct { // Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. static inline _z_queryable_t _z_queryable_null(void) { return (_z_queryable_t){0}; } static inline bool _z_queryable_check(const _z_queryable_t *queryable) { return !_Z_RC_IS_NULL(&queryable->_zn); } -_z_query_t _z_query_create(_z_value_t *value, _z_keyexpr_t *key, const _z_slice_t *parameters, _z_session_rc_t *zn, - uint32_t request_id, const _z_bytes_t attachment); +static inline _z_query_t _z_query_alias(_z_value_t *value, _z_keyexpr_t *key, const _z_slice_t *parameters, + _z_session_rc_t *zn, uint32_t request_id, const _z_bytes_t *attachment, + bool anyke) { + return (_z_query_t){ + ._key = *key, + ._value = *value, + ._request_id = request_id, + ._zn = *zn, + ._attachment = *attachment, + ._parameters = _z_string_alias_slice(parameters), + ._anyke = anyke, + }; +} void _z_queryable_clear(_z_queryable_t *qbl); void _z_queryable_free(_z_queryable_t **qbl); diff --git a/include/zenoh-pico/net/reply.h b/include/zenoh-pico/net/reply.h index fcc8876c8..f352be9a1 100644 --- a/include/zenoh-pico/net/reply.h +++ b/include/zenoh-pico/net/reply.h @@ -59,11 +59,6 @@ typedef struct _z_reply_data_t { // Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. static inline _z_reply_data_t _z_reply_data_null(void) { return (_z_reply_data_t){0}; } -static inline _z_reply_data_t _z_reply_data_init(void) { - _z_reply_data_t reply_data = _z_reply_data_null(); - reply_data._tag = _Z_REPLY_TAG_NONE; - return reply_data; -} void _z_reply_data_clear(_z_reply_data_t *rd); z_result_t _z_reply_data_copy(_z_reply_data_t *dst, const _z_reply_data_t *src); @@ -85,14 +80,27 @@ typedef struct _z_reply_t { // Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. static inline _z_reply_t _z_reply_null(void) { return (_z_reply_t){0}; } +static inline _z_reply_t _z_reply_alias(_z_keyexpr_t *keyexpr, _z_id_t id, const _z_bytes_t *payload, + const _z_timestamp_t *timestamp, _z_encoding_t *encoding, z_sample_kind_t kind, + const _z_bytes_t *attachment) { + _z_reply_t r; + r.data.replier_id = id; + r.data._tag = _Z_REPLY_TAG_DATA; + r.data._result.sample = _z_sample_alias(keyexpr, payload, timestamp, encoding, kind, _Z_N_QOS_DEFAULT, attachment, + Z_RELIABILITY_DEFAULT); + return r; +} +static inline _z_reply_t _z_reply_err_alias(const _z_bytes_t *payload, _z_encoding_t *encoding) { + _z_reply_t r; + r.data._tag = _Z_REPLY_TAG_ERROR; + r.data._result.error.payload = *payload; + r.data._result.error.encoding = *encoding; + return r; +} _z_reply_t _z_reply_move(_z_reply_t *src_reply); void _z_reply_clear(_z_reply_t *src); void _z_reply_free(_z_reply_t **hello); z_result_t _z_reply_copy(_z_reply_t *dst, const _z_reply_t *src); -_z_reply_t _z_reply_create(_z_keyexpr_t *keyexpr, _z_id_t id, const _z_bytes_t *payload, - const _z_timestamp_t *timestamp, _z_encoding_t *encoding, z_sample_kind_t kind, - const _z_bytes_t *attachment); -_z_reply_t _z_reply_err_create(const _z_bytes_t payload, _z_encoding_t *encoding); typedef struct _z_pending_reply_t { _z_reply_t _reply; diff --git a/include/zenoh-pico/net/sample.h b/include/zenoh-pico/net/sample.h index ab42e6985..718fe95da 100644 --- a/include/zenoh-pico/net/sample.h +++ b/include/zenoh-pico/net/sample.h @@ -46,6 +46,21 @@ static inline bool _z_sample_check(const _z_sample_t *sample) { return _z_keyexpr_check(&sample->keyexpr) || _z_encoding_check(&sample->encoding) || _z_bytes_check(&sample->payload) || _z_bytes_check(&sample->attachment); } +static inline _z_sample_t _z_sample_alias(const _z_keyexpr_t *key, const _z_bytes_t *payload, + const _z_timestamp_t *timestamp, const _z_encoding_t *encoding, + const z_sample_kind_t kind, const _z_qos_t qos, const _z_bytes_t *attachment, + z_reliability_t reliability) { + return (_z_sample_t){ + .keyexpr = *key, + .payload = *payload, + .timestamp = *timestamp, + .encoding = *encoding, + .kind = kind, + .qos = qos, + .attachment = *attachment, + .reliability = reliability, + }; +} void _z_sample_move(_z_sample_t *dst, _z_sample_t *src); /** @@ -59,8 +74,4 @@ void _z_sample_free(_z_sample_t **sample); z_result_t _z_sample_copy(_z_sample_t *dst, const _z_sample_t *src); _z_sample_t _z_sample_duplicate(const _z_sample_t *src); -void _z_sample_create(_z_sample_t *s, _z_keyexpr_t *key, _z_bytes_t *payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, _z_bytes_t *attachment, - z_reliability_t reliability); - #endif /* ZENOH_PICO_SAMPLE_NETAPI_H */ diff --git a/include/zenoh-pico/net/session.h b/include/zenoh-pico/net/session.h index b2bdd8fec..5362c1921 100644 --- a/include/zenoh-pico/net/session.h +++ b/include/zenoh-pico/net/session.h @@ -21,6 +21,7 @@ #include "zenoh-pico/collections/list.h" #include "zenoh-pico/config.h" #include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/session.h" #include "zenoh-pico/session/subscription.h" #include "zenoh-pico/utils/config.h" @@ -61,6 +62,9 @@ typedef struct _z_session_t { // Session queryables #if Z_FEATURE_QUERYABLE == 1 _z_session_queryable_rc_list_t *_local_queryable; +#if Z_FEATURE_RX_CACHE == 1 + _z_queryable_cache_t _queryable_cache; +#endif #endif #if Z_FEATURE_QUERY == 1 _z_pending_query_list_t *_pending_queries; diff --git a/include/zenoh-pico/protocol/codec/core.h b/include/zenoh-pico/protocol/codec/core.h index c86d1b18c..16cdef966 100644 --- a/include/zenoh-pico/protocol/codec/core.h +++ b/include/zenoh-pico/protocol/codec/core.h @@ -61,7 +61,7 @@ z_result_t _z_slice_val_decode_na(_z_slice_t *bs, _z_zbuf_t *zbf); z_result_t _z_slice_encode(_z_wbuf_t *buf, const _z_slice_t *bs); z_result_t _z_slice_decode(_z_slice_t *bs, _z_zbuf_t *buf); -z_result_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf); +z_result_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf, _z_arc_slice_t *arcs); z_result_t _z_bytes_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs); z_result_t _z_zbuf_read_exact(_z_zbuf_t *zbf, uint8_t *dest, size_t length); diff --git a/include/zenoh-pico/protocol/codec/message.h b/include/zenoh-pico/protocol/codec/message.h index c9bd9c039..b2d5c625c 100644 --- a/include/zenoh-pico/protocol/codec/message.h +++ b/include/zenoh-pico/protocol/codec/message.h @@ -19,19 +19,19 @@ #include "zenoh-pico/protocol/iobuf.h" z_result_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb); -z_result_t _z_push_body_decode(_z_push_body_t *body, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_push_body_decode(_z_push_body_t *body, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_query_encode(_z_wbuf_t *wbf, const _z_msg_query_t *query); z_result_t _z_query_decode(_z_msg_query_t *query, _z_zbuf_t *zbf, uint8_t header); z_result_t _z_reply_encode(_z_wbuf_t *wbf, const _z_msg_reply_t *reply); -z_result_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_err_encode(_z_wbuf_t *wbf, const _z_msg_err_t *err); -z_result_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_put_encode(_z_wbuf_t *wbf, const _z_msg_put_t *put); -z_result_t _z_put_decode(_z_msg_put_t *put, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_put_decode(_z_msg_put_t *put, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_del_encode(_z_wbuf_t *wbf, const _z_msg_del_t *del); z_result_t _z_del_decode(_z_msg_del_t *del, _z_zbuf_t *zbf, uint8_t header); diff --git a/include/zenoh-pico/protocol/codec/network.h b/include/zenoh-pico/protocol/codec/network.h index 64a5229c8..e3bce1f14 100644 --- a/include/zenoh-pico/protocol/codec/network.h +++ b/include/zenoh-pico/protocol/codec/network.h @@ -20,11 +20,11 @@ #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/iobuf.h" z_result_t _z_push_encode(_z_wbuf_t *wbf, const _z_n_msg_push_t *msg); -z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_request_encode(_z_wbuf_t *wbf, const _z_n_msg_request_t *msg); -z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_response_encode(_z_wbuf_t *wbf, const _z_n_msg_response_t *msg); -z_result_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_response_final_encode(_z_wbuf_t *wbf, const _z_n_msg_response_final_t *msg); z_result_t _z_response_final_decode(_z_n_msg_response_final_t *msg, _z_zbuf_t *zbf, uint8_t header); z_result_t _z_declare_encode(_z_wbuf_t *wbf, const _z_n_msg_declare_t *decl); @@ -33,6 +33,6 @@ z_result_t _z_n_interest_encode(_z_wbuf_t *wbf, const _z_n_msg_interest_t *inter z_result_t _z_n_interest_decode(_z_n_msg_interest_t *interest, _z_zbuf_t *zbf, uint8_t header); z_result_t _z_network_message_encode(_z_wbuf_t *wbf, const _z_network_message_t *msg); -z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf); +z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf, _z_arc_slice_t *arcs); #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_NETWORK_H */ diff --git a/include/zenoh-pico/protocol/codec/transport.h b/include/zenoh-pico/protocol/codec/transport.h index 06bb26327..4a83857b1 100644 --- a/include/zenoh-pico/protocol/codec/transport.h +++ b/include/zenoh-pico/protocol/codec/transport.h @@ -22,7 +22,8 @@ z_result_t _z_scouting_message_encode(_z_wbuf_t *buf, const _z_scouting_message_ z_result_t _z_scouting_message_decode(_z_scouting_message_t *msg, _z_zbuf_t *buf); z_result_t _z_transport_message_encode(_z_wbuf_t *buf, const _z_transport_message_t *msg); -z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *buf); +z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *buf, _z_arc_slice_svec_t *arc_pool, + _z_network_message_svec_t *msg_pool); z_result_t _z_join_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_join_t *msg); z_result_t _z_join_decode(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header); @@ -40,11 +41,10 @@ z_result_t _z_keep_alive_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_k z_result_t _z_keep_alive_decode(_z_t_msg_keep_alive_t *msg, _z_zbuf_t *zbf, uint8_t header); z_result_t _z_frame_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_frame_t *msg); -z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header); +z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_svec_t *arc_pool, + _z_network_message_svec_t *msg_pool); z_result_t _z_fragment_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_fragment_t *msg); z_result_t _z_fragment_decode(_z_t_msg_fragment_t *msg, _z_zbuf_t *zbf, uint8_t header); -z_result_t _z_transport_message_encode(_z_wbuf_t *wbf, const _z_transport_message_t *msg); -z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *zbf); #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_TRANSPORT_H */ diff --git a/include/zenoh-pico/protocol/core.h b/include/zenoh-pico/protocol/core.h index e66e3745e..c793656bd 100644 --- a/include/zenoh-pico/protocol/core.h +++ b/include/zenoh-pico/protocol/core.h @@ -70,7 +70,9 @@ typedef struct { // Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. static inline _z_timestamp_t _z_timestamp_null(void) { return (_z_timestamp_t){0}; } -static inline bool _z_timestamp_check(const _z_timestamp_t *stamp) { return stamp->valid; } +static inline void _z_timestamp_invalid(_z_timestamp_t *tstamp) { tstamp->valid = false; } +static inline bool _z_timestamp_check(const _z_timestamp_t *tstamp) { return tstamp->valid; } +void _z_timestamp_copy(_z_timestamp_t *dst, const _z_timestamp_t *src); _z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp); void _z_timestamp_clear(_z_timestamp_t *tstamp); void _z_timestamp_move(_z_timestamp_t *dst, _z_timestamp_t *src); @@ -170,6 +172,9 @@ typedef struct { // Warning: None of the sub-types require a non-0 initialization. Add a init function if it changes. static inline _z_value_t _z_value_null(void) { return (_z_value_t){0}; } +static inline bool _z_value_check(const _z_value_t *value) { + return _z_bytes_check(&value->payload) || _z_encoding_check(&value->encoding); +} _z_value_t _z_value_steal(_z_value_t *value); z_result_t _z_value_copy(_z_value_t *dst, const _z_value_t *src); void _z_value_move(_z_value_t *dst, _z_value_t *src); diff --git a/include/zenoh-pico/protocol/definitions/network.h b/include/zenoh-pico/protocol/definitions/network.h index c3ea611f8..24d86102c 100644 --- a/include/zenoh-pico/protocol/definitions/network.h +++ b/include/zenoh-pico/protocol/definitions/network.h @@ -91,7 +91,7 @@ static inline bool _z_n_qos_get_express(_z_n_qos_t n_qos) { return (bool)(n_qos. #define _z_n_qos_make(express, nodrop, priority) \ _z_n_qos_create((bool)express, nodrop ? Z_CONGESTION_CONTROL_BLOCK : Z_CONGESTION_CONTROL_DROP, \ (z_priority_t)priority) -#define _Z_N_QOS_DEFAULT _z_n_qos_make(0, 0, 5) +#define _Z_N_QOS_DEFAULT ((_z_qos_t){._val = 5}) // RESPONSE FINAL message flags: // Z Extensions if Z==1 then Zenoh extensions are present @@ -290,7 +290,7 @@ void _z_n_msg_free(_z_network_message_t **m); inline static void _z_msg_clear(_z_zenoh_message_t *msg) { _z_n_msg_clear(msg); } inline static void _z_msg_free(_z_zenoh_message_t **msg) { _z_n_msg_free(msg); } _Z_ELEM_DEFINE(_z_network_message, _z_network_message_t, _z_noop_size, _z_n_msg_clear, _z_noop_copy, _z_noop_move) -_Z_SVEC_DEFINE(_z_network_message, _z_network_message_t, false) +_Z_SVEC_DEFINE(_z_network_message, _z_network_message_t) void _z_msg_fix_mapping(_z_zenoh_message_t *msg, uint16_t mapping); _z_network_message_t _z_msg_make_query(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_slice_t) parameters, _z_zint_t qid, diff --git a/include/zenoh-pico/session/query.h b/include/zenoh-pico/session/query.h index 9a8ea69ae..c1267e348 100644 --- a/include/zenoh-pico/session/query.h +++ b/include/zenoh-pico/session/query.h @@ -27,7 +27,7 @@ _z_zint_t _z_get_query_id(_z_session_t *zn); _z_pending_query_t *_z_get_pending_query_by_id(_z_session_t *zn, const _z_zint_t id); z_result_t _z_register_pending_query(_z_session_t *zn, _z_pending_query_t *pq); -z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, _z_zint_t reply_context, const _z_keyexpr_t keyexpr, +z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, _z_zint_t reply_context, _z_keyexpr_t *keyexpr, _z_msg_put_t *msg, z_sample_kind_t kind); z_result_t _z_trigger_query_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *msg); z_result_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id); diff --git a/include/zenoh-pico/session/queryable.h b/include/zenoh-pico/session/queryable.h index 4498a5bed..6e8e8eeed 100644 --- a/include/zenoh-pico/session/queryable.h +++ b/include/zenoh-pico/session/queryable.h @@ -16,20 +16,37 @@ #define ZENOH_PICO_SESSION_QUERYABLE_H #include +#include -#include "zenoh-pico/net/session.h" +// Forward declaration to avoid cyclical include +typedef struct _z_session_t _z_session_t; +typedef struct _z_session_rc_t _z_session_rc_t; + +// Queryable infos +typedef struct { + _z_query_handler_t callback; + void *arg; +} _z_queryable_infos_t; + +_Z_ELEM_DEFINE(_z_queryable_infos, _z_queryable_infos_t, _z_noop_size, _z_noop_clear, _z_noop_copy, _z_noop_move) +_Z_SVEC_DEFINE(_z_queryable_infos, _z_queryable_infos_t) + +typedef struct { + _z_keyexpr_t ke_in; + _z_keyexpr_t ke_out; + _z_queryable_infos_svec_t infos; + size_t qle_nb; +} _z_queryable_cache_t; #if Z_FEATURE_QUERYABLE == 1 #define _Z_QUERYABLE_COMPLETE_DEFAULT false #define _Z_QUERYABLE_DISTANCE_DEFAULT 0 /*------------------ Queryable ------------------*/ +void _z_queryable_cache_clear(_z_queryable_cache_t *cache); _z_session_queryable_rc_t *_z_get_session_queryable_by_id(_z_session_t *zn, const _z_zint_t id); -_z_session_queryable_rc_list_t *_z_get_session_queryable_by_key(_z_session_t *zn, const _z_keyexpr_t key); - _z_session_queryable_rc_t *_z_register_session_queryable(_z_session_t *zn, _z_session_queryable_t *q); -z_result_t _z_trigger_queryables(_z_session_rc_t *zn, _z_msg_query_t *query, const _z_keyexpr_t q_key, uint32_t qid, - const _z_bytes_t attachment); +z_result_t _z_trigger_queryables(_z_session_rc_t *zn, _z_msg_query_t *query, _z_keyexpr_t *q_key, uint32_t qid); void _z_unregister_session_queryable(_z_session_t *zn, _z_session_queryable_rc_t *q); void _z_flush_session_queryable(_z_session_t *zn); #endif diff --git a/include/zenoh-pico/session/reply.h b/include/zenoh-pico/session/reply.h index c10aa0b28..083fed40f 100644 --- a/include/zenoh-pico/session/reply.h +++ b/include/zenoh-pico/session/reply.h @@ -22,7 +22,7 @@ #ifndef ZENOH_PICO_SESSION_REPLY_H #define ZENOH_PICO_SESSION_REPLY_H -z_result_t _z_trigger_reply_partial(_z_session_t *zn, _z_zint_t id, _z_keyexpr_t key, _z_msg_reply_t *reply); +z_result_t _z_trigger_reply_partial(_z_session_t *zn, _z_zint_t id, _z_keyexpr_t *key, _z_msg_reply_t *reply); z_result_t _z_trigger_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *error); diff --git a/include/zenoh-pico/session/session.h b/include/zenoh-pico/session/session.h index d2aa10129..6296ad1f1 100644 --- a/include/zenoh-pico/session/session.h +++ b/include/zenoh-pico/session/session.h @@ -80,12 +80,12 @@ typedef struct { } _z_publication_t; // Forward type declaration to avoid cyclical include -typedef struct _z_query_rc_t _z_query_rc_t; +typedef struct _z_query_t _z_query_t; /** * The callback signature of the functions handling query messages. */ -typedef void (*_z_query_handler_t)(_z_query_rc_t *query, void *arg); +typedef void (*_z_query_handler_t)(_z_query_t *query, void *arg); typedef struct { _z_keyexpr_t _key; diff --git a/include/zenoh-pico/session/subscription.h b/include/zenoh-pico/session/subscription.h index 2d7e1187a..852e6cd9d 100644 --- a/include/zenoh-pico/session/subscription.h +++ b/include/zenoh-pico/session/subscription.h @@ -29,16 +29,17 @@ typedef struct { } _z_subscription_infos_t; _Z_ELEM_DEFINE(_z_subscription_infos, _z_subscription_infos_t, _z_noop_size, _z_noop_clear, _z_noop_copy, _z_noop_move) -_Z_SVEC_DEFINE(_z_subscription_infos, _z_subscription_infos_t, false) +_Z_SVEC_DEFINE(_z_subscription_infos, _z_subscription_infos_t) typedef struct { _z_keyexpr_t ke_in; _z_keyexpr_t ke_out; _z_subscription_infos_svec_t infos; + size_t sub_nb; } _z_subscription_cache_t; /*------------------ Subscription ------------------*/ -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, _z_bytes_t *attachment, z_reliability_t reliability); @@ -50,7 +51,7 @@ void _z_subscription_cache_clear(_z_subscription_cache_t *cache); _z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id); _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_t *sub); -z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, +z_result_t _z_trigger_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability); void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub); diff --git a/include/zenoh-pico/transport/transport.h b/include/zenoh-pico/transport/transport.h index 678bf2022..e78de9366 100644 --- a/include/zenoh-pico/transport/transport.h +++ b/include/zenoh-pico/transport/transport.h @@ -69,6 +69,8 @@ _z_transport_peer_entry_list_t *_z_transport_peer_entry_list_insert(_z_transport // Forward type declaration to avoid cyclical include typedef struct _z_session_rc_t _z_session_rc_ref_t; +#define _Z_RES_POOL_INIT_SIZE 8 // Arbitrary small value + typedef struct { _z_session_rc_ref_t *_session; _z_link_t _link; @@ -79,6 +81,8 @@ typedef struct { _z_zint_t _sn_res; _z_zint_t _sn_tx_reliable; _z_zint_t _sn_tx_best_effort; + _z_arc_slice_svec_t _arc_pool; + _z_network_message_svec_t _msg_pool; volatile _z_zint_t _lease; volatile bool _transmitted; #if Z_FEATURE_MULTI_THREAD == 1 diff --git a/src/api/api.c b/src/api/api.c index d74130335..93c811f0b 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -66,7 +66,7 @@ void z_string_array_new(z_owned_string_array_t *a) { a->_val = _z_string_array_n size_t z_string_array_push_by_alias(z_loaned_string_array_t *a, const z_loaned_string_t *value) { _z_string_t str = _z_string_alias(*value); - _z_string_svec_append(a, &str); + _z_string_svec_append(a, &str, true); return _z_string_svec_len(a); } @@ -74,7 +74,7 @@ size_t z_string_array_push_by_alias(z_loaned_string_array_t *a, const z_loaned_s size_t z_string_array_push_by_copy(z_loaned_string_array_t *a, const z_loaned_string_t *value) { _z_string_t str; _z_string_copy(&str, value); - _z_string_svec_append(a, &str); + _z_string_svec_append(a, &str, true); return _z_string_svec_len(a); } @@ -244,12 +244,12 @@ const uint8_t *z_slice_data(const z_loaned_slice_t *slice) { return slice->start size_t z_slice_len(const z_loaned_slice_t *slice) { return slice->len; } -void z_slice_empty(z_owned_slice_t *slice) { slice->_val = _z_slice_empty(); } +void z_slice_empty(z_owned_slice_t *slice) { slice->_val = _z_slice_null(); } bool z_slice_is_empty(const z_loaned_slice_t *slice) { return _z_slice_is_empty(slice); } z_result_t z_bytes_to_slice(const z_loaned_bytes_t *bytes, z_owned_slice_t *dst) { - dst->_val = _z_slice_empty(); + dst->_val = _z_slice_null(); return _z_bytes_to_slice(bytes, &dst->_val); } @@ -417,17 +417,16 @@ z_query_consolidation_t z_query_consolidation_none(void) { z_query_consolidation_t z_query_consolidation_default(void) { return z_query_consolidation_auto(); } void z_query_parameters(const z_loaned_query_t *query, z_view_string_t *parameters) { - parameters->_val = _z_string_alias_str(_Z_RC_IN_VAL(query)->_parameters); + parameters->_val = _z_string_alias(query->_parameters); } -const z_loaned_bytes_t *z_query_attachment(const z_loaned_query_t *query) { return &_Z_RC_IN_VAL(query)->attachment; } +const z_loaned_bytes_t *z_query_attachment(const z_loaned_query_t *query) { return &query->_attachment; } -const z_loaned_keyexpr_t *z_query_keyexpr(const z_loaned_query_t *query) { return &_Z_RC_IN_VAL(query)->_key; } +const z_loaned_keyexpr_t *z_query_keyexpr(const z_loaned_query_t *query) { return &query->_key; } -const z_loaned_bytes_t *z_query_payload(const z_loaned_query_t *query) { return &_Z_RC_IN_VAL(query)->_value.payload; } -const z_loaned_encoding_t *z_query_encoding(const z_loaned_query_t *query) { - return &_Z_RC_IN_VAL(query)->_value.encoding; -} +const z_loaned_bytes_t *z_query_payload(const z_loaned_query_t *query) { return &query->_value.payload; } + +const z_loaned_encoding_t *z_query_encoding(const z_loaned_query_t *query) { return &query->_value.encoding; } void z_closure_sample_call(const z_loaned_closure_sample_t *closure, z_loaned_sample_t *sample) { if (closure->call != NULL) { @@ -470,16 +469,13 @@ _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_config_t, config, _z_config_check, _z_config_nu _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_string_t, string, _z_string_check, _z_string_null, _z_string_copy, _z_string_clear) -bool _z_value_check(const _z_value_t *value) { - return _z_encoding_check(&value->encoding) || _z_bytes_check(&value->payload); -} _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_value_t, reply_err, _z_value_check, _z_value_null, _z_value_copy, _z_value_clear) _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_keyexpr_t, keyexpr, _z_keyexpr_check, _z_keyexpr_null, _z_keyexpr_copy, _z_keyexpr_clear) _Z_VIEW_FUNCTIONS_IMPL(_z_keyexpr_t, keyexpr, _z_keyexpr_check, _z_keyexpr_null) _Z_VIEW_FUNCTIONS_IMPL(_z_string_t, string, _z_string_check, _z_string_null) -_Z_VIEW_FUNCTIONS_IMPL(_z_slice_t, slice, _z_slice_check, _z_slice_empty) +_Z_VIEW_FUNCTIONS_IMPL(_z_slice_t, slice, _z_slice_check, _z_slice_null) _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_hello_t, hello, _z_hello_check, _z_hello_null, _z_hello_copy, _z_hello_clear) @@ -517,11 +513,11 @@ z_result_t z_whatami_to_view_string(z_whatami_t whatami, z_view_string_t *str_ou bool _z_string_array_check(const _z_string_svec_t *val) { return !_z_string_svec_is_empty(val); } z_result_t _z_string_array_copy(_z_string_svec_t *dst, const _z_string_svec_t *src) { - return _z_string_svec_copy(dst, src); + return _z_string_svec_copy(dst, src, true); } _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_string_svec_t, string_array, _z_string_array_check, _z_string_array_null, _z_string_array_copy, _z_string_svec_clear) -_Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_slice_t, slice, _z_slice_check, _z_slice_empty, _z_slice_copy, _z_slice_clear) +_Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_slice_t, slice, _z_slice_check, _z_slice_null, _z_slice_copy, _z_slice_clear) _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_bytes_t, bytes, _z_bytes_check, _z_bytes_null, _z_bytes_copy, _z_bytes_drop) _Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL(_z_bytes_writer_t, bytes_writer, _z_bytes_writer_check, _z_bytes_writer_empty, _z_bytes_writer_clear) @@ -1121,7 +1117,7 @@ bool z_reply_replier_id(const z_loaned_reply_t *reply, z_id_t *out_id) { #endif #if Z_FEATURE_QUERYABLE == 1 -_Z_OWNED_FUNCTIONS_RC_IMPL(query) +_Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_query_t, query, _z_query_check, _z_query_null, _z_query_copy, _z_query_clear) void _z_queryable_drop(_z_queryable_t *queryable) { _z_undeclare_queryable(queryable); @@ -1191,9 +1187,7 @@ void z_query_reply_options_default(z_query_reply_options_t *options) { z_result_t z_query_reply(const z_loaned_query_t *query, const z_loaned_keyexpr_t *keyexpr, z_moved_bytes_t *payload, const z_query_reply_options_t *options) { - // Try upgrading session weak to rc - _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&_Z_RC_IN_VAL(query)->_zn); - if (_Z_RC_IS_NULL(&sess_rc)) { + if (_Z_RC_IS_NULL(&query->_zn)) { return _Z_ERR_SESSION_CLOSED; } // Set options @@ -1208,12 +1202,11 @@ z_result_t z_query_reply(const z_loaned_query_t *query, const z_loaned_keyexpr_t _z_value_t value = {.payload = _z_bytes_from_owned_bytes(&payload->_this), .encoding = _z_encoding_from_owned(&opts.encoding->_this)}; - z_result_t ret = _z_send_reply(_Z_RC_IN_VAL(query), &sess_rc, keyexpr_aliased, value, Z_SAMPLE_KIND_PUT, + z_result_t ret = _z_send_reply(query, &query->_zn, keyexpr_aliased, value, Z_SAMPLE_KIND_PUT, opts.congestion_control, opts.priority, opts.is_express, opts.timestamp, _z_bytes_from_owned_bytes(&opts.attachment->_this)); z_bytes_drop(payload); // Clean-up - _z_session_rc_drop(&sess_rc); z_encoding_drop(opts.encoding); z_bytes_drop(opts.attachment); return ret; @@ -1229,9 +1222,7 @@ void z_query_reply_del_options_default(z_query_reply_del_options_t *options) { z_result_t z_query_reply_del(const z_loaned_query_t *query, const z_loaned_keyexpr_t *keyexpr, const z_query_reply_del_options_t *options) { - // Try upgrading session weak to rc - _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&_Z_RC_IN_VAL(query)->_zn); - if (_Z_RC_IS_NULL(&sess_rc)) { + if (_Z_RC_IS_NULL(&query->_zn)) { return _Z_ERR_SESSION_CLOSED; } _z_keyexpr_t keyexpr_aliased = _z_keyexpr_alias_from_user_defined(*keyexpr, true); @@ -1244,11 +1235,10 @@ z_result_t z_query_reply_del(const z_loaned_query_t *query, const z_loaned_keyex _z_value_t value = {.payload = _z_bytes_null(), .encoding = _z_encoding_null()}; - z_result_t ret = _z_send_reply(_Z_RC_IN_VAL(query), &sess_rc, keyexpr_aliased, value, Z_SAMPLE_KIND_DELETE, + z_result_t ret = _z_send_reply(query, &query->_zn, keyexpr_aliased, value, Z_SAMPLE_KIND_DELETE, opts.congestion_control, opts.priority, opts.is_express, opts.timestamp, _z_bytes_from_owned_bytes(&opts.attachment->_this)); // Clean-up - _z_session_rc_drop(&sess_rc); z_bytes_drop(opts.attachment); return ret; } @@ -1257,9 +1247,7 @@ void z_query_reply_err_options_default(z_query_reply_err_options_t *options) { o z_result_t z_query_reply_err(const z_loaned_query_t *query, z_moved_bytes_t *payload, const z_query_reply_err_options_t *options) { - // Try upgrading session weak to rc - _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&_Z_RC_IN_VAL(query)->_zn); - if (_Z_RC_IS_NULL(&sess_rc)) { + if (_Z_RC_IS_NULL(&query->_zn)) { return _Z_ERR_SESSION_CLOSED; } z_query_reply_err_options_t opts; @@ -1271,9 +1259,7 @@ z_result_t z_query_reply_err(const z_loaned_query_t *query, z_moved_bytes_t *pay // Set value _z_value_t value = {.payload = _z_bytes_from_owned_bytes(&payload->_this), .encoding = _z_encoding_from_owned(&opts.encoding->_this)}; - - z_result_t ret = _z_send_reply_err(_Z_RC_IN_VAL(query), &sess_rc, value); - _z_session_rc_drop(&sess_rc); + z_result_t ret = _z_send_reply_err(query, &query->_zn, value); z_bytes_drop(payload); // Clean-up z_encoding_drop(opts.encoding); diff --git a/src/collections/arc_slice.c b/src/collections/arc_slice.c index 17d17a8eb..28603aff9 100644 --- a/src/collections/arc_slice.c +++ b/src/collections/arc_slice.c @@ -36,9 +36,6 @@ _z_arc_slice_t _z_arc_slice_wrap_slice_rc(_z_slice_simple_rc_t* slice_rc, size_t assert(offset + len <= _Z_RC_IN_VAL(slice_rc)->len); _z_arc_slice_t arc_s; arc_s.slice = _z_slice_simple_rc_clone(slice_rc); - if (_Z_RC_IS_NULL(&arc_s.slice)) { - return _z_arc_slice_empty(); - } arc_s.len = len; arc_s.start = offset; return arc_s; @@ -79,6 +76,6 @@ z_result_t _z_arc_slice_move(_z_arc_slice_t* dst, _z_arc_slice_t* src) { z_result_t _z_arc_slice_drop(_z_arc_slice_t* s) { _z_slice_simple_rc_drop(&s->slice); - *s = _z_arc_slice_empty(); + s->len = 0; return _Z_RES_OK; } diff --git a/src/collections/bytes.c b/src/collections/bytes.c index deb3f8252..ab3507a95 100644 --- a/src/collections/bytes.c +++ b/src/collections/bytes.c @@ -28,7 +28,7 @@ bool _z_bytes_check(const _z_bytes_t *bytes) { return !_z_bytes_is_empty(bytes); } z_result_t _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src) { - return _z_arc_slice_svec_copy(&dst->_slices, &src->_slices); + return _z_arc_slice_svec_copy(&dst->_slices, &src->_slices, true); } _z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src) { @@ -63,6 +63,8 @@ _z_arc_slice_t *_z_bytes_get_slice(const _z_bytes_t *bs, size_t i) { void _z_bytes_drop(_z_bytes_t *bytes) { _z_arc_slice_svec_clear(&bytes->_slices); } +void _z_bytes_aliased_drop(_z_bytes_t *bytes) { _z_arc_slice_svec_reset(&bytes->_slices); } + void _z_bytes_free(_z_bytes_t **bs) { _z_bytes_t *ptr = *bs; @@ -93,7 +95,7 @@ z_result_t _z_bytes_from_slice(_z_bytes_t *b, _z_slice_t s) { *b = _z_bytes_null(); _z_arc_slice_t arc_s = _z_arc_slice_wrap(s, 0, s.len); if (_z_arc_slice_len(&arc_s) != s.len) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - return _z_arc_slice_svec_append(&b->_slices, &arc_s); + return _z_arc_slice_svec_append(&b->_slices, &arc_s, true); } z_result_t _z_bytes_from_buf(_z_bytes_t *b, const uint8_t *src, size_t len) { @@ -125,8 +127,12 @@ z_result_t _z_bytes_to_slice(const _z_bytes_t *bytes, _z_slice_t *s) { } z_result_t _z_bytes_append_slice(_z_bytes_t *dst, _z_arc_slice_t *s) { - _Z_CLEAN_RETURN_IF_ERR(_z_arc_slice_svec_append(&dst->_slices, s), _z_arc_slice_drop(s)); - return _Z_RES_OK; + z_result_t ret = _Z_RES_OK; + ret = _z_arc_slice_svec_append(&dst->_slices, s, true); + if (ret != _Z_RES_OK) { + _z_arc_slice_drop(s); + } + return ret; } z_result_t _z_bytes_append_bytes(_z_bytes_t *dst, _z_bytes_t *src) { @@ -149,7 +155,7 @@ _z_slice_t _z_bytes_try_get_contiguous(const _z_bytes_t *bs) { _z_arc_slice_t *arc_s = _z_bytes_get_slice(bs, 0); return _z_slice_alias_buf(_z_arc_slice_data(arc_s), _z_arc_slice_len(arc_s)); } - return _z_slice_empty(); + return _z_slice_null(); } void _z_bytes_move(_z_bytes_t *dst, _z_bytes_t *src) { diff --git a/src/collections/slice.c b/src/collections/slice.c index 5c9116ea7..049721a8a 100644 --- a/src/collections/slice.c +++ b/src/collections/slice.c @@ -111,22 +111,19 @@ z_result_t _z_slice_n_copy(_z_slice_t *dst, const _z_slice_t *src, size_t offset } void _z_slice_move(_z_slice_t *dst, _z_slice_t *src) { - dst->start = src->start; - dst->len = src->len; - dst->_delete_context = src->_delete_context; - + *dst = *src; _z_slice_reset(src); } _z_slice_t _z_slice_duplicate(const _z_slice_t *src) { - _z_slice_t dst = _z_slice_empty(); + _z_slice_t dst = _z_slice_null(); _z_slice_copy(&dst, src); return dst; } _z_slice_t _z_slice_steal(_z_slice_t *b) { _z_slice_t ret = *b; - *b = _z_slice_empty(); + *b = _z_slice_null(); return ret; } bool _z_slice_eq(const _z_slice_t *left, const _z_slice_t *right) { diff --git a/src/collections/string.c b/src/collections/string.c index a2545e767..2dad38f40 100644 --- a/src/collections/string.c +++ b/src/collections/string.c @@ -33,6 +33,12 @@ _z_string_t _z_string_copy_from_substr(const char *value, size_t len) { return s; } +_z_string_t _z_string_alias_slice(const _z_slice_t *slice) { + _z_string_t s; + s._slice = _z_slice_alias(*slice); + return s; +} + _z_string_t _z_string_alias_str(const char *value) { _z_string_t s; s._slice = _z_slice_alias_buf((const uint8_t *)(value), strlen(value)); @@ -71,7 +77,7 @@ z_result_t _z_string_copy_substring(_z_string_t *dst, const _z_string_t *src, si return _z_slice_n_copy(&dst->_slice, &src->_slice, offset, len); } -void _z_string_move(_z_string_t *dst, _z_string_t *src) { *dst = _z_string_steal(src); } +void _z_string_move(_z_string_t *dst, _z_string_t *src) { _z_slice_move(&dst->_slice, &src->_slice); } _z_string_t _z_string_steal(_z_string_t *str) { _z_string_t ret; diff --git a/src/collections/vec.c b/src/collections/vec.c index 60ee8f4a1..e37614cca 100644 --- a/src/collections/vec.c +++ b/src/collections/vec.c @@ -135,7 +135,7 @@ void _z_vec_remove(_z_vec_t *v, size_t pos, z_element_free_f free_f) { /*-------- svec --------*/ _z_svec_t _z_svec_make(size_t capacity, size_t element_size) { - _z_svec_t v = {._capacity = 0, ._len = 0, ._val = NULL}; + _z_svec_t v = _z_svec_null(); if (capacity != 0) { v._val = z_malloc(element_size * capacity); } @@ -145,7 +145,11 @@ _z_svec_t _z_svec_make(size_t capacity, size_t element_size) { return v; } -void _z_svec_init(_z_svec_t *dst, size_t element_size) { memset(dst->_val, 0, dst->_capacity * element_size); } +void _z_svec_init(_z_svec_t *v, size_t offset, size_t element_size) { + assert(offset <= v->_capacity); + void *start = _z_svec_get_mut(v, offset, element_size); + memset(start, 0, (v->_capacity - offset) * element_size); +} static inline void __z_svec_move_inner(void *dst, void *src, z_element_move_f move, size_t num_elements, size_t element_size, bool use_elem_f) { @@ -206,7 +210,7 @@ void _z_svec_clear(_z_svec_t *v, z_element_clear_f clear_f, size_t element_size) void _z_svec_release(_z_svec_t *v) { z_free(v->_val); - *v = _z_svec_null(); + v->_capacity = 0; } void _z_svec_free(_z_svec_t **v, z_element_clear_f clear, size_t element_size) { @@ -226,13 +230,13 @@ bool _z_svec_is_empty(const _z_svec_t *v) { return v->_len == 0; } z_result_t _z_svec_expand(_z_svec_t *v, z_element_move_f move, size_t element_size, bool use_elem_f) { // Allocate a new vector - size_t _capacity = v->_capacity == 0 ? 1 : (v->_capacity << 1); + size_t _capacity = v->_capacity << 1; void *_val = (void *)z_malloc(_capacity * element_size); if (_val == NULL) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } + // Move and clear old data __z_svec_move_inner(_val, v->_val, move, v->_len, element_size, use_elem_f); - // Free the old data z_free(v->_val); // Update the current vector v->_val = _val; @@ -241,7 +245,9 @@ z_result_t _z_svec_expand(_z_svec_t *v, z_element_move_f move, size_t element_si } z_result_t _z_svec_append(_z_svec_t *v, const void *e, z_element_move_f move, size_t element_size, bool use_elem_f) { - if (v->_len == v->_capacity) { + if (v->_capacity == 0) { + *v = _z_svec_make(1, element_size); + } else if (v->_len == v->_capacity) { _Z_RETURN_IF_ERR(_z_svec_expand(v, move, element_size, use_elem_f)); } // Append element diff --git a/src/net/query.c b/src/net/query.c index a4b41b6aa..dcf5b647a 100644 --- a/src/net/query.c +++ b/src/net/query.c @@ -20,15 +20,13 @@ void _z_query_clear_inner(_z_query_t *q) { _z_keyexpr_clear(&q->_key); _z_value_clear(&q->_value); - _z_bytes_drop(&q->attachment); - z_free(q->_parameters); - _z_session_weak_drop(&q->_zn); + _z_bytes_drop(&q->_attachment); + _z_string_clear(&q->_parameters); + _z_session_rc_drop(&q->_zn); } void _z_query_clear(_z_query_t *q) { - // Try to upgrade session weak to rc - _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&q->_zn); - if (!_Z_RC_IS_NULL(&sess_rc)) { + if (!_Z_RC_IS_NULL(&q->_zn)) { // Send REPLY_FINAL message _z_zenoh_message_t z_msg = _z_n_msg_make_response_final(q->_request_id); if (_z_send_n_msg(_Z_RC_IN_VAL(&q->_zn), &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != @@ -36,7 +34,6 @@ void _z_query_clear(_z_query_t *q) { _Z_ERROR("Query send REPLY_FINAL transport failure !"); } _z_msg_clear(&z_msg); - _z_session_rc_drop(&sess_rc); } // Clean up memory _z_query_clear_inner(q); @@ -46,13 +43,9 @@ z_result_t _z_query_copy(_z_query_t *dst, const _z_query_t *src) { *dst = _z_query_null(); _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst->_key, &src->_key)); _Z_CLEAN_RETURN_IF_ERR(_z_value_copy(&dst->_value, &src->_value), _z_query_clear_inner(dst)); - _Z_CLEAN_RETURN_IF_ERR(_z_bytes_copy(&dst->attachment, &src->attachment), _z_query_clear_inner(dst)); - dst->_parameters = _z_str_clone(src->_parameters); - if (dst->_parameters == NULL && src->_parameters != NULL) { - _z_query_clear_inner(dst); - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - _z_session_weak_copy(&dst->_zn, &src->_zn); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_copy(&dst->_attachment, &src->_attachment), _z_query_clear_inner(dst)); + _Z_CLEAN_RETURN_IF_ERR(_z_string_copy(&dst->_parameters, &src->_parameters), _z_query_clear_inner(dst)); + _z_session_rc_copy(&dst->_zn, &src->_zn); if (_Z_RC_IS_NULL(&dst->_zn)) { _z_query_clear_inner(dst); return _Z_ERR_SYSTEM_OUT_OF_MEMORY; @@ -73,21 +66,6 @@ void _z_query_free(_z_query_t **query) { } #if Z_FEATURE_QUERYABLE == 1 -_z_query_t _z_query_create(_z_value_t *value, _z_keyexpr_t *key, const _z_slice_t *parameters, _z_session_rc_t *zsrc, - uint32_t request_id, const _z_bytes_t attachment) { - _z_query_t q = _z_query_null(); - q._request_id = request_id; - q._zn = _z_session_rc_clone_as_weak(zsrc); - q._parameters = (char *)z_malloc(parameters->len + 1); - memcpy(q._parameters, parameters->start, parameters->len); - q._parameters[parameters->len] = 0; - q._anyke = (strstr(q._parameters, Z_SELECTOR_QUERY_MATCH) == NULL) ? false : true; - q._key = _z_keyexpr_steal(key); - _z_bytes_copy(&q.attachment, &attachment); - _z_value_move(&q._value, value); - return q; -} - void _z_queryable_clear(_z_queryable_t *qbl) { _z_session_weak_drop(&qbl->_zn); *qbl = _z_queryable_null(); diff --git a/src/net/reply.c b/src/net/reply.c index 67987cb35..9c06b2674 100644 --- a/src/net/reply.c +++ b/src/net/reply.c @@ -39,7 +39,6 @@ void _z_reply_data_free(_z_reply_data_t **reply_data) { } z_result_t _z_reply_data_copy(_z_reply_data_t *dst, const _z_reply_data_t *src) { - *dst = _z_reply_data_init(); if (src->_tag == _Z_REPLY_TAG_DATA) { _Z_RETURN_IF_ERR(_z_sample_copy(&dst->_result.sample, &src->_result.sample)); } else if (src->_tag == _Z_REPLY_TAG_ERROR) { @@ -69,11 +68,7 @@ void _z_reply_free(_z_reply_t **reply) { } } -z_result_t _z_reply_copy(_z_reply_t *dst, const _z_reply_t *src) { - *dst = _z_reply_null(); - _Z_RETURN_IF_ERR(_z_reply_data_copy(&dst->data, &src->data)); - return _Z_RES_OK; -} +z_result_t _z_reply_copy(_z_reply_t *dst, const _z_reply_t *src) { return _z_reply_data_copy(&dst->data, &src->data); } bool _z_pending_reply_eq(const _z_pending_reply_t *one, const _z_pending_reply_t *two) { return one->_tstamp.time == two->_tstamp.time; @@ -87,48 +82,4 @@ void _z_pending_reply_clear(_z_pending_reply_t *pr) { _z_timestamp_clear(&pr->_tstamp); } -_z_reply_t _z_reply_create(_z_keyexpr_t *keyexpr, _z_id_t id, const _z_bytes_t *payload, - const _z_timestamp_t *timestamp, _z_encoding_t *encoding, z_sample_kind_t kind, - const _z_bytes_t *attachment) { - _z_reply_t reply = _z_reply_null(); - reply.data._tag = _Z_REPLY_TAG_DATA; - reply.data.replier_id = id; - - // Create reply sample - reply.data._result.sample.keyexpr = _z_keyexpr_steal(keyexpr); - reply.data._result.sample.kind = kind; - reply.data._result.sample.timestamp = _z_timestamp_duplicate(timestamp); - _z_bytes_copy(&reply.data._result.sample.payload, payload); - _z_bytes_copy(&reply.data._result.sample.attachment, attachment); - _z_encoding_move(&reply.data._result.sample.encoding, encoding); - - return reply; -} - -_z_reply_t _z_reply_err_create(const _z_bytes_t payload, _z_encoding_t *encoding) { - _z_reply_t reply = _z_reply_null(); - reply.data._tag = _Z_REPLY_TAG_ERROR; - _z_bytes_copy(&reply.data._result.error.payload, &payload); - _z_encoding_move(&reply.data._result.error.encoding, encoding); - return reply; -} -#else -_z_reply_t _z_reply_create(_z_keyexpr_t *keyexpr, _z_id_t id, const _z_bytes_t *payload, - const _z_timestamp_t *timestamp, _z_encoding_t *encoding, z_sample_kind_t kind, - const _z_bytes_t *attachment) { - _ZP_UNUSED(keyexpr); - _ZP_UNUSED(id); - _ZP_UNUSED(payload); - _ZP_UNUSED(timestamp); - _ZP_UNUSED(encoding); - _ZP_UNUSED(kind); - _ZP_UNUSED(attachment); - return _z_reply_null(); -} - -_z_reply_t _z_reply_err_create(const _z_bytes_t payload, _z_encoding_t *encoding) { - _ZP_UNUSED(payload); - _ZP_UNUSED(encoding); - return _z_reply_null(); -} -#endif +#endif // Z_FEATURE_QUERY == 1 diff --git a/src/net/sample.c b/src/net/sample.c index d158398c6..b700e49c1 100644 --- a/src/net/sample.c +++ b/src/net/sample.c @@ -26,8 +26,8 @@ void _z_sample_move(_z_sample_t *dst, _z_sample_t *src) { void _z_sample_clear(_z_sample_t *sample) { _z_keyexpr_clear(&sample->keyexpr); - _z_bytes_drop(&sample->payload); _z_encoding_clear(&sample->encoding); + _z_bytes_drop(&sample->payload); _z_bytes_drop(&sample->attachment); } @@ -56,32 +56,3 @@ _z_sample_t _z_sample_duplicate(const _z_sample_t *src) { _z_sample_copy(&dst, src); return dst; } - -#if Z_FEATURE_SUBSCRIPTION == 1 -void _z_sample_create(_z_sample_t *s, _z_keyexpr_t *key, _z_bytes_t *payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, _z_bytes_t *attachment, - z_reliability_t reliability) { - s->kind = kind; - s->qos = qos; - s->reliability = reliability; - s->keyexpr = _z_keyexpr_steal(key); - s->timestamp = _z_timestamp_check(timestamp) ? _z_timestamp_duplicate(timestamp) : _z_timestamp_null(); - _z_encoding_move(&s->encoding, encoding); - _z_bytes_move(&s->attachment, attachment); - _z_bytes_move(&s->payload, payload); -} -#else -void _z_sample_create(_z_sample_t *s, _z_keyexpr_t *key, _z_bytes_t *payload, const _z_timestamp_t *timestamp, - _z_encoding_t *encoding, const z_sample_kind_t kind, const _z_qos_t qos, _z_bytes_t *attachment, - z_reliability_t reliability) { - _ZP_UNUSED(key); - _ZP_UNUSED(payload); - _ZP_UNUSED(timestamp); - _ZP_UNUSED(encoding); - _ZP_UNUSED(kind); - _ZP_UNUSED(qos); - _ZP_UNUSED(attachment); - _ZP_UNUSED(reliability); - *s = _z_sample_null(); -} -#endif diff --git a/src/net/session.c b/src/net/session.c index cf86220cd..cf3a7e991 100644 --- a/src/net/session.c +++ b/src/net/session.c @@ -95,7 +95,7 @@ z_result_t _z_open(_z_session_rc_t *zn, _z_config_t *config) { _z_hello_list_t *hellos = _z_scout_inner(what, zid, &mcast_locator, timeout, true); if (hellos != NULL) { _z_hello_t *hello = _z_hello_list_head(hellos); - _z_string_svec_copy(&locators, &hello->_locators); + _z_string_svec_copy(&locators, &hello->_locators, true); } _z_hello_list_free(&hellos); } else { @@ -112,7 +112,7 @@ z_result_t _z_open(_z_session_rc_t *zn, _z_config_t *config) { } locators = _z_string_svec_make(1); _z_string_t s = _z_string_copy_from_str(_z_config_get(config, key)); - _z_string_svec_append(&locators, &s); + _z_string_svec_append(&locators, &s, true); } ret = _Z_ERR_SCOUT_NO_RESULTS; diff --git a/src/protocol/codec.c b/src/protocol/codec.c index 64f22cade..eea67422e 100644 --- a/src/protocol/codec.c +++ b/src/protocol/codec.c @@ -194,37 +194,51 @@ z_result_t _z_zsize_decode_with_reader(_z_zint_t *zint, __z_single_byte_reader_t z_result_t _z_uint8_decode_reader(uint8_t *zint, void *context) { return _z_uint8_decode(zint, (_z_zbuf_t *)context); } z_result_t _z_zint64_decode(uint64_t *zint, _z_zbuf_t *zbf) { - return _z_zint64_decode_with_reader(zint, _z_uint8_decode_reader, (void *)zbf); + *zint = 0; + uint8_t b = 0; + _Z_RETURN_IF_ERR(_z_uint8_decode(&b, zbf)); + + uint8_t i = 0; + while (((b & 0x80) != 0) && (i != 7 * (VLE_LEN - 1))) { + *zint = *zint | ((uint64_t)(b & 0x7f)) << i; + _Z_RETURN_IF_ERR(_z_uint8_decode(&b, zbf)); + i = i + (uint8_t)7; + } + *zint = *zint | ((uint64_t)b << i); + return _Z_RES_OK; } z_result_t _z_zint16_decode(uint16_t *zint, _z_zbuf_t *zbf) { - z_result_t ret = _Z_RES_OK; uint64_t buf; _Z_RETURN_IF_ERR(_z_zint64_decode(&buf, zbf)); - if (buf <= UINT16_MAX) { - *zint = (uint16_t)buf; - } else { + if (buf > UINT16_MAX) { _Z_INFO("Invalid zint16 value decoded"); - ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - return ret; + *zint = (uint16_t)buf; + return _Z_RES_OK; } z_result_t _z_zint32_decode(uint32_t *zint, _z_zbuf_t *zbf) { - z_result_t ret = _Z_RES_OK; uint64_t buf; _Z_RETURN_IF_ERR(_z_zint64_decode(&buf, zbf)); - if (buf <= UINT32_MAX) { - *zint = (uint32_t)buf; - } else { + if (buf > UINT32_MAX) { _Z_INFO("Invalid zint32 value decoded"); - ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - return ret; + *zint = (uint32_t)buf; + return _Z_RES_OK; } z_result_t _z_zsize_decode(_z_zint_t *zint, _z_zbuf_t *zbf) { - return _z_zsize_decode_with_reader(zint, _z_uint8_decode_reader, (void *)zbf); + uint64_t buf; + _Z_RETURN_IF_ERR(_z_zint64_decode(&buf, zbf)); + if (buf > SIZE_MAX) { + _Z_INFO("Invalide zsize value decoded"); + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + *zint = (_z_zint_t)buf; + return _Z_RES_OK; } /*------------------ uint8_array ------------------*/ @@ -281,15 +295,16 @@ z_result_t _z_slice_val_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice z_result_t _z_slice_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice_decode_na(bs, zbf); } -z_result_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf) { +z_result_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf, _z_arc_slice_t *arcs) { // Decode slice _z_slice_t s; _Z_RETURN_IF_ERR(_z_slice_decode(&s, zbf)); // Calc offset size_t offset = _z_ptr_u8_diff(s.start, _Z_RC_IN_VAL(&zbf->_slice)->start); // Get ownership of subslice - _z_arc_slice_t arcs = _z_arc_slice_wrap_slice_rc(&zbf->_slice, offset, s.len); - return _z_bytes_append_slice(bs, &arcs); + *arcs = _z_arc_slice_wrap_slice_rc(&zbf->_slice, offset, s.len); + _z_bytes_alias_arc_slice(bs, arcs); + return _Z_RES_OK; } z_result_t _z_bytes_encode_val(_z_wbuf_t *wbf, const _z_bytes_t *bs) { diff --git a/src/protocol/codec/message.c b/src/protocol/codec/message.c index 35c8fa826..c11c62e46 100644 --- a/src/protocol/codec/message.c +++ b/src/protocol/codec/message.c @@ -327,7 +327,7 @@ z_result_t _z_push_body_decode_extensions(_z_msg_ext_t *extension, void *ctx) { return ret; } -z_result_t _z_push_body_decode(_z_push_body_t *pshb, _z_zbuf_t *zbf, uint8_t header) { +z_result_t _z_push_body_decode(_z_push_body_t *pshb, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { z_result_t ret = _Z_RES_OK; switch (_Z_MID(header)) { case _Z_MID_Z_PUT: { @@ -342,7 +342,7 @@ z_result_t _z_push_body_decode(_z_push_body_t *pshb, _z_zbuf_t *zbf, uint8_t hea _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_push_body_decode_extensions, pshb)); } if (ret == _Z_RES_OK) { - _Z_RETURN_IF_ERR(_z_bytes_decode(&pshb->_body._put._payload, zbf)); + _Z_RETURN_IF_ERR(_z_bytes_decode(&pshb->_body._put._payload, zbf, arcs)); } break; } @@ -367,10 +367,10 @@ z_result_t _z_put_encode(_z_wbuf_t *wbf, const _z_msg_put_t *put) { _z_push_body_t body = {._is_put = true, ._body = {._put = *put}}; return _z_push_body_encode(wbf, &body); } -z_result_t _z_put_decode(_z_msg_put_t *put, _z_zbuf_t *zbf, uint8_t header) { +z_result_t _z_put_decode(_z_msg_put_t *put, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { assert(_Z_MID(header) == _Z_MID_Z_PUT); _z_push_body_t body = {._is_put = true, ._body = {._put = *put}}; - z_result_t ret = _z_push_body_decode(&body, zbf, header); + z_result_t ret = _z_push_body_decode(&body, zbf, header, arcs); *put = body._body._put; return ret; } @@ -382,7 +382,7 @@ z_result_t _z_del_encode(_z_wbuf_t *wbf, const _z_msg_del_t *del) { z_result_t _z_del_decode(_z_msg_del_t *del, _z_zbuf_t *zbf, uint8_t header) { assert(_Z_MID(header) == _Z_MID_Z_DEL); _z_push_body_t body = {._is_put = false, ._body = {._del = *del}}; - z_result_t ret = _z_push_body_decode(&body, zbf, header); + z_result_t ret = _z_push_body_decode(&body, zbf, header, NULL); *del = body._body._del; return ret; } @@ -509,7 +509,7 @@ z_result_t _z_reply_decode_extension(_z_msg_ext_t *extension, void *ctx) { } return ret; } -z_result_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header) { +z_result_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { if (_Z_HAS_FLAG(header, _Z_FLAG_Z_R_C)) { _Z_RETURN_IF_ERR(_z_uint8_decode((uint8_t *)&reply->_consolidation, zbf)); } else { @@ -520,7 +520,7 @@ z_result_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header } uint8_t put_header = 0; _Z_RETURN_IF_ERR(_z_uint8_decode(&put_header, zbf)); - _Z_RETURN_IF_ERR(_z_push_body_decode(&reply->_body, zbf, put_header)); + _Z_RETURN_IF_ERR(_z_push_body_decode(&reply->_body, zbf, put_header, arcs)); return _Z_RES_OK; } @@ -569,14 +569,14 @@ z_result_t _z_err_decode_extension(_z_msg_ext_t *extension, void *ctx) { } return ret; } -z_result_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header) { +z_result_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { if (_Z_HAS_FLAG(header, _Z_FLAG_Z_E_E)) { _Z_RETURN_IF_ERR(_z_encoding_decode(&err->_encoding, zbf)); } if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_err_decode_extension, err)); } - _Z_RETURN_IF_ERR(_z_bytes_decode(&err->_payload, zbf)); + _Z_RETURN_IF_ERR(_z_bytes_decode(&err->_payload, zbf, arcs)); return _Z_RES_OK; } diff --git a/src/protocol/codec/network.c b/src/protocol/codec/network.c index de453c9ae..44cf9cde9 100644 --- a/src/protocol/codec/network.c +++ b/src/protocol/codec/network.c @@ -92,7 +92,7 @@ z_result_t _z_push_decode_ext_cb(_z_msg_ext_t *extension, void *ctx) { return ret; } -z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header) { +z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { z_result_t ret = _Z_RES_OK; msg->_qos = _Z_N_QOS_DEFAULT; ret |= _z_keyexpr_decode(&msg->_key, zbf, _Z_HAS_FLAG(header, _Z_FLAG_N_PUSH_N)); @@ -104,7 +104,7 @@ z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header) if (ret == _Z_RES_OK) { uint8_t msgheader; _Z_RETURN_IF_ERR(_z_uint8_decode(&msgheader, zbf)); - _Z_RETURN_IF_ERR(_z_push_body_decode(&msg->_body, zbf, msgheader)); + _Z_RETURN_IF_ERR(_z_push_body_decode(&msg->_body, zbf, msgheader, arcs)); } return ret; @@ -206,7 +206,7 @@ z_result_t _z_request_decode_extensions(_z_msg_ext_t *extension, void *ctx) { } return _Z_RES_OK; } -z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, const uint8_t header) { +z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, const uint8_t header, _z_arc_slice_t *arcs) { msg->_ext_qos = _Z_N_QOS_DEFAULT; _Z_RETURN_IF_ERR(_z_zsize_decode(&msg->_rid, zbf)); _Z_RETURN_IF_ERR(_z_keyexpr_decode(&msg->_key, zbf, _Z_HAS_FLAG(header, _Z_FLAG_N_REQUEST_N))); @@ -224,7 +224,7 @@ z_result_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, const uint } break; case _Z_MID_Z_PUT: { msg->_tag = _Z_REQUEST_PUT; - _Z_RETURN_IF_ERR(_z_put_decode(&msg->_body._put, zbf, zheader)); + _Z_RETURN_IF_ERR(_z_put_decode(&msg->_body._put, zbf, zheader, arcs)); } break; case _Z_MID_Z_DEL: { msg->_tag = _Z_REQUEST_DEL; @@ -334,7 +334,7 @@ z_result_t _z_response_decode_extension(_z_msg_ext_t *extension, void *ctx) { return ret; } -z_result_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t header) { +z_result_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs) { _Z_DEBUG("Decoding _Z_MID_N_RESPONSE"); msg->_ext_qos = _Z_N_QOS_DEFAULT; z_result_t ret = _Z_RES_OK; @@ -352,12 +352,12 @@ z_result_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t switch (_Z_MID(inner_header)) { case _Z_MID_Z_REPLY: { msg->_tag = _Z_RESPONSE_BODY_REPLY; - ret = _z_reply_decode(&msg->_body._reply, zbf, inner_header); + ret = _z_reply_decode(&msg->_body._reply, zbf, inner_header, arcs); break; } case _Z_MID_Z_ERR: { msg->_tag = _Z_RESPONSE_BODY_ERR; - ret = _z_err_decode(&msg->_body._err, zbf, inner_header); + ret = _z_err_decode(&msg->_body._err, zbf, inner_header, arcs); break; } default: { @@ -513,7 +513,7 @@ z_result_t _z_network_message_encode(_z_wbuf_t *wbf, const _z_network_message_t return _Z_ERR_GENERIC; } } -z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf) { +z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf, _z_arc_slice_t *arcs) { uint8_t header; _Z_RETURN_IF_ERR(_z_uint8_decode(&header, zbf)); switch (_Z_MID(header)) { @@ -523,15 +523,15 @@ z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf) } break; case _Z_MID_N_PUSH: { msg->_tag = _Z_N_PUSH; - return _z_push_decode(&msg->_body._push, zbf, header); + return _z_push_decode(&msg->_body._push, zbf, header, arcs); } break; case _Z_MID_N_REQUEST: { msg->_tag = _Z_N_REQUEST; - return _z_request_decode(&msg->_body._request, zbf, header); + return _z_request_decode(&msg->_body._request, zbf, header, arcs); } break; case _Z_MID_N_RESPONSE: { msg->_tag = _Z_N_RESPONSE; - return _z_response_decode(&msg->_body._response, zbf, header); + return _z_response_decode(&msg->_body._response, zbf, header, arcs); } break; case _Z_MID_N_RESPONSE_FINAL: { msg->_tag = _Z_N_RESPONSE_FINAL; diff --git a/src/protocol/codec/transport.c b/src/protocol/codec/transport.c index f09b5460f..5e07d5fea 100644 --- a/src/protocol/codec/transport.c +++ b/src/protocol/codec/transport.c @@ -28,10 +28,6 @@ #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/result.h" -#define _Z_FRAME_VEC_BASE_SIZE 8 // Abritrary small value -#define _Z_FRAME_VEC_SIZE_FROM_ZBUF_LEN(len) \ - (_Z_FRAME_VEC_BASE_SIZE + (len) / Z_CONFIG_FRAME_AVG_MSG_SIZE) // Approximate number of messages in frame - uint8_t _z_whatami_to_uint8(z_whatami_t whatami) { return (whatami >> 1) & 0x03; // get set bit index; only first 3 bits can be set } @@ -225,7 +221,7 @@ z_result_t _z_init_decode(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header) if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_INIT_A) == true)) { ret |= _z_slice_decode(&msg->_cookie, zbf); } else { - msg->_cookie = _z_slice_empty(); + msg->_cookie = _z_slice_null(); } if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { @@ -270,10 +266,10 @@ z_result_t _z_open_decode(_z_t_msg_open_t *msg, _z_zbuf_t *zbf, uint8_t header) if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_OPEN_A) == false)) { ret |= _z_slice_decode(&msg->_cookie, zbf); if (ret != _Z_RES_OK) { - msg->_cookie = _z_slice_empty(); + msg->_cookie = _z_slice_null(); } } else { - msg->_cookie = _z_slice_empty(); + msg->_cookie = _z_slice_null(); } if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x02); @@ -352,7 +348,50 @@ z_result_t _z_frame_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_frame_ return ret; } -z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header) { +static void _z_frame_update_arcs_msg_pool(_z_network_message_svec_t *msg_pool, _z_arc_slice_svec_t *arc_pool) { + for (size_t i = 0; i < arc_pool->_len; i++) { + _z_network_message_t *nm = _z_network_message_svec_get(msg_pool, i); + switch (nm->_tag) { + case _Z_N_PUSH: { + if (!nm->_body._push._body._is_put) { + continue; + } + _z_bytes_alias_arc_slice(&nm->_body._push._body._body._put._payload, + _z_arc_slice_svec_get(arc_pool, i)); + } break; + case _Z_N_REQUEST: { + if (nm->_body._request._tag != _Z_REQUEST_PUT) { + continue; + } + _z_bytes_alias_arc_slice(&nm->_body._request._body._put._payload, _z_arc_slice_svec_get(arc_pool, i)); + } break; + case _Z_N_RESPONSE: { + switch (nm->_body._response._tag) { + case _Z_RESPONSE_BODY_REPLY: + if (!nm->_body._response._body._reply._body._is_put) { + continue; + } + _z_bytes_alias_arc_slice(&nm->_body._response._body._reply._body._body._put._payload, + _z_arc_slice_svec_get(arc_pool, i)); + break; + + case _Z_RESPONSE_BODY_ERR: + _z_bytes_alias_arc_slice(&nm->_body._response._body._err._payload, + _z_arc_slice_svec_get(arc_pool, i)); + break; + + default: + continue; + } + } + default: + continue; + } + } +} + +z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_svec_t *arc_pool, + _z_network_message_svec_t *msg_pool) { z_result_t ret = _Z_RES_OK; *msg = (_z_t_msg_frame_t){0}; @@ -360,26 +399,32 @@ z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z)) { _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, 0x04)); } - // Create message vector - size_t var_size = _Z_FRAME_VEC_SIZE_FROM_ZBUF_LEN(_z_zbuf_len(zbf)); - msg->_messages = _z_network_message_svec_make(var_size); - if (msg->_messages._capacity == 0) { - return _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - _z_network_message_svec_init(&msg->_messages); + // Init message vector + msg_pool->_len = 0; + arc_pool->_len = 0; + _z_network_message_svec_init(msg_pool, 0); size_t msg_idx = 0; while (_z_zbuf_len(zbf) > 0) { // Expand message vector if needed - if (msg_idx >= msg->_messages._capacity) { - _Z_RETURN_IF_ERR(_z_network_message_svec_expand(&msg->_messages)); - _z_network_message_svec_init(&msg->_messages); + if (msg_idx >= msg_pool->_capacity) { + _Z_RETURN_IF_ERR(_z_network_message_svec_expand(msg_pool, false)); + _z_network_message_svec_init(msg_pool, msg_pool->_len); + } + // Expand arc pool if needed + if (msg_idx >= arc_pool->_capacity) { + _Z_RETURN_IF_ERR(_z_arc_slice_svec_expand(arc_pool, false)); + // Update arcs references in msg pool + _z_frame_update_arcs_msg_pool(msg_pool, arc_pool); } // Mark the reading position of the iobfer size_t r_pos = _z_zbuf_get_rpos(zbf); - _z_network_message_t *nm = _z_network_message_svec_get_mut(&msg->_messages, msg_idx); - ret = _z_network_message_decode(nm, zbf); + // Retrieve storage in resource pool + _z_network_message_t *nm = _z_network_message_svec_get_mut(msg_pool, msg_idx); + _z_arc_slice_t *arcs = _z_arc_slice_svec_get_mut(arc_pool, msg_idx); + // Decode message + ret = _z_network_message_decode(nm, zbf, arcs); if (ret != _Z_RES_OK) { - _z_network_message_svec_clear(&msg->_messages); + _z_network_message_svec_reset(msg_pool); _z_zbuf_set_rpos(zbf, r_pos); // Restore the reading position of the iobfer // FIXME: Check for the return error, since not all of them means a decoding error @@ -391,9 +436,12 @@ z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header } return ret; } - msg->_messages._len++; + arc_pool->_len++; + msg_pool->_len++; msg_idx++; } + // Alias network message svec in frame struct + msg->_messages = _z_network_message_svec_alias(msg_pool); return _Z_RES_OK; } @@ -493,7 +541,8 @@ z_result_t _z_transport_message_encode(_z_wbuf_t *wbf, const _z_transport_messag return ret; } -z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *zbf) { +z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *zbf, _z_arc_slice_svec_t *arc_pool, + _z_network_message_svec_t *msg_pool) { z_result_t ret = _Z_RES_OK; ret |= _z_uint8_decode(&msg->_header, zbf); // Decode the header @@ -501,7 +550,7 @@ z_result_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *z uint8_t mid = _Z_MID(msg->_header); switch (mid) { case _Z_MID_T_FRAME: { - ret |= _z_frame_decode(&msg->_body._frame, zbf, msg->_header); + ret |= _z_frame_decode(&msg->_body._frame, zbf, msg->_header, arc_pool, msg_pool); } break; case _Z_MID_T_FRAGMENT: { ret |= _z_fragment_decode(&msg->_body._fragment, zbf, msg->_header); diff --git a/src/protocol/core.c b/src/protocol/core.c index 16842f708..da1ef9ef8 100644 --- a/src/protocol/core.c +++ b/src/protocol/core.c @@ -63,7 +63,7 @@ z_result_t _z_value_copy(_z_value_t *dst, const _z_value_t *src) { z_result_t _z_hello_copy(_z_hello_t *dst, const _z_hello_t *src) { *dst = _z_hello_null(); - _Z_RETURN_IF_ERR(_z_string_svec_copy(&dst->_locators, &src->_locators)); + _Z_RETURN_IF_ERR(_z_string_svec_copy(&dst->_locators, &src->_locators, true)); dst->_version = src->_version; dst->_whatami = src->_whatami; memcpy(&dst->_zid.id, &src->_zid.id, _Z_ID_LEN); diff --git a/src/protocol/definitions/message.c b/src/protocol/definitions/message.c index 0c3058e0a..e8f967e62 100644 --- a/src/protocol/definitions/message.c +++ b/src/protocol/definitions/message.c @@ -23,8 +23,7 @@ void _z_msg_reply_clear(_z_msg_reply_t *msg) { _z_push_body_clear(&msg->_body); } void _z_msg_put_clear(_z_msg_put_t *msg) { - // TODO: systematically move everything so there's nothing to clear - _z_bytes_drop(&msg->_payload); + _z_bytes_aliased_drop(&msg->_payload); _z_bytes_drop(&msg->_attachment); _z_encoding_clear(&msg->_encoding); _z_timestamp_clear(&msg->_commons._timestamp); @@ -45,5 +44,5 @@ void _z_msg_query_clear(_z_msg_query_t *msg) { } void _z_msg_err_clear(_z_msg_err_t *err) { _z_encoding_clear(&err->_encoding); - _z_bytes_drop(&err->_payload); + _z_bytes_aliased_drop(&err->_payload); } diff --git a/src/protocol/definitions/transport.c b/src/protocol/definitions/transport.c index 448951e46..fa910b771 100644 --- a/src/protocol/definitions/transport.c +++ b/src/protocol/definitions/transport.c @@ -40,7 +40,7 @@ void _z_t_msg_close_clear(_z_t_msg_close_t *msg) { (void)(msg); } void _z_t_msg_keep_alive_clear(_z_t_msg_keep_alive_t *msg) { (void)(msg); } -void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg) { _z_network_message_svec_clear(&msg->_messages); } +void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg) { (void)(msg); } void _z_t_msg_fragment_clear(_z_t_msg_fragment_t *msg) { _z_slice_clear(&msg->_payload); } @@ -248,7 +248,7 @@ _z_transport_message_t _z_t_msg_make_frame_header(_z_zint_t sn, z_reliability_t /*------------------ Fragment Message ------------------*/ _z_transport_message_t _z_t_msg_make_fragment_header(_z_zint_t sn, z_reliability_t reliability, bool is_last) { - return _z_t_msg_make_fragment(sn, _z_slice_empty(), reliability, is_last); + return _z_t_msg_make_fragment(sn, _z_slice_null(), reliability, is_last); } _z_transport_message_t _z_t_msg_make_fragment(_z_zint_t sn, _z_slice_t payload, z_reliability_t reliability, bool is_last) { @@ -307,7 +307,7 @@ void _z_t_msg_copy_keep_alive(_z_t_msg_keep_alive_t *clone, _z_t_msg_keep_alive_ void _z_t_msg_copy_frame(_z_t_msg_frame_t *clone, _z_t_msg_frame_t *msg) { clone->_sn = msg->_sn; - _z_network_message_svec_copy(&clone->_messages, &msg->_messages); + _z_network_message_svec_copy(&clone->_messages, &msg->_messages, false); } /*------------------ Transport Message ------------------*/ diff --git a/src/protocol/keyexpr.c b/src/protocol/keyexpr.c index f71e38875..15e1beee0 100644 --- a/src/protocol/keyexpr.c +++ b/src/protocol/keyexpr.c @@ -82,7 +82,6 @@ void _z_keyexpr_clear(_z_keyexpr_t *rk) { if (_z_keyexpr_has_suffix(rk)) { _z_string_clear(&rk->_suffix); } - rk->_suffix = _z_string_null(); } void _z_keyexpr_free(_z_keyexpr_t **rk) { @@ -103,7 +102,15 @@ bool _z_keyexpr_equals(const _z_keyexpr_t *left, const _z_keyexpr_t *right) { if (_z_keyexpr_mapping_id(left) != _z_keyexpr_mapping_id(right)) { return false; } - return _z_string_equals(&left->_suffix, &right->_suffix); + bool l_suffix = _z_keyexpr_has_suffix(left); + bool r_suffix = _z_keyexpr_has_suffix(right); + if (l_suffix != r_suffix) { + return false; + } + if (l_suffix && r_suffix) { + return _z_string_equals(&left->_suffix, &right->_suffix); + } + return true; } _z_keyexpr_t _z_keyexpr_alias_from_user_defined(_z_keyexpr_t src, bool try_declared) { diff --git a/src/session/query.c b/src/session/query.c index 241839551..22f05571c 100644 --- a/src/session/query.c +++ b/src/session/query.c @@ -111,39 +111,38 @@ z_result_t _z_register_pending_query(_z_session_t *zn, _z_pending_query_t *pen_q return ret; } -z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, const _z_keyexpr_t keyexpr, - _z_msg_put_t *msg, z_sample_kind_t kind) { - z_result_t ret = _Z_RES_OK; - +static z_result_t _z_trigger_query_reply_partial_inner(_z_session_t *zn, const _z_zint_t id, + const _z_keyexpr_t *keyexpr, _z_msg_put_t *msg, + z_sample_kind_t kind) { _z_session_mutex_lock(zn); + // Get query infos _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, id); - if ((ret == _Z_RES_OK) && (pen_qry == NULL)) { - ret = _Z_ERR_ENTITY_UNKNOWN; + if (pen_qry == NULL) { + _z_session_mutex_unlock(zn); + return _Z_ERR_ENTITY_UNKNOWN; } - - _z_keyexpr_t expanded_ke = __unsafe_z_get_expanded_key_from_key(zn, &keyexpr, true); - if ((ret == _Z_RES_OK) && - ((pen_qry->_anykey == false) && (_z_keyexpr_suffix_intersects(&pen_qry->_key, &keyexpr) == false))) { - ret = _Z_ERR_QUERY_NOT_MATCH; + _z_keyexpr_t expanded_ke = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, true); + if (!pen_qry->_anykey && !_z_keyexpr_suffix_intersects(&pen_qry->_key, keyexpr)) { + _z_session_mutex_unlock(zn); + return _Z_ERR_QUERY_NOT_MATCH; } - // Build the reply - _z_reply_t reply = _z_reply_create(&expanded_ke, zn->_local_zid, &msg->_payload, &msg->_commons._timestamp, - &msg->_encoding, kind, &msg->_attachment); - - bool drop = false; - // Verify if this is a newer reply, free the old one in case it is - if ((ret == _Z_RES_OK) && ((pen_qry->_consolidation == Z_CONSOLIDATION_MODE_LATEST) || - (pen_qry->_consolidation == Z_CONSOLIDATION_MODE_MONOTONIC))) { + _z_reply_t reply = _z_reply_alias(&expanded_ke, zn->_local_zid, &msg->_payload, &msg->_commons._timestamp, + &msg->_encoding, kind, &msg->_attachment); + // Process monotonic & latest consolidation mode + if ((pen_qry->_consolidation == Z_CONSOLIDATION_MODE_LATEST) || + (pen_qry->_consolidation == Z_CONSOLIDATION_MODE_MONOTONIC)) { + bool drop = false; _z_pending_reply_list_t *pen_rps = pen_qry->_pending_replies; _z_pending_reply_t *pen_rep = NULL; + + // Verify if this is a newer reply, free the old one in case it is while (pen_rps != NULL) { pen_rep = _z_pending_reply_list_head(pen_rps); - // Check if this is the same resource key if (_z_string_equals(&pen_rep->_reply.data._result.sample.keyexpr._suffix, - &reply.data._result.sample.keyexpr._suffix) == true) { + &reply.data._result.sample.keyexpr._suffix)) { if (msg->_commons._timestamp.time <= pen_rep->_tstamp.time) { drop = true; } else { @@ -154,87 +153,74 @@ z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, } pen_rps = _z_pending_reply_list_tail(pen_rps); } - - if (drop == false) { + if (!drop) { // Cache most recent reply pen_rep = (_z_pending_reply_t *)z_malloc(sizeof(_z_pending_reply_t)); - if (pen_rep != NULL) { - if (pen_qry->_consolidation == Z_CONSOLIDATION_MODE_MONOTONIC) { - // No need to store the whole reply in the monotonic mode. - _z_reply_t partial_reply; - (void)memset(&partial_reply, 0, - sizeof(_z_reply_t)); // Avoid warnings on uninitialized values on the reply - partial_reply.data._tag = _Z_REPLY_TAG_DATA; - partial_reply.data._result.sample.keyexpr = - _z_keyexpr_duplicate(&reply.data._result.sample.keyexpr); - pen_rep->_reply = partial_reply; - } else { - pen_rep->_reply = reply; // Store the whole reply in the latest mode - } - pen_rep->_tstamp = _z_timestamp_duplicate(&msg->_commons._timestamp); - pen_qry->_pending_replies = _z_pending_reply_list_push(pen_qry->_pending_replies, pen_rep); + if (pen_rep == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + if (pen_qry->_consolidation == Z_CONSOLIDATION_MODE_MONOTONIC) { + // No need to store the whole reply in the monotonic mode. + pen_rep->_reply = _z_reply_null(); + pen_rep->_reply.data._tag = _Z_REPLY_TAG_DATA; + pen_rep->_reply.data._result.sample.keyexpr = _z_keyexpr_duplicate(&reply.data._result.sample.keyexpr); } else { - ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + // Copy the reply to store it out of context + _Z_RETURN_IF_ERR(_z_reply_copy(&pen_rep->_reply, &reply)); } + pen_rep->_tstamp = _z_timestamp_duplicate(&msg->_commons._timestamp); + pen_qry->_pending_replies = _z_pending_reply_list_push(pen_qry->_pending_replies, pen_rep); } } - _z_session_mutex_unlock(zn); - // Trigger the user callback - if ((ret == _Z_RES_OK) && (pen_qry->_consolidation != Z_CONSOLIDATION_MODE_LATEST)) { - _z_reply_t cb_reply = _z_reply_null(); - cb_reply = _z_reply_move(&reply); - pen_qry->_callback(&cb_reply, pen_qry->_arg); - _z_reply_clear(&cb_reply); - return ret; - } - // Other cases - if (drop || (ret != _Z_RES_OK)) { - _z_reply_clear(&reply); + // Trigger callback if applicable + if (pen_qry->_consolidation != Z_CONSOLIDATION_MODE_LATEST) { + pen_qry->_callback(&reply, pen_qry->_arg); } + return _Z_RES_OK; +} +z_result_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, _z_keyexpr_t *keyexpr, + _z_msg_put_t *msg, z_sample_kind_t kind) { + z_result_t ret = _z_trigger_query_reply_partial_inner(zn, id, keyexpr, msg, kind); + // Clean up + _z_keyexpr_clear(keyexpr); + _z_bytes_aliased_drop(&msg->_payload); + _z_bytes_drop(&msg->_attachment); + _z_encoding_clear(&msg->_encoding); return ret; } z_result_t _z_trigger_query_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *msg) { z_result_t ret = _Z_RES_OK; + // Retrieve query _z_session_mutex_lock(zn); - _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, id); - if ((ret == _Z_RES_OK) && (pen_qry == NULL)) { + if (pen_qry == NULL) { ret = _Z_ERR_ENTITY_UNKNOWN; } - - // Build the reply - _z_reply_t reply = _z_reply_err_create(msg->_payload, &msg->_encoding); - _z_session_mutex_unlock(zn); // Trigger the user callback if (ret == _Z_RES_OK) { - _z_reply_t cb_reply = _z_reply_null(); - cb_reply = _z_reply_move(&reply); - pen_qry->_callback(&cb_reply, pen_qry->_arg); - _z_reply_clear(&cb_reply); + _z_reply_t reply = _z_reply_err_alias(&msg->_payload, &msg->_encoding); + pen_qry->_callback(&reply, pen_qry->_arg); } - - if (ret != _Z_RES_OK) { - _z_reply_clear(&reply); - } - + // Clean up + _z_bytes_aliased_drop(&msg->_payload); + _z_encoding_clear(&msg->_encoding); return ret; } z_result_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id) { z_result_t ret = _Z_RES_OK; + // Retrieve query _z_session_mutex_lock(zn); - - // Final reply received for unknown query id _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, id); - if ((ret == _Z_RES_OK) && (pen_qry == NULL)) { + if (pen_qry == NULL) { ret = _Z_ERR_ENTITY_UNKNOWN; } // The reply is the final one, apply consolidation if needed @@ -243,21 +229,15 @@ z_result_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id) { _z_pending_reply_t *pen_rep = _z_pending_reply_list_head(pen_qry->_pending_replies); // Trigger the query handler - _z_reply_t cb_reply = _z_reply_null(); - cb_reply = _z_reply_move(&pen_rep->_reply); - pen_qry->_callback(&cb_reply, pen_qry->_arg); + pen_qry->_callback(&pen_rep->_reply, pen_qry->_arg); pen_qry->_pending_replies = _z_pending_reply_list_pop(pen_qry->_pending_replies, NULL); - _z_reply_clear(&cb_reply); } } - if (ret == _Z_RES_OK) { // Dropping a pending query triggers the dropper callback that is now the equivalent to a reply with the FINAL zn->_pending_queries = _z_pending_query_list_drop_filter(zn->_pending_queries, _z_pending_query_eq, pen_qry); } - _z_session_mutex_unlock(zn); - return ret; } diff --git a/src/session/queryable.c b/src/session/queryable.c index ba04debd7..d3b120751 100644 --- a/src/session/queryable.c +++ b/src/session/queryable.c @@ -25,8 +25,63 @@ #include "zenoh-pico/session/resource.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/pointers.h" +#include "zenoh-pico/utils/string.h" #if Z_FEATURE_QUERYABLE == 1 + +#define _Z_QLEINFOS_VEC_SIZE 4 // Arbitrary initial size + +#if Z_FEATURE_RX_CACHE == 1 +static inline bool _z_queryable_get_from_cache(_z_session_t *zn, const _z_keyexpr_t *ke, _z_keyexpr_t *ke_val, + _z_queryable_infos_svec_t *infos_val, size_t *qle_nb) { + if (!_z_keyexpr_equals(ke, &zn->_queryable_cache.ke_in)) { + return false; + } + *ke_val = _z_keyexpr_alias(zn->_queryable_cache.ke_out); + *infos_val = _z_queryable_infos_svec_alias(&zn->_queryable_cache.infos); + *qle_nb = zn->_queryable_cache.qle_nb; + return true; +} + +static inline void _z_queryable_update_cache(_z_session_t *zn, const _z_keyexpr_t *ke_in, const _z_keyexpr_t *ke_out, + _z_queryable_infos_svec_t *infos) { + // Clear previous data + _z_queryable_cache_clear(&zn->_queryable_cache); + // Register new info + zn->_queryable_cache.ke_in = _z_keyexpr_duplicate(ke_in); + zn->_queryable_cache.ke_out = _z_keyexpr_duplicate(ke_out); + zn->_queryable_cache.infos = _z_queryable_infos_svec_alias(infos); + zn->_queryable_cache.qle_nb = _z_queryable_infos_svec_len(infos); +} + +void _z_queryable_cache_clear(_z_queryable_cache_t *cache) { + _z_queryable_infos_svec_clear(&cache->infos); + _z_keyexpr_clear(&cache->ke_in); + _z_keyexpr_clear(&cache->ke_out); +} + +#else +static inline bool _z_queryable_get_from_cache(_z_session_t *zn, const _z_keyexpr_t *ke, _z_keyexpr_t *ke_val, + _z_queryable_infos_svec_t *infos_val, size_t *sub_nb) { + _ZP_UNUSED(zn); + _ZP_UNUSED(ke); + _ZP_UNUSED(ke_val); + _ZP_UNUSED(infos_val); + _ZP_UNUSED(sub_nb); + return false; +} + +static inline void _z_queryable_update_cache(_z_session_t *zn, const _z_keyexpr_t *ke_in, const _z_keyexpr_t *ke_out, + _z_queryable_infos_svec_t *infos) { + _ZP_UNUSED(zn); + _ZP_UNUSED(ke_in); + _ZP_UNUSED(ke_out); + _ZP_UNUSED(infos); + return; +} +#endif // Z_FEATURE_RX_CACHE == 1 + bool _z_session_queryable_eq(const _z_session_queryable_t *one, const _z_session_queryable_t *two) { return one->_id == two->_id; } @@ -39,7 +94,8 @@ void _z_session_queryable_clear(_z_session_queryable_t *qle) { } /*------------------ Queryable ------------------*/ -_z_session_queryable_rc_t *__z_get_session_queryable_by_id(_z_session_queryable_rc_list_t *qles, const _z_zint_t id) { +static _z_session_queryable_rc_t *__z_get_session_queryable_by_id(_z_session_queryable_rc_list_t *qles, + const _z_zint_t id) { _z_session_queryable_rc_t *ret = NULL; _z_session_queryable_rc_list_t *xs = qles; @@ -56,29 +112,12 @@ _z_session_queryable_rc_t *__z_get_session_queryable_by_id(_z_session_queryable_ return ret; } -_z_session_queryable_rc_list_t *__z_get_session_queryable_by_key(_z_session_queryable_rc_list_t *qles, - const _z_keyexpr_t key) { - _z_session_queryable_rc_list_t *ret = NULL; - - _z_session_queryable_rc_list_t *xs = qles; - while (xs != NULL) { - _z_session_queryable_rc_t *qle = _z_session_queryable_rc_list_head(xs); - if (_z_keyexpr_suffix_intersects(&_Z_RC_IN_VAL(qle)->_key, &key) == true) { - ret = _z_session_queryable_rc_list_push(ret, _z_session_queryable_rc_clone_as_ptr(qle)); - } - - xs = _z_session_queryable_rc_list_tail(xs); - } - - return ret; -} - /** * This function is unsafe because it operates in potentially concurrent data. * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_session_queryable_rc_t *__unsafe_z_get_session_queryable_by_id(_z_session_t *zn, const _z_zint_t id) { +static _z_session_queryable_rc_t *__unsafe_z_get_session_queryable_by_id(_z_session_t *zn, const _z_zint_t id) { _z_session_queryable_rc_list_t *qles = zn->_local_queryable; return __z_get_session_queryable_by_id(qles, id); } @@ -88,9 +127,23 @@ _z_session_queryable_rc_t *__unsafe_z_get_session_queryable_by_id(_z_session_t * * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_session_queryable_rc_list_t *__unsafe_z_get_session_queryable_by_key(_z_session_t *zn, const _z_keyexpr_t key) { +static z_result_t __unsafe_z_get_session_queryable_by_key(_z_session_t *zn, const _z_keyexpr_t *key, + _z_queryable_infos_svec_t *qle_infos) { _z_session_queryable_rc_list_t *qles = zn->_local_queryable; - return __z_get_session_queryable_by_key(qles, key); + + *qle_infos = _z_queryable_infos_svec_make(_Z_QLEINFOS_VEC_SIZE); + _z_session_queryable_rc_list_t *xs = qles; + while (xs != NULL) { + // Parse queryable list + _z_session_queryable_rc_t *qle = _z_session_queryable_rc_list_head(xs); + if (_z_keyexpr_suffix_intersects(&_Z_RC_IN_VAL(qle)->_key, key)) { + _z_queryable_infos_t new_qle_info = {.arg = _Z_RC_IN_VAL(qle)->_arg, + .callback = _Z_RC_IN_VAL(qle)->_callback}; + _Z_RETURN_IF_ERR(_z_queryable_infos_svec_append(qle_infos, &new_qle_info, false)); + } + xs = _z_session_queryable_rc_list_tail(xs); + } + return _Z_RES_OK; } _z_session_queryable_rc_t *_z_get_session_queryable_by_id(_z_session_t *zn, const _z_zint_t id) { @@ -103,17 +156,6 @@ _z_session_queryable_rc_t *_z_get_session_queryable_by_id(_z_session_t *zn, cons return qle; } -_z_session_queryable_rc_list_t *_z_get_session_queryable_by_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { - _z_session_mutex_lock(zn); - - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, false); - _z_session_queryable_rc_list_t *qles = __unsafe_z_get_session_queryable_by_key(zn, key); - - _z_session_mutex_unlock(zn); - - return qles; -} - _z_session_queryable_rc_t *_z_register_session_queryable(_z_session_t *zn, _z_session_queryable_t *q) { _Z_DEBUG(">>> Allocating queryable for (%ju:%.*s)", (uintmax_t)q->_key._id, (int)_z_string_len(&q->_key._suffix), _z_string_data(&q->_key._suffix)); @@ -132,37 +174,79 @@ _z_session_queryable_rc_t *_z_register_session_queryable(_z_session_t *zn, _z_se return ret; } -z_result_t _z_trigger_queryables(_z_session_rc_t *zsrc, _z_msg_query_t *msgq, const _z_keyexpr_t q_key, uint32_t qid, - const _z_bytes_t attachment) { - z_result_t ret = _Z_RES_OK; - _z_session_t *zn = _Z_RC_IN_VAL(zsrc); - - _z_session_mutex_lock(zn); - - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, &q_key, true); - if (_z_keyexpr_has_suffix(&key)) { - _z_session_queryable_rc_list_t *qles = __unsafe_z_get_session_queryable_by_key(zn, key); - +static z_result_t _z_session_queryable_get_infos(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_keyexpr_t *key, + _z_queryable_infos_svec_t *qles, size_t *qle_nb) { + // Check cache + if (!_z_queryable_get_from_cache(zn, keyexpr, key, qles, qle_nb)) { + _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr->_id, (int)_z_string_len(&keyexpr->_suffix), + _z_string_data(&keyexpr->_suffix), _z_keyexpr_mapping_id(keyexpr)); + _z_session_mutex_lock(zn); + *key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, true); + + if (!_z_keyexpr_has_suffix(key)) { + _z_session_mutex_unlock(zn); + return _Z_ERR_KEYEXPR_UNKNOWN; + } + // Get queryable list + z_result_t ret = __unsafe_z_get_session_queryable_by_key(zn, key, qles); _z_session_mutex_unlock(zn); + if (ret != _Z_RES_OK) { + return ret; + } + *qle_nb = _z_queryable_infos_svec_len(qles); + // Update cache + _z_queryable_update_cache(zn, keyexpr, key, qles); + } + return _Z_RES_OK; +} - // Build the z_query - _z_query_t q = _z_query_create(&msgq->_ext_value, &key, &msgq->_parameters, zsrc, qid, attachment); - _z_query_rc_t query = _z_query_rc_new_from_val(&q); - // Parse session_queryable list - _z_session_queryable_rc_list_t *xs = qles; - while (xs != NULL) { - _z_session_queryable_rc_t *qle = _z_session_queryable_rc_list_head(xs); - _Z_RC_IN_VAL(qle)->_callback(&query, _Z_RC_IN_VAL(qle)->_arg); - xs = _z_session_queryable_rc_list_tail(xs); +static z_result_t _z_trigger_queryables_inner(_z_session_rc_t *zsrc, _z_msg_query_t *msgq, const _z_keyexpr_t *q_key, + uint32_t qid) { + _z_session_t *zn = _Z_RC_IN_VAL(zsrc); + _z_keyexpr_t key; + _z_queryable_infos_svec_t qles; + size_t qle_nb; + // Retrieve sub infos + _Z_RETURN_IF_ERR(_z_session_queryable_get_infos(zn, q_key, &key, &qles, &qle_nb)); + // Check if there are queryables + _Z_DEBUG("Triggering %ju queryables for key %d - %.*s", (uintmax_t)qle_nb, key._id, + (int)_z_string_len(&key._suffix), _z_string_data(&key._suffix)); + if (qle_nb == 0) { + _z_keyexpr_clear(&key); + return _Z_RES_OK; + } + // Check anyke + char *slice_end = _z_ptr_char_offset((char *)msgq->_parameters.start, (ptrdiff_t)msgq->_parameters.len); + bool anyke = false; + if (_z_slice_check(&msgq->_parameters)) { + if (_z_strstr((char *)msgq->_parameters.start, slice_end, Z_SELECTOR_QUERY_MATCH) != NULL) { + anyke = true; } - // Clean up - _z_query_rc_drop(&query); - _z_session_queryable_rc_list_free(&qles); - } else { - _z_session_mutex_unlock(zn); - ret = _Z_ERR_KEYEXPR_UNKNOWN; } + // Build the z_query + _z_query_t query = + _z_query_alias(&msgq->_ext_value, &key, &msgq->_parameters, zsrc, qid, &msgq->_ext_attachment, anyke); + // Parse session_queryable svec + for (size_t i = 0; i < qle_nb; i++) { + _z_queryable_infos_t *qle_info = _z_queryable_infos_svec_get(&qles, i); + qle_info->callback(&query, qle_info->arg); + } + // Clean up + _z_keyexpr_clear(&key); +#if Z_FEATURE_RX_CACHE != 1 + _z_queryable_infos_svec_release(&qles); // Otherwise it's released with cache +#endif + return _Z_RES_OK; +} +z_result_t _z_trigger_queryables(_z_session_rc_t *zsrc, _z_msg_query_t *msgq, _z_keyexpr_t *q_key, uint32_t qid) { + z_result_t ret = _z_trigger_queryables_inner(zsrc, msgq, q_key, qid); + // Clean up + _z_keyexpr_clear(q_key); + _z_encoding_clear(&msgq->_ext_value.encoding); + _z_bytes_drop(&msgq->_ext_value.payload); + _z_bytes_drop(&msgq->_ext_attachment); + _z_slice_clear(&msgq->_parameters); return ret; } diff --git a/src/session/reply.c b/src/session/reply.c index 7eb13194c..6361099ee 100644 --- a/src/session/reply.c +++ b/src/session/reply.c @@ -19,7 +19,7 @@ #include "zenoh-pico/session/query.h" #include "zenoh-pico/utils/logging.h" -z_result_t _z_trigger_reply_partial(_z_session_t *zn, _z_zint_t id, _z_keyexpr_t key, _z_msg_reply_t *reply) { +z_result_t _z_trigger_reply_partial(_z_session_t *zn, _z_zint_t id, _z_keyexpr_t *key, _z_msg_reply_t *reply) { z_result_t ret = _Z_RES_OK; // TODO check id to know where to dispatch diff --git a/src/session/rx.c b/src/session/rx.c index 70213b898..c15e53810 100644 --- a/src/session/rx.c +++ b/src/session/rx.c @@ -93,8 +93,7 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * case _Z_REQUEST_QUERY: { #if Z_FEATURE_QUERYABLE == 1 _z_msg_query_t *query = &req->_body._query; - ret = _z_trigger_queryables(zsrc, query, req->_key, (uint32_t)req->_rid, - req->_body._query._ext_attachment); + ret = _z_trigger_queryables(zsrc, query, &req->_key, (uint32_t)req->_rid); #else _Z_DEBUG("_Z_REQUEST_QUERY dropped, queryables not supported"); #endif @@ -133,7 +132,7 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * switch (response->_tag) { case _Z_RESPONSE_BODY_REPLY: { _z_msg_reply_t *reply = &response->_body._reply; - ret = _z_trigger_reply_partial(zn, response->_request_id, response->_key, reply); + ret = _z_trigger_reply_partial(zn, response->_request_id, &response->_key, reply); } break; case _Z_RESPONSE_BODY_ERR: { _z_msg_err_t *error = &response->_body._err; diff --git a/src/session/scout.c b/src/session/scout.c index 28244f08f..5badf7201 100644 --- a/src/session/scout.c +++ b/src/session/scout.c @@ -89,7 +89,7 @@ _z_hello_list_t *__z_scout_loop(const _z_wbuf_t *wbf, _z_string_t *locator, unsi for (size_t i = 0; i < n_loc; i++) { _z_string_t s = _z_locator_to_string(&s_msg._body._hello._locators._val[i]); - _z_string_svec_append(&hello->_locators, &s); + _z_string_svec_append(&hello->_locators, &s, true); } } else { // @TODO: construct the locator departing from the sock address diff --git a/src/session/subscription.c b/src/session/subscription.c index 3e6297176..cad4821a5 100644 --- a/src/session/subscription.c +++ b/src/session/subscription.c @@ -34,12 +34,13 @@ #if Z_FEATURE_RX_CACHE == 1 static inline bool _z_subscription_get_from_cache(_z_session_t *zn, const _z_keyexpr_t *ke, _z_keyexpr_t *ke_val, - _z_subscription_infos_svec_t *infos_val) { + _z_subscription_infos_svec_t *infos_val, size_t *sub_nb) { if (!_z_keyexpr_equals(ke, &zn->_subscription_cache.ke_in)) { return false; } *ke_val = _z_keyexpr_alias(zn->_subscription_cache.ke_out); *infos_val = _z_subscription_infos_svec_alias(&zn->_subscription_cache.infos); + *sub_nb = zn->_subscription_cache.sub_nb; return true; } @@ -51,6 +52,7 @@ static inline void _z_subscription_update_cache(_z_session_t *zn, const _z_keyex zn->_subscription_cache.ke_in = _z_keyexpr_duplicate(ke_in); zn->_subscription_cache.ke_out = _z_keyexpr_duplicate(ke_out); zn->_subscription_cache.infos = _z_subscription_infos_svec_alias(infos); + zn->_subscription_cache.sub_nb = _z_subscription_infos_svec_len(infos); } void _z_subscription_cache_clear(_z_subscription_cache_t *cache) { @@ -61,11 +63,12 @@ void _z_subscription_cache_clear(_z_subscription_cache_t *cache) { #else static inline bool _z_subscription_get_from_cache(_z_session_t *zn, const _z_keyexpr_t *ke, _z_keyexpr_t *ke_val, - _z_subscription_infos_svec_t *infos_val) { + _z_subscription_infos_svec_t *infos_val, size_t *sub_nb) { _ZP_UNUSED(zn); _ZP_UNUSED(ke); _ZP_UNUSED(ke_val); _ZP_UNUSED(infos_val); + _ZP_UNUSED(sub_nb); return false; } @@ -137,7 +140,7 @@ static z_result_t __unsafe_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t if (_z_keyexpr_suffix_intersects(&_Z_RC_IN_VAL(sub)->_key, key)) { _z_subscription_infos_t new_sub_info = {.arg = _Z_RC_IN_VAL(sub)->_arg, .callback = _Z_RC_IN_VAL(sub)->_callback}; - _Z_RETURN_IF_ERR(_z_subscription_infos_svec_append(sub_infos, &new_sub_info)); + _Z_RETURN_IF_ERR(_z_subscription_infos_svec_append(sub_infos, &new_sub_info, false)); } xs = _z_subscription_rc_list_tail(xs); } @@ -176,7 +179,7 @@ _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_loca return ret; } -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, _z_bytes_t *attachment, z_reliability_t reliability) { z_result_t ret = _z_trigger_subscriptions(zn, keyexpr, payload, encoding, Z_SAMPLE_KIND_PUT, timestamp, qos, @@ -184,54 +187,76 @@ void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexp (void)ret; } -z_result_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, - _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, - const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability) { - _z_sample_t sample; - _z_keyexpr_t key; - _z_subscription_infos_svec_t subs; +static z_result_t _z_subscription_get_infos(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_keyexpr_t *key, + _z_subscription_infos_svec_t *subs, size_t *sub_nb) { // Check cache - if (!_z_subscription_get_from_cache(zn, keyexpr, &key, &subs)) { + if (!_z_subscription_get_from_cache(zn, keyexpr, key, subs, sub_nb)) { _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr->_id, (int)_z_string_len(&keyexpr->_suffix), _z_string_data(&keyexpr->_suffix), _z_keyexpr_mapping_id(keyexpr)); _z_session_mutex_lock(zn); - key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, true); + *key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, true); - if (!_z_keyexpr_has_suffix(&key)) { + if (!_z_keyexpr_has_suffix(key)) { _z_session_mutex_unlock(zn); return _Z_ERR_KEYEXPR_UNKNOWN; } // Get subscription list - z_result_t ret = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, &key, &subs); + z_result_t ret = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, key, subs); _z_session_mutex_unlock(zn); if (ret != _Z_RES_OK) { return ret; } + *sub_nb = _z_subscription_infos_svec_len(subs); // Update cache - _z_subscription_update_cache(zn, keyexpr, &key, &subs); + _z_subscription_update_cache(zn, keyexpr, key, subs); } - // Check if there is subs - size_t sub_nb = _z_subscription_infos_svec_len(&subs); + return _Z_RES_OK; +} + +static z_result_t _z_trigger_subscriptions_inner(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, + _z_encoding_t *encoding, const _z_zint_t kind, + const _z_timestamp_t *timestamp, const _z_n_qos_t qos, + _z_bytes_t *attachment, z_reliability_t reliability) { + _z_keyexpr_t key; + _z_subscription_infos_svec_t subs; + size_t sub_nb; + // Retrieve sub infos + _Z_RETURN_IF_ERR(_z_subscription_get_infos(zn, keyexpr, &key, &subs, &sub_nb)); + // Check if there are subs _Z_DEBUG("Triggering %ju subs for key %d - %.*s", (uintmax_t)sub_nb, key._id, (int)_z_string_len(&key._suffix), _z_string_data(&key._suffix)); if (sub_nb == 0) { + _z_keyexpr_clear(&key); return _Z_RES_OK; } - // Build the sample - _z_sample_create(&sample, &key, payload, timestamp, encoding, kind, qos, attachment, reliability); + // Create sample + _z_sample_t sample = _z_sample_alias(&key, payload, timestamp, encoding, kind, qos, attachment, reliability); // Parse subscription infos svec for (size_t i = 0; i < sub_nb; i++) { _z_subscription_infos_t *sub_info = _z_subscription_infos_svec_get(&subs, i); sub_info->callback(&sample, sub_info->arg); } // Clean up - _z_sample_clear(&sample); + _z_keyexpr_clear(&key); #if Z_FEATURE_RX_CACHE != 1 _z_subscription_infos_svec_release(&subs); // Otherwise it's released with cache #endif return _Z_RES_OK; } +z_result_t _z_trigger_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, + _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, + const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability) { + z_result_t ret = + _z_trigger_subscriptions_inner(zn, keyexpr, payload, encoding, kind, timestamp, qos, attachment, reliability); + // Clean up + _z_keyexpr_clear(keyexpr); + _z_encoding_clear(encoding); + _z_bytes_aliased_drop(payload); + _z_bytes_drop(attachment); + return ret; +} + void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub) { _z_session_mutex_lock(zn); @@ -256,7 +281,7 @@ void _z_flush_subscriptions(_z_session_t *zn) { } #else // Z_FEATURE_SUBSCRIPTION == 0 -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, +void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, _z_bytes_t *attachment, z_reliability_t reliability) { _ZP_UNUSED(zn); diff --git a/src/session/utils.c b/src/session/utils.c index dde52129c..84ad8793e 100644 --- a/src/session/utils.c +++ b/src/session/utils.c @@ -26,6 +26,8 @@ #include "zenoh-pico/utils/logging.h" /*------------------ clone helpers ------------------*/ +void _z_timestamp_copy(_z_timestamp_t *dst, const _z_timestamp_t *src) { *dst = *src; } + _z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp) { return *tstamp; } void _z_timestamp_move(_z_timestamp_t *dst, _z_timestamp_t *src) { @@ -66,6 +68,9 @@ z_result_t _z_session_init(_z_session_rc_t *zsrc, _z_id_t *zid) { #endif #if Z_FEATURE_QUERYABLE == 1 zn->_local_queryable = NULL; +#if Z_FEATURE_RX_CACHE == 1 + memset(&zn->_queryable_cache, 0, sizeof(zn->_queryable_cache)); +#endif #endif #if Z_FEATURE_QUERY == 1 zn->_pending_queries = NULL; @@ -120,6 +125,9 @@ void _z_session_clear(_z_session_t *zn) { #endif #if Z_FEATURE_QUERYABLE == 1 _z_flush_session_queryable(zn); +#if Z_FEATURE_RX_CACHE == 1 + _z_queryable_cache_clear(&zn->_queryable_cache); +#endif #endif #if Z_FEATURE_QUERY == 1 _z_flush_pending_queries(zn); diff --git a/src/transport/common/rx.c b/src/transport/common/rx.c index 5c5c68073..49a39b6cb 100644 --- a/src/transport/common/rx.c +++ b/src/transport/common/rx.c @@ -72,10 +72,14 @@ z_result_t _z_link_recv_t_msg(_z_transport_message_t *t_msg, const _z_link_t *zl } if (ret == _Z_RES_OK) { _z_transport_message_t l_t_msg; - ret = _z_transport_message_decode(&l_t_msg, &zbf); + _z_arc_slice_svec_t arc_pool = _z_arc_slice_svec_make(1); + _z_network_message_svec_t msg_pool = _z_network_message_svec_make(1); + ret = _z_transport_message_decode(&l_t_msg, &zbf, &arc_pool, &msg_pool); if (ret == _Z_RES_OK) { _z_t_msg_copy(t_msg, &l_t_msg); } + _z_arc_slice_svec_clear(&arc_pool); + _z_network_message_svec_clear(&msg_pool); } _z_zbuf_clear(&zbf); diff --git a/src/transport/multicast/read.c b/src/transport/multicast/read.c index ad7a1eb1c..bea0b82f3 100644 --- a/src/transport/multicast/read.c +++ b/src/transport/multicast/read.c @@ -107,7 +107,8 @@ void *_zp_multicast_read_task(void *ztm_arg) { while (_z_zbuf_len(&zbuf) > 0) { // Decode one session message _z_transport_message_t t_msg; - z_result_t ret = _z_transport_message_decode(&t_msg, &zbuf); + z_result_t ret = + _z_transport_message_decode(&t_msg, &zbuf, &ztm->_common._arc_pool, &ztm->_common._msg_pool); if (ret == _Z_RES_OK) { ret = _z_multicast_handle_transport_message(ztm, &t_msg, &addr); diff --git a/src/transport/multicast/rx.c b/src/transport/multicast/rx.c index c1f438c38..1ab13f161 100644 --- a/src/transport/multicast/rx.c +++ b/src/transport/multicast/rx.c @@ -77,7 +77,7 @@ static z_result_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_t if (ret == _Z_RES_OK) { _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_common._zbuf)); - ret = _z_transport_message_decode(t_msg, &ztm->_common._zbuf); + ret = _z_transport_message_decode(t_msg, &ztm->_common._zbuf, &ztm->_common._arc_pool, &ztm->_common._msg_pool); } _z_transport_rx_mutex_unlock(&ztm->_common); return ret; @@ -240,7 +240,9 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, } // Decode message _z_zenoh_message_t zm = {0}; - ret = _z_network_message_decode(&zm, &zbf); + assert(ztm->_common._arc_pool._capacity >= 1); + _z_arc_slice_t *arcs = _z_arc_slice_svec_get_mut(&ztm->_common._arc_pool, 0); + ret = _z_network_message_decode(&zm, &zbf, arcs); zm._reliability = tmsg_reliability; if (ret == _Z_RES_OK) { uint16_t mapping = entry->_peer_id; diff --git a/src/transport/multicast/transport.c b/src/transport/multicast/transport.c index 776d007fb..3f5f1c1bf 100644 --- a/src/transport/multicast/transport.c +++ b/src/transport/multicast/transport.c @@ -81,8 +81,13 @@ z_result_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, ztm->_common._wbuf = _z_wbuf_make(mtu, false); ztm->_common._zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); + // Initialize resource pool + ztm->_common._arc_pool = _z_arc_slice_svec_make(_Z_RES_POOL_INIT_SIZE); + ztm->_common._msg_pool = _z_network_message_svec_make(_Z_RES_POOL_INIT_SIZE); + // Clean up the buffers if one of them failed to be allocated - if ((_z_wbuf_capacity(&ztm->_common._wbuf) != mtu) || + if ((ztm->_common._msg_pool._capacity == 0) || (ztm->_common._arc_pool._capacity == 0) || + (_z_wbuf_capacity(&ztm->_common._wbuf) != mtu) || (_z_zbuf_capacity(&ztm->_common._zbuf) != Z_BATCH_MULTICAST_SIZE)) { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; _Z_ERROR("Not enough memory to allocate transport tx rx buffers!"); @@ -209,6 +214,8 @@ void _z_multicast_transport_clear(_z_transport_t *zt) { // Clean up the buffers _z_wbuf_clear(&ztm->_common._wbuf); _z_zbuf_clear(&ztm->_common._zbuf); + _z_arc_slice_svec_release(&ztm->_common._arc_pool); + _z_network_message_svec_release(&ztm->_common._msg_pool); // Clean up peer list _z_transport_peer_entry_list_free(&ztm->_peers); diff --git a/src/transport/raweth/rx.c b/src/transport/raweth/rx.c index 389b57c70..fdec282f8 100644 --- a/src/transport/raweth/rx.c +++ b/src/transport/raweth/rx.c @@ -100,7 +100,7 @@ z_result_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_m // Decode message if (ret == _Z_RES_OK) { _Z_DEBUG(">> \t transport_message_decode: %ju", (uintmax_t)_z_zbuf_len(&ztm->_common._zbuf)); - ret = _z_transport_message_decode(t_msg, &ztm->_common._zbuf); + ret = _z_transport_message_decode(t_msg, &ztm->_common._zbuf, &ztm->_common._arc_pool, &ztm->_common._msg_pool); } _z_transport_rx_mutex_unlock(&ztm->_common); return ret; diff --git a/src/transport/unicast/read.c b/src/transport/unicast/read.c index ab347251d..5851f3146 100644 --- a/src/transport/unicast/read.c +++ b/src/transport/unicast/read.c @@ -102,7 +102,8 @@ void *_zp_unicast_read_task(void *ztu_arg) { while (_z_zbuf_len(&zbuf) > 0) { // Decode one session message _z_transport_message_t t_msg; - z_result_t ret = _z_transport_message_decode(&t_msg, &zbuf); + z_result_t ret = + _z_transport_message_decode(&t_msg, &zbuf, &ztu->_common._arc_pool, &ztu->_common._msg_pool); if (ret == _Z_RES_OK) { ret = _z_unicast_handle_transport_message(ztu, &t_msg); diff --git a/src/transport/unicast/rx.c b/src/transport/unicast/rx.c index 1d30e988f..628f2815d 100644 --- a/src/transport/unicast/rx.c +++ b/src/transport/unicast/rx.c @@ -75,7 +75,7 @@ z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_me if (ret == _Z_RES_OK) { _Z_DEBUG(">> \t transport_message_decode"); - ret = _z_transport_message_decode(t_msg, &ztu->_common._zbuf); + ret = _z_transport_message_decode(t_msg, &ztu->_common._zbuf, &ztu->_common._arc_pool, &ztu->_common._msg_pool); // Mark the session that we have received data if (ret == _Z_RES_OK) { @@ -194,7 +194,9 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t } // Decode message _z_zenoh_message_t zm = {0}; - ret = _z_network_message_decode(&zm, &zbf); + assert(ztu->_common._arc_pool._capacity >= 1); + _z_arc_slice_t *arcs = _z_arc_slice_svec_get_mut(&ztu->_common._arc_pool, 0); + ret = _z_network_message_decode(&zm, &zbf, arcs); zm._reliability = tmsg_reliability; if (ret == _Z_RES_OK) { _z_handle_network_message(ztu->_common._session, &zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); diff --git a/src/transport/unicast/transport.c b/src/transport/unicast/transport.c index fe48e3f24..6f90b4397 100644 --- a/src/transport/unicast/transport.c +++ b/src/transport/unicast/transport.c @@ -64,8 +64,13 @@ z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, ztu->_common._wbuf = _z_wbuf_make(wbuf_size, false); ztu->_common._zbuf = _z_zbuf_make(zbuf_size); + // Initialize resources pool + ztu->_common._arc_pool = _z_arc_slice_svec_make(_Z_RES_POOL_INIT_SIZE); + ztu->_common._msg_pool = _z_network_message_svec_make(_Z_RES_POOL_INIT_SIZE); + // Clean up the buffers if one of them failed to be allocated - if ((_z_wbuf_capacity(&ztu->_common._wbuf) != wbuf_size) || + if ((ztu->_common._msg_pool._capacity == 0) || (ztu->_common._arc_pool._capacity == 0) || + (_z_wbuf_capacity(&ztu->_common._wbuf) != wbuf_size) || (_z_zbuf_capacity(&ztu->_common._zbuf) != zbuf_size)) { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; _Z_ERROR("Not enough memory to allocate transport tx rx buffers!"); @@ -227,7 +232,7 @@ static z_result_t _z_unicast_handshake_listener(_z_transport_unicast_establish_p } _Z_DEBUG("Received Z_INIT(Syn)"); // Encode InitAck - _z_slice_t cookie = _z_slice_empty(); + _z_slice_t cookie = _z_slice_null(); _z_transport_message_t iam = _z_t_msg_make_init_ack(whatami, *local_zid, cookie); // Any of the size parameters in the InitAck must be less or equal than the one in the InitSyn, if (iam._body._init._seq_num_res > tmsg._body._init._seq_num_res) { @@ -339,6 +344,8 @@ void _z_unicast_transport_clear(_z_transport_t *zt) { // Clean up the buffers _z_wbuf_clear(&ztu->_common._wbuf); _z_zbuf_clear(&ztu->_common._zbuf); + _z_arc_slice_svec_release(&ztu->_common._arc_pool); + _z_network_message_svec_release(&ztu->_common._msg_pool); #if Z_FEATURE_FRAGMENTATION == 1 _z_wbuf_clear(&ztu->_dbuf_reliable); _z_wbuf_clear(&ztu->_dbuf_best_effort); diff --git a/tests/modularity.py b/tests/modularity.py index 7350ae70a..be18d86c1 100644 --- a/tests/modularity.py +++ b/tests/modularity.py @@ -47,8 +47,8 @@ def pub_and_sub(args): # Expected z_sub output & status if args.sub == 1: - z_sub_expected_status = -2 if args.pub == 1: + z_sub_expected_status = [0, -2] z_sub_expected_output = """Opening session... Declaring Subscriber on 'demo/example/**'... Press CTRL-C to quit... @@ -63,16 +63,17 @@ def pub_and_sub(args): >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 8] Pub from Pico!') >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 9] Pub from Pico!')""" else: + z_sub_expected_status = [-2] z_sub_expected_output = """Opening session... Declaring Subscriber on 'demo/example/**'... Press CTRL-C to quit...""" else: - z_sub_expected_status = 254 + z_sub_expected_status = [254] z_sub_expected_output = "ERROR: Zenoh pico was compiled without " "Z_FEATURE_SUBSCRIPTION but this example requires it." print("Start subscriber") # Start z_sub in the background - z_sub_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_sub" + z_sub_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_sub -n 10" z_sub_process = subprocess.Popen( z_sub_command, shell=True, @@ -132,7 +133,7 @@ def pub_and_sub(args): print("Check subscriber status & output") # Check the exit status of z_sub z_sub_status = z_sub_process.returncode - if z_sub_status == z_sub_expected_status: + if z_sub_status in z_sub_expected_status: print("z_sub status valid") else: print(f"z_sub status invalid, expected: {z_sub_expected_status}, received: {z_sub_status}") @@ -175,24 +176,25 @@ def query_and_queryable(args): # Expected z_queryable output & status if args.queryable == 1: - z_queryable_expected_status = -2 if args.query == 1: + z_queryable_expected_status = [0, -2] z_queryable_expected_output = """Opening session... Creating Queryable on 'demo/example/zenoh-pico-queryable'... Press CTRL-C to quit... >> [Queryable handler] Received Query 'demo/example/**' """ else: + z_queryable_expected_status = [-2] z_queryable_expected_output = """Opening session... Creating Queryable on 'demo/example/zenoh-pico-queryable'... Press CTRL-C to quit...""" else: - z_queryable_expected_status = 254 + z_queryable_expected_status = [254] z_queryable_expected_output = "ERROR: Zenoh pico was compiled without " "Z_FEATURE_QUERYABLE but this example requires it." print("Start queryable") # Start z_queryable in the background - z_queryable_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_queryable" + z_queryable_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_queryable -n 1" z_queryable_process = subprocess.Popen( z_queryable_command, shell=True, @@ -252,7 +254,7 @@ def query_and_queryable(args): print("Check queryable status & output") # Check the exit status of z_queryable z_queryable_status = z_queryable_process.returncode - if z_queryable_status == z_queryable_expected_status: + if z_queryable_status in z_queryable_expected_status: print("z_queryable status valid") else: print(f"z_queryable status invalid, expected: {z_queryable_expected_status}," f" received: {z_queryable_status}") diff --git a/tests/z_msgcodec_test.c b/tests/z_msgcodec_test.c index f3a92a77a..1b0b134c5 100644 --- a/tests/z_msgcodec_test.c +++ b/tests/z_msgcodec_test.c @@ -172,7 +172,7 @@ _z_wbuf_t gen_wbuf(size_t len) { _z_slice_t gen_slice(size_t len) { if (len == 0) { - return _z_slice_empty(); + return _z_slice_null(); } uint8_t *p = (uint8_t *)z_malloc(sizeof(uint8_t) * len); @@ -225,7 +225,7 @@ _z_string_svec_t gen_str_array(size_t size) { _z_string_svec_t sa = _z_string_svec_make(size); for (size_t i = 0; i < size; i++) { _z_string_t s = _z_string_copy_from_str(gen_str(16)); - _z_string_svec_append(&sa, &s); + _z_string_svec_append(&sa, &s, true); } return sa; @@ -555,7 +555,8 @@ void payload_field(void) { _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); _z_bytes_t d_pld = _z_bytes_null(); - res = _z_bytes_decode(&d_pld, &zbf); + _z_arc_slice_t arcs = {0}; + res = _z_bytes_decode(&d_pld, &zbf, &arcs); assert(res == _Z_RES_OK); printf(" "); assert_eq_bytes(&e_pld, &d_pld); @@ -563,7 +564,7 @@ void payload_field(void) { // Free _z_bytes_drop(&e_pld); - _z_bytes_drop(&d_pld); + _z_bytes_aliased_drop(&d_pld); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } @@ -1068,7 +1069,8 @@ void declare_message(void) { // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); _z_network_message_t d_dcl = {0}; - res = _z_network_message_decode(&d_dcl, &zbf); + _z_arc_slice_t arcs = {0}; + res = _z_network_message_decode(&d_dcl, &zbf, &arcs); assert(res == _Z_RES_OK); assert_eq_declare_message(&n_msg._body._declare, &d_dcl._body._declare); @@ -1202,8 +1204,9 @@ void push_body_message(void) { // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); _z_push_body_t d_da = {0}; + _z_arc_slice_t arcs = {0}; uint8_t header = _z_zbuf_read(&zbf); - res = _z_push_body_decode(&d_da, &zbf, header); + res = _z_push_body_decode(&d_da, &zbf, header, &arcs); assert(res == _Z_RES_OK); assert_eq_push_body(&e_da, &d_da); @@ -1269,9 +1272,10 @@ void err_message(void) { _z_msg_err_t expected = gen_err(); assert(_z_err_encode(&wbf, &expected) == _Z_RES_OK); _z_msg_err_t decoded = {0}; + _z_arc_slice_t arcs = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); - assert(_Z_RES_OK == _z_err_decode(&decoded, &zbf, header)); + assert(_Z_RES_OK == _z_err_decode(&decoded, &zbf, header, &arcs)); assert_eq_err(&expected, &decoded); _z_msg_err_clear(&decoded); _z_msg_err_clear(&expected); @@ -1297,9 +1301,10 @@ void reply_message(void) { _z_msg_reply_t expected = gen_reply(); assert(_z_reply_encode(&wbf, &expected) == _Z_RES_OK); _z_msg_reply_t decoded = {0}; + _z_arc_slice_t arcs = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); - assert(_Z_RES_OK == _z_reply_decode(&decoded, &zbf, header)); + assert(_Z_RES_OK == _z_reply_decode(&decoded, &zbf, header, &arcs)); assert_eq_reply(&expected, &decoded); _z_msg_reply_clear(&decoded); _z_msg_reply_clear(&expected); @@ -1329,9 +1334,10 @@ void push_message(void) { _z_n_msg_push_t expected = gen_push(); assert(_z_push_encode(&wbf, &expected) == _Z_RES_OK); _z_n_msg_push_t decoded = {0}; + _z_arc_slice_t arcs = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); - assert(_Z_RES_OK == _z_push_decode(&decoded, &zbf, header)); + assert(_Z_RES_OK == _z_push_decode(&decoded, &zbf, header, &arcs)); assert_eq_push(&expected, &decoded); _z_n_msg_push_clear(&decoded); _z_n_msg_push_clear(&expected); @@ -1399,9 +1405,10 @@ void request_message(void) { _z_n_msg_request_t expected = gen_request(); assert(_z_request_encode(&wbf, &expected) == _Z_RES_OK); _z_n_msg_request_t decoded = {0}; + _z_arc_slice_t arcs = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); - z_result_t ret = _z_request_decode(&decoded, &zbf, header); + z_result_t ret = _z_request_decode(&decoded, &zbf, header, &arcs); assert(_Z_RES_OK == ret); assert_eq_request(&expected, &decoded); _z_n_msg_request_clear(&decoded); @@ -1457,9 +1464,10 @@ void response_message(void) { _z_n_msg_response_t expected = gen_response(); assert(_z_response_encode(&wbf, &expected) == _Z_RES_OK); _z_n_msg_response_t decoded = {0}; + _z_arc_slice_t arcs = {0}; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); uint8_t header = _z_zbuf_read(&zbf); - z_result_t ret = _z_response_decode(&decoded, &zbf, header); + z_result_t ret = _z_response_decode(&decoded, &zbf, header, &arcs); assert(_Z_RES_OK == ret); assert_eq_response(&expected, &decoded); _z_n_msg_response_clear(&decoded); @@ -1715,8 +1723,10 @@ void frame_message(void) { _z_transport_message_t expected = gen_frame(); assert(_z_frame_encode(&wbf, expected._header, &expected._body._frame) == _Z_RES_OK); _z_t_msg_frame_t decoded = {0}; + _z_arc_slice_svec_t arcs = _z_arc_slice_svec_make(1); + _z_network_message_svec_t msg = _z_network_message_svec_make(1); _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - z_result_t ret = _z_frame_decode(&decoded, &zbf, expected._header); + z_result_t ret = _z_frame_decode(&decoded, &zbf, expected._header, &arcs, &msg); assert(_Z_RES_OK == ret); assert_eq_frame(&expected._body._frame, &decoded); _z_t_msg_frame_clear(&decoded); @@ -1808,8 +1818,10 @@ void transport_message(void) { _z_transport_message_t expected = gen_transport(); assert(_z_transport_message_encode(&wbf, &expected) == _Z_RES_OK); _z_transport_message_t decoded = {0}; + _z_arc_slice_svec_t arcs = _z_arc_slice_svec_make(1); + _z_network_message_svec_t msg = _z_network_message_svec_make(1); _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - z_result_t ret = _z_transport_message_decode(&decoded, &zbf); + z_result_t ret = _z_transport_message_decode(&decoded, &zbf, &arcs, &msg); assert(_Z_RES_OK == ret); assert_eq_transport(&expected, &decoded); _z_t_msg_clear(&decoded); From 1929633f8f585b67c027af774e62da83a1d274e9 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Thu, 14 Nov 2024 15:05:12 +0100 Subject: [PATCH 12/17] Rebase 1.1 on main (#784) * Update closure handlers documentaion (#736) * Rename closure callback/dropper types (#739) * Remove legacy z_zint_t from public API (#741) * Add `export "C"` for all header files (#740) * Add `export "C"` for proper closures callbacks export * Add `export "C"` for all headers * add serialize from substr functions (#742) * Rename z_loaned_hello_handler_t to z_closure_hello_callback_t (#743) * Mark z_reply_replier_id as unstable (#745) * Add documentation about logging (#744) * Update README.md (#746) * hardcode clang-format runner to Ubuntu24.04 (#748) * fix build granularity (#747) * fix: badly named constant (#750) * fix packages * fix: update debian packaging - include libzenohpico.so in debian package - change the package name to libzenohpico in line with libzenohc - set correct debian version for pre releases - fix wrong version used in Release mode * fix: debian dev package name * fix: package version for releases (#753) * fix: debian_version for official releases otherwise they would be undefined * fix: align cpack version with zenoh-c * chore: review comments move cpack version closer to where it's used * build shared lib for packages instead of static one (#757) * Fix z_task cleanup for platforms with pthread support (#759) * Fix read/lease task cleanup (#760) * Align ID string representation with zenoh (lowercase) (#761) * Remove default parameters from z_closure (#755) * build both libraries:shared and static when packaging; (#766) add static library to dev package; * Publish debian packages (#769) * fix: add workflow to release debian packages * fix: align with zenoh-c - update package names - set version string in the same way - set DEBARCH/RPMARCH - set CPACK_PACKAGE_FILE_NAME - add -j to zip archive to not include parent folder * fix: use CPACK_PACKAGE_NAME * fix: pass package name to all build targets * fix: Don't tag release branch during dry-run * Replace exit with return in zephyr examples (#774) * Add platform_common.c to zephyr CMakeLists.txt file * Rework Zenoh ID conversion * chore: Update org secrets (#782) As per eclipse-zenoh/.eclipsefdn#18, secrets were updated to follow eclipse foundation naming convention. * fix: rebase shenanigans * feat: set batching api as unstable --------- Co-authored-by: Alexander Bushnev Co-authored-by: DenisBiryukov91 <155981813+DenisBiryukov91@users.noreply.github.com> Co-authored-by: Denis Biryukov Co-authored-by: Diogo Mendes Matsubara Co-authored-by: Luca Cominardi --- .github/workflows/build-check.yaml | 6 +- .github/workflows/release.yml | 18 +- CMakeLists.txt | 245 +++++++++++------- GNUmakefile | 20 +- PackageConfig.cmake.in | 13 +- README.md | 11 +- ci/scripts/build-linux.bash | 12 +- ci/scripts/bump-and-tag.bash | 5 +- docs/api.rst | 101 +++++++- examples/CMakeLists.txt | 2 +- examples/espidf/z_get.c | 2 +- examples/espidf/z_queryable.c | 2 +- examples/espidf/z_sub.c | 2 +- examples/freertos_plus_tcp/CMakeLists.txt | 6 +- examples/freertos_plus_tcp/z_get.c | 2 +- examples/freertos_plus_tcp/z_queryable.c | 2 +- examples/freertos_plus_tcp/z_sub.c | 2 +- examples/freertos_plus_tcp/z_sub_st.c | 2 +- examples/unix/c11/z_get.c | 2 +- examples/unix/c11/z_get_attachment.c | 2 +- examples/unix/c11/z_info.c | 4 +- examples/unix/c11/z_queryable.c | 2 +- examples/unix/c11/z_queryable_attachment.c | 2 +- examples/unix/c11/z_sub.c | 2 +- examples/unix/c11/z_sub_attachment.c | 2 +- examples/unix/c11/z_sub_st.c | 2 +- examples/windows/z_get.c | 2 +- examples/windows/z_info.c | 4 +- examples/windows/z_queryable.c | 2 +- examples/windows/z_sub.c | 2 +- examples/windows/z_sub_st.c | 2 +- examples/zephyr/z_get.c | 6 +- examples/zephyr/z_pub.c | 4 +- examples/zephyr/z_pull.c | 6 +- examples/zephyr/z_queryable.c | 6 +- examples/zephyr/z_sub.c | 6 +- include/zenoh-pico/api/encoding.h | 100 +++---- include/zenoh-pico/api/handlers.h | 47 ++-- include/zenoh-pico/api/macros.h | 20 +- include/zenoh-pico/api/primitives.h | 28 +- include/zenoh-pico/api/serialization.h | 36 ++- include/zenoh-pico/api/types.h | 39 ++- include/zenoh-pico/collections/arc_slice.h | 8 + include/zenoh-pico/collections/array.h | 8 + include/zenoh-pico/collections/bytes.h | 8 + include/zenoh-pico/collections/element.h | 8 + include/zenoh-pico/collections/fifo.h | 8 + include/zenoh-pico/collections/intmap.h | 8 + include/zenoh-pico/collections/lifo.h | 8 + include/zenoh-pico/collections/list.h | 8 + include/zenoh-pico/collections/ring.h | 8 + include/zenoh-pico/collections/slice.h | 8 + include/zenoh-pico/collections/string.h | 12 +- include/zenoh-pico/collections/vec.h | 8 + include/zenoh-pico/config.h | 4 +- include/zenoh-pico/link/config/bt.h | 8 + include/zenoh-pico/link/config/raweth.h | 8 + include/zenoh-pico/link/config/serial.h | 8 + include/zenoh-pico/link/config/tcp.h | 8 + include/zenoh-pico/link/config/udp.h | 8 + include/zenoh-pico/link/config/ws.h | 8 + include/zenoh-pico/link/endpoint.h | 8 + include/zenoh-pico/link/link.h | 8 + include/zenoh-pico/link/manager.h | 8 + include/zenoh-pico/net/config.h | 8 + include/zenoh-pico/net/encoding.h | 8 + include/zenoh-pico/net/filtering.h | 8 + include/zenoh-pico/net/logger.h | 8 + include/zenoh-pico/net/primitives.h | 23 +- include/zenoh-pico/net/publish.h | 8 + include/zenoh-pico/net/query.h | 8 + include/zenoh-pico/net/reply.h | 8 + include/zenoh-pico/net/sample.h | 7 + include/zenoh-pico/net/session.h | 8 + include/zenoh-pico/net/subscribe.h | 8 + include/zenoh-pico/protocol/codec/core.h | 8 + .../zenoh-pico/protocol/codec/declarations.h | 9 + include/zenoh-pico/protocol/codec/ext.h | 8 + include/zenoh-pico/protocol/codec/interest.h | 8 + include/zenoh-pico/protocol/codec/message.h | 8 + include/zenoh-pico/protocol/codec/network.h | 9 + include/zenoh-pico/protocol/codec/transport.h | 8 + include/zenoh-pico/protocol/core.h | 8 + .../protocol/definitions/declarations.h | 8 + .../protocol/definitions/interest.h | 8 + .../zenoh-pico/protocol/definitions/message.h | 9 + .../zenoh-pico/protocol/definitions/network.h | 9 + .../protocol/definitions/transport.h | 8 + include/zenoh-pico/protocol/ext.h | 8 + include/zenoh-pico/protocol/iobuf.h | 8 + include/zenoh-pico/protocol/keyexpr.h | 8 + include/zenoh-pico/session/interest.h | 8 + include/zenoh-pico/session/push.h | 8 + include/zenoh-pico/session/query.h | 8 + include/zenoh-pico/session/queryable.h | 2 +- include/zenoh-pico/session/reply.h | 8 + include/zenoh-pico/session/resource.h | 8 + include/zenoh-pico/session/session.h | 24 +- include/zenoh-pico/session/subscription.h | 10 +- include/zenoh-pico/session/utils.h | 8 + include/zenoh-pico/system/link/raweth.h | 8 + include/zenoh-pico/system/link/serial.h | 8 + include/zenoh-pico/system/link/tcp.h | 8 + include/zenoh-pico/system/link/udp.h | 8 + include/zenoh-pico/system/link/ws.h | 8 + .../system/platform/arduino/esp32.h | 8 + .../system/platform/arduino/opencr.h | 8 + .../zenoh-pico/system/platform/emscripten.h | 8 + include/zenoh-pico/system/platform/espidf.h | 8 + include/zenoh-pico/system/platform/flipper.h | 8 + .../system/platform/freertos_plus_tcp.h | 10 +- include/zenoh-pico/system/platform/mbed.h | 8 + include/zenoh-pico/system/platform/unix.h | 13 +- include/zenoh-pico/system/platform/void.h | 8 + include/zenoh-pico/system/platform/windows.h | 8 + include/zenoh-pico/system/platform/zephyr.h | 8 + include/zenoh-pico/transport/common/lease.h | 8 + include/zenoh-pico/transport/common/read.h | 8 + include/zenoh-pico/transport/common/rx.h | 8 + include/zenoh-pico/transport/common/tx.h | 8 + include/zenoh-pico/transport/manager.h | 8 + include/zenoh-pico/transport/multicast.h | 8 + .../zenoh-pico/transport/multicast/lease.h | 8 + include/zenoh-pico/transport/multicast/read.h | 8 + include/zenoh-pico/transport/multicast/rx.h | 8 + .../transport/multicast/transport.h | 10 +- include/zenoh-pico/transport/raweth/read.h | 8 + include/zenoh-pico/transport/raweth/rx.h | 8 + include/zenoh-pico/transport/raweth/tx.h | 8 + include/zenoh-pico/transport/transport.h | 10 +- include/zenoh-pico/transport/unicast.h | 8 + include/zenoh-pico/transport/unicast/lease.h | 8 + include/zenoh-pico/transport/unicast/read.h | 8 + include/zenoh-pico/transport/unicast/rx.h | 8 + .../zenoh-pico/transport/unicast/transport.h | 8 + include/zenoh-pico/transport/utils.h | 8 + include/zenoh-pico/utils/checksum.h | 8 + include/zenoh-pico/utils/config.h | 9 + include/zenoh-pico/utils/encoding.h | 8 + include/zenoh-pico/utils/logging.h | 8 + include/zenoh-pico/utils/pointers.h | 8 + include/zenoh-pico/utils/result.h | 8 + include/zenoh-pico/utils/string.h | 13 + include/zenoh-pico/utils/uuid.h | 27 ++ src/api/api.c | 22 +- src/api/encoding.c | 2 + src/api/serialization.c | 13 +- src/collections/string.c | 13 +- src/net/primitives.c | 10 +- src/net/session.c | 7 +- src/protocol/config.c | 13 + src/system/emscripten/system.c | 6 +- src/system/unix/system.c | 6 +- src/system/zephyr/system.c | 6 +- src/transport/multicast.c | 6 +- src/transport/multicast/transport.c | 4 +- src/transport/unicast.c | 9 +- src/transport/unicast/transport.c | 4 +- src/utils/uuid.c | 6 + tests/z_api_alignment_test.c | 17 +- tests/z_client_test.c | 18 +- tests/z_data_struct_test.c | 13 + tests/z_peer_multicast_test.c | 17 +- tests/z_test_fragment_rx.c | 2 +- zenohpico.pc | 2 +- zephyr/CMakeLists.txt | 1 + 166 files changed, 1470 insertions(+), 390 deletions(-) diff --git a/.github/workflows/build-check.yaml b/.github/workflows/build-check.yaml index 144431572..be3e52d7e 100644 --- a/.github/workflows/build-check.yaml +++ b/.github/workflows/build-check.yaml @@ -34,13 +34,15 @@ jobs: check_format: name: Check codebase format with clang-format - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout code uses: actions/checkout@v4 - name: Run clang-format dry-run - run: find include/ src/ tests/ examples/ -iname "*.ino" -o -iname "*.h" -o -iname "*.c" | xargs clang-format -n -Werror + run: | + clang-format --version + find include/ src/ tests/ examples/ -iname "*.ino" -o -iname "*.h" -o -iname "*.c" | xargs clang-format -n -Werror c99_build: name: Check c99 compilation diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 01fb354b2..e72186dbd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,6 +59,7 @@ jobs: - name: Bump and tag project run: bash ci/scripts/bump-and-tag.bash env: + LIVE_RUN: ${{ inputs.live-run || false }} VERSION: ${{ steps.create-release-branch.outputs.version }} GIT_USER_NAME: eclipse-zenoh-bot GIT_USER_EMAIL: eclipse-zenoh-bot@users.noreply.github.com @@ -150,6 +151,19 @@ jobs: name: ${{ steps.build-linux.outputs.archive-deb }} path: ${{ steps.build-linux.outputs.archive-deb }} + debian: + name: Publish Debian packages + needs: [tag, build-linux] + uses: eclipse-zenoh/ci/.github/workflows/release-crates-debian.yml@main + with: + no-build: true + live-run: ${{ inputs.live-run || false }} + version: ${{ needs.tag.outputs.version }} + repo: ${{ github.repository }} + branch: ${{ needs.tag.outputs.branch }} + installation-test: false + secrets: inherit + eclipse: needs: [tag, build-macos, build-linux] runs-on: ubuntu-latest @@ -160,8 +174,8 @@ jobs: version: ${{ needs.tag.outputs.version }} ssh-host: genie.zenoh@projects-storage.eclipse.org ssh-host-path: /home/data/httpd/download.eclipse.org/zenoh/zenoh-pico - ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} - ssh-passphrase: ${{ secrets.SSH_PASSPHRASE }} + ssh-private-key: ${{ secrets.ORG_GPG_PRIVATE_KEY }} + ssh-passphrase: ${{ secrets.ORG_GPG_PASSPHRASE }} archive-patterns: '.*\.zip' github: diff --git a/CMakeLists.txt b/CMakeLists.txt index b34b73c75..8f2df3631 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,17 +39,6 @@ configure_file( @ONLY ) -set(project_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") -if(NOT DEFINED PROJECT_VERSION_TWEAK) - set(project_version "${project_version}") -elseif(PROJECT_VERSION_TWEAK EQUAL 0) - set(project_version "${project_version}-dev") -elseif(PROJECT_VERSION_TWEAK GREATER 1) - set(project_version "${project_version}-pre.${PROJECT_VERSION_TWEAK}") -endif() -status_print(project_version) - - include(CMakePackageConfigHelpers) include(GNUInstallDirs) @@ -69,6 +58,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") endif() elseif(CMAKE_SYSTEM_NAME MATCHES "Generic") if(WITH_ZEPHYR) + set(PACKAGING OFF) # no packaging support for zephyr set(BUILD_SHARED_LIBS "OFF") endif() endif() @@ -115,44 +105,83 @@ else() endif() endif() +if (PACKAGING) + set(PICO_STATIC ON) + set(PICO_SHARED ON) +endif() +if(BUILD_SHARED_LIBS) + set(PICO_SHARED ON) +else() + set(PICO_STATIC ON) +endif() + set(Libname "zenohpico") -add_library(${Libname}) -add_library(zenohpico::lib ALIAS ${Libname}) +if(PICO_STATIC) + add_library(${Libname}_static STATIC) + set_target_properties(${Libname}_static PROPERTIES OUTPUT_NAME ${Libname}) + add_library(zenohpico::static ALIAS ${Libname}_static) +endif() +if(PICO_SHARED) + add_library(${Libname}_shared SHARED) + set_target_properties(${Libname}_shared PROPERTIES OUTPUT_NAME ${Libname}) + add_library(zenohpico::shared ALIAS ${Libname}_shared) +endif() +if(BUILD_SHARED_LIBS) + add_library(zenohpico::lib ALIAS ${Libname}_shared) +else() + add_library(zenohpico::lib ALIAS ${Libname}_static) +endif() -function(add_definition value) +function(pico_add_compile_definition value) add_definitions(-D${value}) - target_compile_definitions(${Libname} PUBLIC ${value}) + if(PICO_STATIC) + target_compile_definitions(zenohpico_static PUBLIC ${value}) + endif() + if(PICO_SHARED) + target_compile_definitions(zenohpico_shared PUBLIC ${value}) + endif() endfunction() -add_definition(ZENOH_C_STANDARD=${CMAKE_C_STANDARD}) +function(pico_target_link_library value) + if(PICO_STATIC) + target_link_libraries(zenohpico_static ${value}) + endif() + if(PICO_SHARED) + target_link_libraries(zenohpico_shared ${value}) + endif() +endfunction() -# while in development, use timestamp for patch version: -string(TIMESTAMP PROJECT_VERSION_PATCH "%Y%m%ddev") -set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") +pico_add_compile_definition(ZENOH_C_STANDARD=${CMAKE_C_STANDARD}) + +if (NOT CMAKE_BUILD_TYPE MATCHES "RELEASE" OR "Release") + # while in development, use timestamp for patch version: + string(TIMESTAMP PROJECT_VERSION_PATCH "%Y%m%ddev") + set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") +endif() set(CHECK_THREADS "ON") # System definition if(CMAKE_SYSTEM_NAME MATCHES "Linux") - add_definition(ZENOH_LINUX) + pico_add_compile_definition(ZENOH_LINUX) elseif(POSIX_COMPATIBLE) - add_definition(ZENOH_LINUX) + pico_add_compile_definition(ZENOH_LINUX) set(CHECK_THREADS "OFF") elseif(CMAKE_SYSTEM_NAME MATCHES "BSD") - add_definition(ZENOH_BSD) + pico_add_compile_definition(ZENOH_BSD) elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_definition(ZENOH_MACOS) + pico_add_compile_definition(ZENOH_MACOS) set(MACOSX_RPATH "ON") elseif(CMAKE_SYSTEM_NAME MATCHES "Emscripten") - add_definition(ZENOH_EMSCRIPTEN) + pico_add_compile_definition(ZENOH_EMSCRIPTEN) elseif(CMAKE_SYSTEM_NAME MATCHES "Windows") - add_definition(ZENOH_WINDOWS) - add_definition(_CRT_SECURE_NO_WARNINGS) + pico_add_compile_definition(ZENOH_WINDOWS) + pico_add_compile_definition(_CRT_SECURE_NO_WARNINGS) elseif(CMAKE_SYSTEM_NAME MATCHES "Generic") if(WITH_ZEPHYR) - add_definition(ZENOH_ZEPHYR) + pico_add_compile_definition(ZENOH_ZEPHYR) elseif(WITH_FREERTOS_PLUS_TCP) - add_definition(ZENOH_FREERTOS_PLUS_TCP) + pico_add_compile_definition(ZENOH_FREERTOS_PLUS_TCP) endif() else() message(FATAL_ERROR "zenoh-pico is not yet available on ${CMAKE_SYSTEM_NAME} platform") @@ -162,18 +191,18 @@ endif() # Compiler definition message("Compilers in use: ${CMAKE_C_COMPILER_ID}, ${CMAKE_CXX_COMPILER_ID}") if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") - add_definition(ZENOH_COMPILER_CLANG) + pico_add_compile_definition(ZENOH_COMPILER_CLANG) elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "GNU") - add_definition(ZENOH_COMPILER_GCC) + pico_add_compile_definition(ZENOH_COMPILER_GCC) elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel" OR CMAKE_C_COMPILER_ID STREQUAL "Intel") - add_definition(ZENOH_COMPILER_INTEL) + pico_add_compile_definition(ZENOH_COMPILER_INTEL) elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR CMAKE_C_COMPILER_ID STREQUAL "MSVC") - add_definition(ZENOH_COMPILER_MSVC) + pico_add_compile_definition(ZENOH_COMPILER_MSVC) else() - add_definition(ZENOH_COMPILER_OTHER) + pico_add_compile_definition(ZENOH_COMPILER_OTHER) endif() -add_definition(ZENOH_DEBUG=${ZENOH_DEBUG}) +pico_add_compile_definition(ZENOH_DEBUG=${ZENOH_DEBUG}) # Zenoh pico feature configuration options @@ -270,10 +299,19 @@ file(GLOB_RECURSE PublicHeaders "include/zenoh-pico/utils/*.h" "include/zenoh-pico/config.h" ) -target_include_directories(${Libname} - PUBLIC - $ - $) +if(PICO_STATIC) + target_include_directories(${Libname}_static + PUBLIC + $ + $) +endif() +if(PICO_SHARED) + target_include_directories(${Libname}_shared + PUBLIC + $ + $) +endif() + file(GLOB_RECURSE Sources "src/api/*.c" @@ -307,18 +345,24 @@ endif() set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) link_directories(${LIBRARY_OUTPUT_PATH}) -target_sources(${Libname} PRIVATE ${Sources}) +if(PICO_STATIC) + target_sources(zenohpico_static PRIVATE ${Sources}) +endif() +if(PICO_SHARED) + target_sources(zenohpico_shared PRIVATE ${Sources}) +endif() if(CHECK_THREADS) - target_link_libraries(${Libname} Threads::Threads) + pico_target_link_library(Threads::Threads) endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux") - target_link_libraries(${Libname} rt) + pico_target_link_library(rt) endif() if(CMAKE_SYSTEM_NAME MATCHES "Windows") - target_link_libraries(${Libname} Ws2_32 Iphlpapi) + pico_target_link_library(Ws2_32) + pico_target_link_library(Iphlpapi) endif() # @@ -338,12 +382,22 @@ message(STATUS "Build tools: ${BUILD_TOOLS}") message(STATUS "Build tests: ${BUILD_TESTING}") message(STATUS "Build integration: ${BUILD_INTEGRATION}") -install(TARGETS ${Libname} +set(PICO_LIBS "") +if(PICO_STATIC) + list(APPEND PICO_LIBS zenohpico_static) +endif() +if(PICO_SHARED) + list(APPEND PICO_LIBS zenohpico_shared) +endif() + +install(TARGETS ${PICO_LIBS} EXPORT zenohpicoTargets LIBRARY DESTINATION lib ARCHIVE DESTINATION lib RUNTIME DESTINATION bin - COMPONENT Library + LIBRARY COMPONENT Runtime + ARCHIVE COMPONENT Dev + RUNTIME COMPONENT Runtime ) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh-pico.h DESTINATION include @@ -377,17 +431,18 @@ install( "${CMAKE_CURRENT_BINARY_DIR}/zenohpicoConfigVersion.cmake" DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" CONFIGURATIONS ${configurations} - COMPONENT dev) + COMPONENT Dev) # Generate Targets.cmake install( EXPORT zenohpicoTargets NAMESPACE zenohpico:: - DESTINATION "${CMAKE_INSTALL_CMAKEDIR}") + DESTINATION "${CMAKE_INSTALL_CMAKEDIR}" + COMPONENT Dev) if(UNIX) configure_file("${CMAKE_SOURCE_DIR}/zenohpico.pc.in" "${CMAKE_SOURCE_DIR}/zenohpico.pc" @ONLY) - install(FILES "${CMAKE_SOURCE_DIR}/zenohpico.pc" CONFIGURATIONS Release RelWithDebInfo DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + install(FILES "${CMAKE_SOURCE_DIR}/zenohpico.pc" CONFIGURATIONS Release RelWithDebInfo DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" COMPONENT Dev) endif() if(BUILD_EXAMPLES) @@ -398,7 +453,7 @@ if(UNIX OR MSVC) if(BUILD_TOOLS) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tools) add_executable(z_keyexpr_canonizer ${PROJECT_SOURCE_DIR}/tools/z_keyexpr_canonizer.c) - target_link_libraries(z_keyexpr_canonizer ${Libname}) + target_link_libraries(z_keyexpr_canonizer zenohpico::lib) endif() if(BUILD_TESTING AND CMAKE_C_STANDARD MATCHES "11") @@ -422,23 +477,23 @@ if(UNIX OR MSVC) add_executable(z_api_encoding_test ${PROJECT_SOURCE_DIR}/tests/z_api_encoding_test.c) add_executable(z_refcount_test ${PROJECT_SOURCE_DIR}/tests/z_refcount_test.c) - target_link_libraries(z_data_struct_test ${Libname}) - target_link_libraries(z_channels_test ${Libname}) - target_link_libraries(z_collections_test ${Libname}) - target_link_libraries(z_endpoint_test ${Libname}) - target_link_libraries(z_iobuf_test ${Libname}) - target_link_libraries(z_msgcodec_test ${Libname}) - target_link_libraries(z_keyexpr_test ${Libname}) - target_link_libraries(z_api_null_drop_test ${Libname}) - target_link_libraries(z_api_double_drop_test ${Libname}) - target_link_libraries(z_test_fragment_tx ${Libname}) - target_link_libraries(z_test_fragment_rx ${Libname}) - target_link_libraries(z_perf_tx ${Libname}) - target_link_libraries(z_perf_rx ${Libname}) - target_link_libraries(z_bytes_test ${Libname}) - target_link_libraries(z_api_bytes_test ${Libname}) - target_link_libraries(z_api_encoding_test ${Libname}) - target_link_libraries(z_refcount_test ${Libname}) + target_link_libraries(z_data_struct_test zenohpico::lib) + target_link_libraries(z_channels_test zenohpico::lib) + target_link_libraries(z_collections_test zenohpico::lib) + target_link_libraries(z_endpoint_test zenohpico::lib) + target_link_libraries(z_iobuf_test zenohpico::lib) + target_link_libraries(z_msgcodec_test zenohpico::lib) + target_link_libraries(z_keyexpr_test zenohpico::lib) + target_link_libraries(z_api_null_drop_test zenohpico::lib) + target_link_libraries(z_api_double_drop_test zenohpico::lib) + target_link_libraries(z_test_fragment_tx zenohpico::lib) + target_link_libraries(z_test_fragment_rx zenohpico::lib) + target_link_libraries(z_perf_tx zenohpico::lib) + target_link_libraries(z_perf_rx zenohpico::lib) + target_link_libraries(z_bytes_test zenohpico::lib) + target_link_libraries(z_api_bytes_test zenohpico::lib) + target_link_libraries(z_api_encoding_test zenohpico::lib) + target_link_libraries(z_refcount_test zenohpico::lib) configure_file(${PROJECT_SOURCE_DIR}/tests/modularity.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/modularity.py COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/raweth.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/raweth.py COPYONLY) @@ -469,7 +524,7 @@ if(UNIX OR MSVC) if(CMAKE_C_STANDARD MATCHES "11") add_executable(z_peer_multicast_test ${PROJECT_SOURCE_DIR}/tests/z_peer_multicast_test.c) - target_link_libraries(z_peer_multicast_test ${Libname}) + target_link_libraries(z_peer_multicast_test zenohpico::lib) configure_file(${PROJECT_SOURCE_DIR}/tests/multicast.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/multicast.sh COPYONLY) @@ -486,9 +541,9 @@ if(UNIX OR MSVC) add_executable(z_api_alignment_test ${PROJECT_SOURCE_DIR}/tests/z_api_alignment_test.c) add_executable(z_session_test ${PROJECT_SOURCE_DIR}/tests/z_session_test.c) - target_link_libraries(z_client_test ${Libname}) - target_link_libraries(z_api_alignment_test ${Libname}) - target_link_libraries(z_session_test ${Libname}) + target_link_libraries(z_client_test zenohpico::lib) + target_link_libraries(z_api_alignment_test zenohpico::lib) + target_link_libraries(z_session_test zenohpico::lib) configure_file(${PROJECT_SOURCE_DIR}/tests/routed.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/routed.sh COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/api.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/api.sh COPYONLY) @@ -503,37 +558,44 @@ endif() # For packaging if(PACKAGING) + set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}/packages") - set(CPACK_COMPONENTS_ALL Library Headers) - set(CPACK_COMPONENT_LIBRARY_GROUP "lib") + set(CPACK_COMPONENTS_ALL Runtime Headers Dev) + + set(CPACK_COMPONENT_RUNTIME_GROUP "lib") set(CPACK_COMPONENT_HEADERS_GROUP "dev") - set(CPACK_COMPONENT_HEADERS_DEPENDS Library) + set(CPACK_COMPONENT_DEV_GROUP "dev") + set(CPACK_COMPONENT_HEADERS_DEPENDS Runtime) + set(CPACK_COMPONENT_DEV_DEPENDS Runtime) set(CPACK_PACKAGE_CHECKSUM MD5) set(CPACK_PACKAGE_VENDOR "The Eclipse Foundation") - set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) - set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) - set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) - set(CPACK_COMPONENT_LIB_DESCRIPTION "The C client library for Eclipse zenoh targeting pico devices") - set(CPACK_COMPONENT_DEV_DESCRIPTION "${CPACK_COMPONENT_LIB_DESCRIPTION} - devel files") + if(NOT CPACK_PACKAGE_VERSION) + set(SEM_VER "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") + if(PROJECT_VERSION_TWEAK STREQUAL "") + set(CPACK_PACKAGE_VERSION ${SEM_VER}) + elseif(PROJECT_VERSION_TWEAK EQUAL 0) + set(CPACK_PACKAGE_VERSION "${SEM_VER}~dev-1") + elseif(PROJECT_VERSION_TWEAK GREATER 0) + set(CPACK_PACKAGE_VERSION "${SEM_VER}~pre.${PROJECT_VERSION_TWEAK}-1") + endif() + endif() + set(CPACK_COMPONENT_RUNTIME_DESCRIPTION "The C client library for Eclipse zenoh targeting pico devices") + set(CPACK_COMPONENT_HEADERS_DESCRIPTION "${CPACK_COMPONENT_LIB_DESCRIPTION} - headers") + set(CPACK_COMPONENT_DEV_DESCRIPTION "${CPACK_COMPONENT_LIB_DESCRIPTION} - config files") # Sources package set(CPACK_SOURCE_GENERATOR "TGZ") - set(CPACK_SOURCE_IGNORE_FILES "/.git/;/.github/;/build/;/crossbuilds/") - set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-src-${PROJECT_VERSION}") + set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-src-${project_version}") + + set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") if(PACKAGING MATCHES "DEB") if(NOT DEBARCH) - execute_process( - COMMAND dpkg --print-architecture - OUTPUT_VARIABLE DEBARCH - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + set(DEBARCH ${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_SYSTEM_NAME}) endif() - message(STATUS "Configure DEB packaging for Linux ${DEBARCH}") - if(CPACK_GENERATOR) set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB") else() @@ -545,9 +607,10 @@ if(PACKAGING) set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${DEBARCH}) set(CPACK_DEB_COMPONENT_INSTALL ON) set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT) - set(CPACK_DEBIAN_LIB_PACKAGE_NAME ${PROJECT_NAME}) # avoid "-lib" suffix for "lib" package + set(CPACK_DEBIAN_LIB_PACKAGE_NAME "lib${CPACK_PACKAGE_NAME}") set(CPACK_DEBIAN_LIB_PACKAGE_DEPENDS "libc6 (>=2.12)") - set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "${CPACK_DEBIAN_LIB_PACKAGE_NAME} (=${PROJECT_VERSION})") + set(CPACK_DEBIAN_DEV_PACKAGE_NAME "lib${CPACK_PACKAGE_NAME}-dev") + set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "${CPACK_DEBIAN_LIB_PACKAGE_NAME} (=${CPACK_PACKAGE_VERSION})") endif() if(PACKAGING MATCHES "RPM") @@ -555,8 +618,6 @@ if(PACKAGING) set(RPMARCH ${CMAKE_SYSTEM_PROCESSOR}) endif() - message(STATUS "Configure RPM packaging for Linux ${RPMARCH}") - if(CPACK_GENERATOR) set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM") else() @@ -567,8 +628,8 @@ if(PACKAGING) set(CPACK_RPM_PACKAGE_ARCHITECTURE ${RPMARCH}) set(CPACK_RPM_COMPONENT_INSTALL ON) set(CPACK_RPM_FILE_NAME RPM-DEFAULT) - set(CPACK_RPM_LIB_PACKAGE_NAME ${PROJECT_NAME}) # avoid "-lib" suffix for "lib" package - set(CPACK_RPM_DEV_PACKAGE_REQUIRES "${CPACK_RPM_LIB_PACKAGE_NAME} = ${PROJECT_VERSION}") + set(CPACK_RPM_LIB_PACKAGE_NAME ${CPACK_PACKAGE_NAME}) # avoid "-lib" suffix for "lib" package + set(CPACK_RPM_DEV_PACKAGE_REQUIRES "${CPACK_RPM_LIB_PACKAGE_NAME} = ${CPACK_PACKAGE_VERSION}") endif() include(CPack) diff --git a/GNUmakefile b/GNUmakefile index fcbbbb4d8..1ed16502e 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -63,7 +63,7 @@ Z_FEATURE_RAWETH_TRANSPORT?=0 # Buffer sizes FRAG_MAX_SIZE?=300000 BATCH_UNICAST_SIZE?=65535 -BATCH_MULTICAST_SIZE?=8096 +BATCH_MULTICAST_SIZE?=8192 # zenoh-pico/ directory ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) @@ -115,33 +115,33 @@ endif crossbuild: check-docker @echo "FROM dockcross/$(CROSSIMG)\nRUN apt-get update && apt-get -y install rpm" | docker build -t $(CROSSIMG_PREFIX)$(CROSSIMG) - docker run --rm -v $(ROOT_DIR):/workdir -w /workdir $(CROSSIMG_PREFIX)$(CROSSIMG) bash -c "\ - cmake $(CMAKE_OPT) -DPACKAGING=DEB,RPM -DDEBARCH=$(DEBARCH) -DRPMARCH=$(RPMARCH) -B$(CROSSBUILD_DIR)/$(CROSSIMG) && \ + cmake $(CMAKE_OPT) -DCPACK_PACKAGE_NAME=$(PACKAGE_NAME) -DPACKAGING=DEB,RPM -DDEBARCH=$(DEBARCH) -DRPMARCH=$(RPMARCH) -B$(CROSSBUILD_DIR)/$(CROSSIMG) && \ make VERBOSE=1 -C$(CROSSBUILD_DIR)/$(CROSSIMG) all package" docker rmi $(CROSSIMG_PREFIX)$(CROSSIMG) linux-armv5: - CROSSIMG=$@ DEBARCH=arm RPMARCH=arm make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=arm RPMARCH=arm make crossbuild linux-armv6: - CROSSIMG=$@ DEBARCH=arm RPMARCH=arm make crossbuild + PACKAGE_NAME="zenohpico-armv6" CROSSIMG=$@ DEBARCH=arm RPMARCH=arm make crossbuild linux-armv7: - CROSSIMG=$@ DEBARCH=armhf RPMARCH=armhf make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=armhf RPMARCH=armhf make crossbuild linux-armv7a: - CROSSIMG=$@ DEBARCH=armhf RPMARCH=armhf make crossbuild + PACKAGE_NAME="zenohpico-armv7a" CROSSIMG=$@ DEBARCH=armhf RPMARCH=armhf make crossbuild linux-arm64: - CROSSIMG=$@ DEBARCH=arm64 RPMARCH=aarch64 make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=arm64 RPMARCH=aarch64 make crossbuild linux-mips: - CROSSIMG=$@ DEBARCH=mips RPMARCH=mips make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=mips RPMARCH=mips make crossbuild linux-x86: - CROSSIMG=$@ DEBARCH=i386 RPMARCH=x86 make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=i386 RPMARCH=x86 make crossbuild linux-x64: - CROSSIMG=$@ DEBARCH=amd64 RPMARCH=x86_64 make crossbuild + PACKAGE_NAME="zenohpico" CROSSIMG=$@ DEBARCH=amd64 RPMARCH=x86_64 make crossbuild clean: rm -fr $(BUILD_DIR) diff --git a/PackageConfig.cmake.in b/PackageConfig.cmake.in index 94e4777a4..55339d35e 100644 --- a/PackageConfig.cmake.in +++ b/PackageConfig.cmake.in @@ -15,4 +15,15 @@ endif() include("${CMAKE_CURRENT_LIST_DIR}/zenohpicoTargets.cmake") -add_library(zenohpico::lib ALIAS zenohpico::zenohpico) +if(@PICO_SHARED@) + add_library(zenohpico::shared ALIAS zenohpico::zenohpico_shared) +endif() +if(@PICO_STATIC@) + add_library(zenohpico::static ALIAS zenohpico::zenohpico_static) +endif() + +if(@BUILD_SHARED_LIBS@) + add_library(zenohpico::lib ALIAS zenohpico::zenohpico_shared) +else() + add_library(zenohpico::lib ALIAS zenohpico::zenohpico_static) +endif() diff --git a/README.md b/README.md index 452643087..fed957104 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ ![Build](https://github.com/eclipse-zenoh/zenoh-pico/workflows/build/badge.svg) -![Crossbuild](https://github.com/eclipse-zenoh/zenoh-pico/workflows/crossbuild/badge.svg) ![integration](https://github.com/eclipse-zenoh/zenoh-pico/workflows/integration/badge.svg) [![Documentation Status](https://readthedocs.org/projects/zenoh-pico/badge/?version=latest)](https://zenoh-pico.readthedocs.io/en/latest/?badge=latest) [![Discussion](https://img.shields.io/badge/discussion-on%20github-blue)](https://github.com/eclipse-zenoh/roadmap/discussions) @@ -12,14 +11,14 @@ # Eclipse Zenoh The Eclipse Zenoh: Zero Overhead Pub/sub, Store/Query and Compute. -Zenoh (pronounce _/zeno/_) unifies data in motion, data at rest and computations. It carefully blends traditional pub/sub with geo-distributed storages, queries and computations, while retaining a level of time and space efficiency that is well beyond any of the mainstream stacks. +Zenoh (pronounce _/zeno/_) unifies data in motion, data at rest, and computations. It carefully blends traditional pub/sub with geo-distributed storages, queries and computations, while retaining a level of time and space efficiency that is well beyond any of the mainstream stacks. Check the website [zenoh.io](http://zenoh.io) and the [roadmap](https://github.com/eclipse-zenoh/roadmap) for more detailed information. ------------------------------- # Zenoh-Pico: native C library for constrained devices -zenoh-pico is the [Eclipse zenoh](http://zenoh.io) implementation that targets constrained devices and offers a native C API. +zenoh-pico is the [Eclipse zenoh](http://zenoh.io) implementation that targets constrained devices, offering a native C API. It is fully compatible with its main [Rust Zenoh implementation](https://github.com/eclipse-zenoh/zenoh), providing a lightweight implementation of most functionalities. Currently, zenoh-pico provides support for the following (RT)OSs and protocols: @@ -42,11 +41,11 @@ Check the website [zenoh.io](http://zenoh.io) and the [roadmap](https://github.c ## 1. How to install it The Eclipse zenoh-pico library is available as **Debian**, **RPM**, and **tgz** packages in the [Eclipse zenoh-pico download area](https://download.eclipse.org/zenoh/zenoh-pico/). -Those packages are built using manylinux2010 x86-32 and x86-64 to be compatible with most of the Linux platforms. -There are 2 kind of packages: +Those packages are built using manylinux2010 x86-32 and x86-64 for compatibility with most Linux platforms. +There are two kind of packages: - **libzenohpico**: only contains the library file (.so) -- **libzenohpico-dev**: contains the zenoh-pico header files for development. Depends on *libzenohpico* package +- **libzenohpico-dev**: contains the zenoh-pico header files for development and depends on the *libzenohpico* package For other platforms - like RTOS for embedded systems / microcontrollers -, you will need to clone and build the sources. Check [below](#how-to-build-for-microcontrollers) for more details. diff --git a/ci/scripts/build-linux.bash b/ci/scripts/build-linux.bash index 3d3a33ca4..3ac09ccdc 100644 --- a/ci/scripts/build-linux.bash +++ b/ci/scripts/build-linux.bash @@ -9,13 +9,13 @@ readonly version=${VERSION:?input VERSION is required} # Build target readonly target=${TARGET:?input TARGET is required} -BUILD_TYPE=RELEASE make "$target" +BUILD_SHARED_LIBS=ON BUILD_TYPE=RELEASE make "$target" readonly out=$GITHUB_WORKSPACE readonly repo_name=${repo#*/} -readonly archive_lib=$out/$repo_name-$version-$target.zip -readonly archive_deb=$out/$repo_name-$version-$target-deb-pkgs.zip -readonly archive_rpm=$out/$repo_name-$version-$target-rpm-pkgs.zip +readonly archive_lib=$out/$repo_name-$version-$target-standalone.zip +readonly archive_deb=$out/$repo_name-$version-$target-debian.zip +readonly archive_rpm=$out/$repo_name-$version-$target-rpm.zip readonly archive_examples=$out/$repo_name-$version-$target-examples.zip cd crossbuilds/"$target" @@ -24,8 +24,8 @@ cd - zip -r "$archive_lib" include cd crossbuilds/"$target"/packages -zip "$archive_deb" ./*.deb -zip "$archive_rpm" ./*.rpm +zip -9 -j "$archive_deb" ./*.deb +zip -9 -j "$archive_rpm" ./*.rpm cd - cd crossbuilds/"$target"/examples diff --git a/ci/scripts/bump-and-tag.bash b/ci/scripts/bump-and-tag.bash index 58883d627..f54d8953e 100644 --- a/ci/scripts/bump-and-tag.bash +++ b/ci/scripts/bump-and-tag.bash @@ -2,6 +2,7 @@ set -xeo pipefail +readonly live_run=${LIVE_RUN:-false} # Release number readonly version=${VERSION:-input VERSION is required} # Git actor name @@ -18,7 +19,9 @@ export GIT_COMMITTER_EMAIL=$git_user_email printf '%s' "$version" > version.txt git commit version.txt -m "chore: Bump version to $version" -git tag --force "$version" -m "v$version" +if [[ ${live_run} ]]; then + git tag --force "$version" -m "v$version" +fi git log -10 git show-ref --tags git push --force origin diff --git a/docs/api.rst b/docs/api.rst index b2ff6cf4a..b76f7a040 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -462,7 +462,16 @@ See details at :ref:`owned_types_concept` .. c:type:: z_owned_closure_sample_t .. c:type:: z_loaned_closure_sample_t .. c:type:: z_moved_closure_sample_t - + +.. c:type:: void (* z_closure_sample_callback_t)(z_loaned_sample_t * sample, void * arg); + + Function pointer type for handling samples. + Represents a callback function that is invoked when a sample is available for processing. + + Parameters: + - **sample** - Pointer to a :c:type:`z_loaned_sample_t` representing the sample to be processed. + - **arg** - A user-defined pointer to additional data that can be used during the processing of the sample. + Functions ^^^^^^^^^ .. autocfunction:: primitives.h::z_closure_sample @@ -486,7 +495,16 @@ See details at :ref:`owned_types_concept` .. c:type:: z_owned_closure_query_t .. c:type:: z_loaned_closure_query_t .. c:type:: z_moved_closure_query_t - + +.. c:type:: void (* z_closure_query_callback_t)(z_loaned_query_t * query, void * arg); + + Function pointer type for handling queries. + Represents a callback function that is invoked when a query is available for processing. + + Parameters: + - **query** - Pointer to a :c:type:`z_loaned_query_t` representing the query to be processed. + - **arg** - A user-defined pointer to additional data that can be used during the processing of the query. + Functions ^^^^^^^^^ .. autocfunction:: primitives.h::z_closure_query @@ -511,7 +529,16 @@ See details at :ref:`owned_types_concept` .. c:type:: z_owned_closure_reply_t .. c:type:: z_loaned_closure_reply_t .. c:type:: z_moved_closure_reply_t - + +.. c:type:: void (* z_closure_reply_callback_t)(z_loaned_reply_t * reply, void * arg); + + Function pointer type for handling replies. + Represents a callback function that is invoked when a reply is available for processing. + + Parameters: + - **reply** - Pointer to a :c:type:`z_loaned_reply_t` representing the reply to be processed. + - **arg** - A user-defined pointer to additional data that can be used during the processing of the reply. + Functions ^^^^^^^^^ .. autocfunction:: primitives.h::z_closure_reply @@ -536,6 +563,15 @@ See details at :ref:`owned_types_concept` .. c:type:: z_owned_closure_hello_t .. c:type:: z_loaned_closure_hello_t .. c:type:: z_moved_closure_hello_t + +.. c:type:: void (* z_closure_hello_callback_t)(z_loaned_hello_t * hello, void * arg); + + Function pointer type for handling scouting response. + Represents a callback function that is invoked when a hello is available for processing. + + Parameters: + - **hello** - Pointer to a :c:type:`z_loaned_hello_t` representing the hello to be processed. + - **arg** - A user-defined pointer to additional data that can be used during the processing of the hello. Functions ^^^^^^^^^ @@ -561,6 +597,15 @@ See details at :ref:`owned_types_concept` .. c:type:: z_owned_closure_zid_t .. c:type:: z_loaned_closure_zid_t .. c:type:: z_moved_closure_zid_t + +.. c:type:: void (* z_closure_zid_callback_t)(z_loaned_zid_t * zid, void * arg); + + Function pointer type for handling Zenoh ID routers response. + Represents a callback function that is invoked when a zid is available for processing. + + Parameters: + - **zid** - Pointer to a :c:type:`z_loaned_zid_t` representing the zid to be processed. + - **arg** - A user-defined pointer to additional data that can be used during the processing of the zid. Functions ^^^^^^^^^ @@ -1192,6 +1237,7 @@ Functions .. autocfunction:: serialization.h::ze_serializer_serialize_buf .. autocfunction:: serialization.h::ze_serializer_serialize_string .. autocfunction:: serialization.h::ze_serializer_serialize_str +.. autocfunction:: serialization.h::ze_serializer_serialize_substr .. autocfunction:: serialization.h::ze_serializer_serialize_sequence_length .. autocfunction:: serialization.h::ze_deserialize_int8 .. autocfunction:: serialization.h::ze_deserialize_int16 @@ -1222,6 +1268,7 @@ Functions .. autocfunction:: serialization.h::ze_serialize_buf .. autocfunction:: serialization.h::ze_serialize_string .. autocfunction:: serialization.h::ze_serialize_str +.. autocfunction:: serialization.h::ze_serialize_substr Others @@ -1230,8 +1277,6 @@ Others Data Structures --------------- -.. autoctype:: types.h::z_zint_t - .. autoctype:: types.h::zp_task_read_options_t .. autoctype:: types.h::zp_task_lease_options_t .. autoctype:: types.h::zp_read_options_t @@ -1270,10 +1315,52 @@ Functions .. autocfunction:: primitives.h::zp_send_join_options_default .. autocfunction:: primitives.h::zp_send_join -.. TODO Logging -.. TODO ======= +Logging +======= + +.. warning:: This API has been marked as unstable: it works as advertised, but it may be changed in a future release. + +Zenoh-Pico provides a flexible logging system to assist with debugging and monitoring. +By default, logging is disabled in release builds, but it can be enabled and configured +based on the desired level of verbosity. + +Logging Levels +-------------- + +Zenoh-Pico supports three logging levels: + +- **Error**: Only error messages are logged. This is the least verbose level. +- **Info**: Logs informational messages and error messages. +- **Debug**: Logs debug messages, informational messages, and error messages. This is the most verbose level. + +Enabling Logging +---------------- + +To enable logging, you can adjust the logging level by defining the ``ZENOH_DEBUG`` macro at compile time. + +- Set ``ZENOH_DEBUG`` to ``1`` to enable error messages. +- Set ``ZENOH_DEBUG`` to ``2`` to enable informational messages. +- Set ``ZENOH_DEBUG`` to ``3`` to enable debug messages (includes info and error). + +Additionally, logging can be automatically enabled in **debug builds** by defining the ``Z_BUILD_DEBUG`` macro. +In release builds, logging is disabled unless ``ZENOH_DEBUG`` is explicitly set. + +Example of Enabling Logging +--------------------------- + +To enable **debug-level logging** in your build, you would add the following flags during compilation: + +.. code-block:: bash + + gcc -DZENOH_DEBUG=3 -o my_program my_program.c +This will enable the most verbose logging, printing debug, info, and error messages. +Disabling Logging +----------------- +To disable all logging, set ``ZENOH_DEBUG`` to ``0`` or ensure it is undefined in release builds: +.. code-block:: bash + gcc -DZENOH_DEBUG=0 -o my_program my_program.c diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a3fc911cd..a001356e8 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -14,7 +14,7 @@ endif() function(add_example name) add_executable(${name} ${ARGN}) set_property(TARGET ${name} PROPERTY C_STANDARD 11) - target_link_libraries(${name} zenohpico) + target_link_libraries(${name} zenohpico::lib) add_dependencies(examples ${name}) endfunction() diff --git a/examples/espidf/z_get.c b/examples/espidf/z_get.c index 5142009b1..fcfb5f975 100644 --- a/examples/espidf/z_get.c +++ b/examples/espidf/z_get.c @@ -169,7 +169,7 @@ void app_main() { opts.payload = z_move(payload); } z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { diff --git a/examples/espidf/z_queryable.c b/examples/espidf/z_queryable.c index c95ca377e..0939bfac8 100644 --- a/examples/espidf/z_queryable.c +++ b/examples/espidf/z_queryable.c @@ -169,7 +169,7 @@ void app_main() { // Declare Zenoh queryable printf("Declaring Queryable on %s...", KEYEXPR); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); diff --git a/examples/espidf/z_sub.c b/examples/espidf/z_sub.c index 01bb61de2..d7ac968ae 100644 --- a/examples/espidf/z_sub.c +++ b/examples/espidf/z_sub.c @@ -151,7 +151,7 @@ void app_main() { printf("Declaring Subscriber on '%s'...", KEYEXPR); z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); z_owned_subscriber_t sub; z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); diff --git a/examples/freertos_plus_tcp/CMakeLists.txt b/examples/freertos_plus_tcp/CMakeLists.txt index 83f890f30..3a0d44b54 100644 --- a/examples/freertos_plus_tcp/CMakeLists.txt +++ b/examples/freertos_plus_tcp/CMakeLists.txt @@ -55,9 +55,9 @@ FetchContent_MakeAvailable(freertos_kernel freertos_plus_tcp) set(BUILD_SHARED_LIBS OFF) set(WITH_FREERTOS_PLUS_TCP ON) set(ZENOH_DEBUG 3) -configure_include_project(ZENOHPICO zenohpico zenohpico "../.." zenohpico "https://github.com/eclipse-zenoh/zenoh-pico" "") +configure_include_project(ZENOHPICO zenohpico zenohpico::lib "../.." zenohpico "https://github.com/eclipse-zenoh/zenoh-pico" "") -target_link_libraries(zenohpico +target_link_libraries(zenohpico_static freertos_kernel freertos_plus_tcp ) @@ -74,7 +74,7 @@ function(add_example name) main freertos_kernel freertos_plus_tcp - zenohpico + zenohpico::lib ) endfunction() diff --git a/examples/freertos_plus_tcp/z_get.c b/examples/freertos_plus_tcp/z_get.c index 96931fcab..7d76d8de3 100644 --- a/examples/freertos_plus_tcp/z_get.c +++ b/examples/freertos_plus_tcp/z_get.c @@ -93,7 +93,7 @@ void app_main(void) { opts.payload = z_move(payload); } z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); return; diff --git a/examples/freertos_plus_tcp/z_queryable.c b/examples/freertos_plus_tcp/z_queryable.c index 34c1c2a94..a1f8634f8 100644 --- a/examples/freertos_plus_tcp/z_queryable.c +++ b/examples/freertos_plus_tcp/z_queryable.c @@ -85,7 +85,7 @@ void app_main(void) { printf("Creating Queryable on '%s'...\n", KEYEXPR); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; if (z_declare_queryable(z_loan(s), &qable, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create queryable.\n"); diff --git a/examples/freertos_plus_tcp/z_sub.c b/examples/freertos_plus_tcp/z_sub.c index 45f7c4775..4febeecf7 100644 --- a/examples/freertos_plus_tcp/z_sub.c +++ b/examples/freertos_plus_tcp/z_sub.c @@ -62,7 +62,7 @@ void app_main(void) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", KEYEXPR); z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); diff --git a/examples/freertos_plus_tcp/z_sub_st.c b/examples/freertos_plus_tcp/z_sub_st.c index 805a0c949..34ae7b6f4 100644 --- a/examples/freertos_plus_tcp/z_sub_st.c +++ b/examples/freertos_plus_tcp/z_sub_st.c @@ -59,7 +59,7 @@ void app_main(void) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", KEYEXPR); z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); diff --git a/examples/unix/c11/z_get.c b/examples/unix/c11/z_get.c index 034ddb2d5..3bf67421f 100644 --- a/examples/unix/c11/z_get.c +++ b/examples/unix/c11/z_get.c @@ -135,7 +135,7 @@ int main(int argc, char **argv) { } z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); return -1; diff --git a/examples/unix/c11/z_get_attachment.c b/examples/unix/c11/z_get_attachment.c index 2d7ddcccc..1d20e3c96 100644 --- a/examples/unix/c11/z_get_attachment.c +++ b/examples/unix/c11/z_get_attachment.c @@ -192,7 +192,7 @@ int main(int argc, char **argv) { opts.encoding = z_move(encoding); z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); return -1; diff --git a/examples/unix/c11/z_info.c b/examples/unix/c11/z_info.c index 94df7db68..fe4b61beb 100644 --- a/examples/unix/c11/z_info.c +++ b/examples/unix/c11/z_info.c @@ -86,14 +86,14 @@ int main(int argc, char **argv) { printf("Routers IDs:\n"); z_owned_closure_zid_t callback; - z_closure(&callback, print_zid); + z_closure(&callback, print_zid, NULL, NULL); z_info_routers_zid(z_loan(s), z_move(callback)); // `callback` has been `z_move`d just above, so it's safe to reuse the variable, // we'll just have to make sure we `z_move` it again to avoid mem-leaks. printf("Peers IDs:\n"); z_owned_closure_zid_t callback2; - z_closure(&callback2, print_zid); + z_closure(&callback2, print_zid, NULL, NULL); z_info_peers_zid(z_loan(s), z_move(callback2)); z_drop(z_move(s)); diff --git a/examples/unix/c11/z_queryable.c b/examples/unix/c11/z_queryable.c index 13ced6dfc..6ec72f517 100644 --- a/examples/unix/c11/z_queryable.c +++ b/examples/unix/c11/z_queryable.c @@ -146,7 +146,7 @@ int main(int argc, char **argv) { printf("Creating Queryable on '%s'...\n", keyexpr); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; if (z_declare_queryable(z_loan(s), &qable, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create queryable.\n"); diff --git a/examples/unix/c11/z_queryable_attachment.c b/examples/unix/c11/z_queryable_attachment.c index ace30bb48..fceed2e2f 100644 --- a/examples/unix/c11/z_queryable_attachment.c +++ b/examples/unix/c11/z_queryable_attachment.c @@ -185,7 +185,7 @@ int main(int argc, char **argv) { printf("Creating Queryable on '%s'...\n", keyexpr); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; if (z_declare_queryable(z_loan(s), &qable, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create queryable.\n"); diff --git a/examples/unix/c11/z_sub.c b/examples/unix/c11/z_sub.c index 1c9df33b1..0d8b73e39 100644 --- a/examples/unix/c11/z_sub.c +++ b/examples/unix/c11/z_sub.c @@ -98,7 +98,7 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", keyexpr); z_owned_subscriber_t sub; z_view_keyexpr_t ke; diff --git a/examples/unix/c11/z_sub_attachment.c b/examples/unix/c11/z_sub_attachment.c index 823280673..0421f419e 100644 --- a/examples/unix/c11/z_sub_attachment.c +++ b/examples/unix/c11/z_sub_attachment.c @@ -147,7 +147,7 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", keyexpr); z_owned_subscriber_t sub; z_view_keyexpr_t ke; diff --git a/examples/unix/c11/z_sub_st.c b/examples/unix/c11/z_sub_st.c index 083d9465d..edc3b4e5e 100644 --- a/examples/unix/c11/z_sub_st.c +++ b/examples/unix/c11/z_sub_st.c @@ -90,7 +90,7 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", keyexpr); z_owned_subscriber_t sub; z_view_keyexpr_t ke; diff --git a/examples/windows/z_get.c b/examples/windows/z_get.c index 3c5a3f338..dc4cfc862 100644 --- a/examples/windows/z_get.c +++ b/examples/windows/z_get.c @@ -92,7 +92,7 @@ int main(int argc, char **argv) { opts.payload = z_move(payload); } z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); return -1; diff --git a/examples/windows/z_info.c b/examples/windows/z_info.c index 96f8dcc62..62a459156 100644 --- a/examples/windows/z_info.c +++ b/examples/windows/z_info.c @@ -59,14 +59,14 @@ int main(int argc, char **argv) { printf("Routers IDs:\n"); z_owned_closure_zid_t callback; - z_closure(&callback, print_zid); + z_closure(&callback, print_zid, NULL, NULL); z_info_routers_zid(z_loan(s), z_move(callback)); // `callback` has been `z_move`d just above, so it's safe to reuse the variable, // we'll just have to make sure we `z_move` it again to avoid mem-leaks. printf("Peers IDs:\n"); z_owned_closure_zid_t callback2; - z_closure(&callback2, print_zid); + z_closure(&callback2, print_zid, NULL, NULL); z_info_peers_zid(z_loan(s), z_move(callback2)); z_drop(z_move(s)); diff --git a/examples/windows/z_queryable.c b/examples/windows/z_queryable.c index 11a01d92e..4a1c2e469 100644 --- a/examples/windows/z_queryable.c +++ b/examples/windows/z_queryable.c @@ -79,7 +79,7 @@ int main(int argc, char **argv) { printf("Creating Queryable on '%s'...\n", keyexpr); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; if (z_declare_queryable(z_loan(s), &qable, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create queryable.\n"); diff --git a/examples/windows/z_sub.c b/examples/windows/z_sub.c index 166775ea1..8df2bb696 100644 --- a/examples/windows/z_sub.c +++ b/examples/windows/z_sub.c @@ -59,7 +59,7 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", keyexpr); z_owned_subscriber_t sub; z_view_keyexpr_t ke; diff --git a/examples/windows/z_sub_st.c b/examples/windows/z_sub_st.c index 16507ef28..b1d2a6634 100644 --- a/examples/windows/z_sub_st.c +++ b/examples/windows/z_sub_st.c @@ -56,7 +56,7 @@ int main(int argc, char **argv) { } z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", keyexpr); z_owned_subscriber_t sub; z_view_keyexpr_t ke; diff --git a/examples/zephyr/z_get.c b/examples/zephyr/z_get.c index 8d22aa0c7..c56049899 100644 --- a/examples/zephyr/z_get.c +++ b/examples/zephyr/z_get.c @@ -66,7 +66,7 @@ int main(int argc, char **argv) { z_owned_session_t s; if (z_open(&s, z_move(config), NULL) < 0) { printf("Unable to open session!\n"); - exit(-1); + return -1; } printf("OK\n"); @@ -87,12 +87,12 @@ int main(int argc, char **argv) { opts.payload = z_move(payload); } z_owned_closure_reply_t callback; - z_closure(&callback, reply_handler, reply_dropper); + z_closure(&callback, reply_handler, reply_dropper, NULL); z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); - exit(-1); + return -1; } } diff --git a/examples/zephyr/z_pub.c b/examples/zephyr/z_pub.c index ce91c4d38..4f9f063b7 100644 --- a/examples/zephyr/z_pub.c +++ b/examples/zephyr/z_pub.c @@ -48,7 +48,7 @@ int main(int argc, char **argv) { z_owned_session_t s; if (z_open(&s, z_move(config), NULL) < 0) { printf("Unable to open session!\n"); - exit(-1); + return -1; } printf("OK\n"); @@ -62,7 +62,7 @@ int main(int argc, char **argv) { z_owned_publisher_t pub; if (z_declare_publisher(z_loan(s), &pub, z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); - exit(-1); + return -1; } printf("OK\n"); diff --git a/examples/zephyr/z_pull.c b/examples/zephyr/z_pull.c index 06562eed6..e3be5f345 100644 --- a/examples/zephyr/z_pull.c +++ b/examples/zephyr/z_pull.c @@ -48,7 +48,7 @@ int main(int argc, char **argv) { z_owned_session_t s; if (z_open(&s, z_move(config), NULL) < 0) { printf("Unable to open session!\n"); - exit(-1); + return -1; } printf("OK\n"); @@ -56,7 +56,7 @@ int main(int argc, char **argv) { if (zp_start_read_task(z_loan_mut(s), NULL) < 0 || zp_start_lease_task(z_loan_mut(s), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_session_drop(z_session_move(&s)); - exit(-1); + return -1; } printf("Declaring Subscriber on '%s'...\n", KEYEXPR); @@ -68,7 +68,7 @@ int main(int argc, char **argv) { z_view_keyexpr_from_str(&ke, KEYEXPR); if (z_declare_subscriber(z_loan(s), &sub, z_loan(ke), z_move(closure), NULL) < 0) { printf("Unable to declare subscriber.\n"); - exit(-1); + return -1; } printf("Pulling data every %zu ms... Ring size: %zd\n", INTERVAL, SIZE); diff --git a/examples/zephyr/z_queryable.c b/examples/zephyr/z_queryable.c index 0d34c4c03..1eafda347 100644 --- a/examples/zephyr/z_queryable.c +++ b/examples/zephyr/z_queryable.c @@ -71,7 +71,7 @@ int main(int argc, char **argv) { z_owned_session_t s; if (z_open(&s, z_move(config), NULL) < 0) { printf("Unable to open session!\n"); - exit(-1); + return -1; } printf("OK\n"); @@ -82,13 +82,13 @@ int main(int argc, char **argv) { // Declare Zenoh queryable printf("Declaring Queryable on %s...", KEYEXPR); z_owned_closure_query_t callback; - z_closure(&callback, query_handler); + z_closure(&callback, query_handler, NULL, NULL); z_owned_queryable_t qable; z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); if (z_declare_queryable(z_loan(s), &qable, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare queryable.\n"); - exit(-1); + return -1; } printf("OK\n"); printf("Zenoh setup finished!\n"); diff --git a/examples/zephyr/z_sub.c b/examples/zephyr/z_sub.c index 68c0f46e1..c49668b3c 100644 --- a/examples/zephyr/z_sub.c +++ b/examples/zephyr/z_sub.c @@ -55,7 +55,7 @@ int main(int argc, char **argv) { z_owned_session_t s; if (z_open(&s, z_move(config), NULL) < 0) { printf("Unable to open session!\n"); - exit(-1); + return -1; } printf("OK\n"); @@ -65,13 +65,13 @@ int main(int argc, char **argv) { printf("Declaring Subscriber on '%s'...", KEYEXPR); z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); z_view_keyexpr_t ke; z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); z_owned_subscriber_t sub; if (z_declare_subscriber(z_loan(s), &sub, z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); - exit(-1); + return -1; } printf("OK!\n"); diff --git a/include/zenoh-pico/api/encoding.h b/include/zenoh-pico/api/encoding.h index 3544693b8..7393ae259 100644 --- a/include/zenoh-pico/api/encoding.h +++ b/include/zenoh-pico/api/encoding.h @@ -78,84 +78,84 @@ extern const z_owned_encoding_t ZP_ENCODING_ZENOH_SERIALIZED; * Constant alias for string: `"application/octet-stream"`. */ const z_loaned_encoding_t *z_encoding_application_octet_stream(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_OCTET_STREAM; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_OCTET_STREAM; /** * A textual file. * Constant alias for string: `"text/plain"`. */ const z_loaned_encoding_t *z_encoding_text_plain(void); -extern const z_owned_encoding_t ENCODING_TEXT_PLAIN; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_PLAIN; /** * JSON data intended to be consumed by an application. * Constant alias for string: `"application/json"`. */ const z_loaned_encoding_t *z_encoding_application_json(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JSON; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JSON; /** * JSON data intended to be human readable. * Constant alias for string: `"text/json"`. */ const z_loaned_encoding_t *z_encoding_text_json(void); -extern const z_owned_encoding_t ENCODING_TEXT_JSON; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_JSON; /** * A Common Data Representation (CDR)-encoded data. * Constant alias for string: `"application/cdr"`. */ const z_loaned_encoding_t *z_encoding_application_cdr(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_CDR; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_CDR; /** * A Concise Binary Object Representation (CBOR)-encoded data. * Constant alias for string: `"application/cbor"`. */ const z_loaned_encoding_t *z_encoding_application_cbor(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_CBOR; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_CBOR; /** * YAML data intended to be consumed by an application. * Constant alias for string: `"application/yaml"`. */ const z_loaned_encoding_t *z_encoding_application_yaml(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_YAML; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_YAML; /** * YAML data intended to be human readable. * Constant alias for string: `"text/yaml"`. */ const z_loaned_encoding_t *z_encoding_text_yaml(void); -extern const z_owned_encoding_t ENCODING_TEXT_YAML; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_YAML; /** * JSON5 encoded data that are human readable. * Constant alias for string: `"text/json5"`. */ const z_loaned_encoding_t *z_encoding_text_json5(void); -extern const z_owned_encoding_t ENCODING_TEXT_JSON5; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_JSON5; /** * A Python object serialized using `pickle `_. * Constant alias for string: `"application/python-serialized-object"`. */ const z_loaned_encoding_t *z_encoding_application_python_serialized_object(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_PYTHON_SERIALIZED_OBJECT; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_PYTHON_SERIALIZED_OBJECT; /** * An application-specific protobuf-encoded data. * Constant alias for string: `"application/protobuf"`. */ const z_loaned_encoding_t *z_encoding_application_protobuf(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_PROTOBUF; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_PROTOBUF; /** * A Java serialized object. * Constant alias for string: `"application/java-serialized-object"`. */ const z_loaned_encoding_t *z_encoding_application_java_serialized_object(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JAVA_SERIALIZED_OBJECT; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JAVA_SERIALIZED_OBJECT; /** * An `openmetrics `_ data, commonly used by @@ -163,266 +163,266 @@ extern const z_owned_encoding_t ENCODING_APPLICATION_JAVA_SERIALIZED_OBJECT; * Constant alias for string: `"application/openmetrics-text"`. */ const z_loaned_encoding_t *z_encoding_application_openmetrics_text(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_OPENMETRICS_TEXT; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_OPENMETRICS_TEXT; /** * A Portable Network Graphics (PNG) image. * Constant alias for string: `"image/png"`. */ const z_loaned_encoding_t *z_encoding_image_png(void); -extern const z_owned_encoding_t ENCODING_IMAGE_PNG; +extern const z_owned_encoding_t ZP_ENCODING_IMAGE_PNG; /** * A Joint Photographic Experts Group (JPEG) image. * Constant alias for string: `"image/jpeg"`. */ const z_loaned_encoding_t *z_encoding_image_jpeg(void); -extern const z_owned_encoding_t ENCODING_IMAGE_JPEG; +extern const z_owned_encoding_t ZP_ENCODING_IMAGE_JPEG; /** * A Graphics Interchange Format (GIF) image. * Constant alias for string: `"image/gif"`. */ const z_loaned_encoding_t *z_encoding_image_gif(void); -extern const z_owned_encoding_t ENCODING_IMAGE_GIF; +extern const z_owned_encoding_t ZP_ENCODING_IMAGE_GIF; /** * A BitMap (BMP) image. * Constant alias for string: `"image/bmp"`. */ const z_loaned_encoding_t *z_encoding_image_bmp(void); -extern const z_owned_encoding_t ENCODING_IMAGE_BMP; +extern const z_owned_encoding_t ZP_ENCODING_IMAGE_BMP; /** * A Web Portable (WebP) image. * Constant alias for string: `"image/webp"`. */ const z_loaned_encoding_t *z_encoding_image_webp(void); -extern const z_owned_encoding_t ENCODING_IMAGE_WEBP; +extern const z_owned_encoding_t ZP_ENCODING_IMAGE_WEBP; /** * An XML file intended to be consumed by an application. * Constant alias for string: `"application/xml"`. */ const z_loaned_encoding_t *z_encoding_application_xml(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_XML; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_XML; /** * An encoded list of tuples, each consisting of a name and a value. * Constant alias for string: `"application/x-www-form-urlencoded"`. */ const z_loaned_encoding_t *z_encoding_application_x_www_form_urlencoded(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_X_WWW_FORM_URLENCODED; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_X_WWW_FORM_URLENCODED; /** * An HTML file. * Constant alias for string: `"text/html"`. */ const z_loaned_encoding_t *z_encoding_text_html(void); -extern const z_owned_encoding_t ENCODING_TEXT_HTML; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_HTML; /** * An XML file that is human-readable. * Constant alias for string: `"text/xml"`. */ const z_loaned_encoding_t *z_encoding_text_xml(void); -extern const z_owned_encoding_t ENCODING_TEXT_XML; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_XML; /** * A CSS file. * Constant alias for string: `"text/css"`. */ const z_loaned_encoding_t *z_encoding_text_css(void); -extern const z_owned_encoding_t ENCODING_TEXT_CSS; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_CSS; /** * A JavaScript file. * Constant alias for string: `"text/javascript"`. */ const z_loaned_encoding_t *z_encoding_text_javascript(void); -extern const z_owned_encoding_t ENCODING_TEXT_JAVASCRIPT; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_JAVASCRIPT; /** * A Markdown file. * Constant alias for string: `"text/markdown"`. */ const z_loaned_encoding_t *z_encoding_text_markdown(void); -extern const z_owned_encoding_t ENCODING_TEXT_MARKDOWN; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_MARKDOWN; /** * A CSV file. * Constant alias for string: `"text/csv"`. */ const z_loaned_encoding_t *z_encoding_text_csv(void); -extern const z_owned_encoding_t ENCODING_TEXT_CSV; +extern const z_owned_encoding_t ZP_ENCODING_TEXT_CSV; /** * An application-specific SQL query. * Constant alias for string: `"application/sql"`. */ const z_loaned_encoding_t *z_encoding_application_sql(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_SQL; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_SQL; /** * Constrained Application Protocol (CoAP) data intended for CoAP-to-HTTP and HTTP-to-CoAP proxies. * Constant alias for string: `"application/coap-payload"`. */ const z_loaned_encoding_t *z_encoding_application_coap_payload(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_COAP_PAYLOAD; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_COAP_PAYLOAD; /** * Defines a JSON document structure for expressing a sequence of operations to apply to a JSON document. * Constant alias for string: `"application/json-patch+json"`. */ const z_loaned_encoding_t *z_encoding_application_json_patch_json(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JSON_PATCH_JSON; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JSON_PATCH_JSON; /** * A JSON text sequence consists of any number of JSON texts, all encoded in UTF-8. * Constant alias for string: `"application/json-seq"`. */ const z_loaned_encoding_t *z_encoding_application_json_seq(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JSON_SEQ; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JSON_SEQ; /** * A JSONPath defines a string syntax for selecting and extracting JSON values from within a given JSON value. * Constant alias for string: `"application/jsonpath"`. */ const z_loaned_encoding_t *z_encoding_application_jsonpath(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JSONPATH; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JSONPATH; /** * A JSON Web Token (JWT). * Constant alias for string: `"application/jwt"`. */ const z_loaned_encoding_t *z_encoding_application_jwt(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_JWT; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_JWT; /** * An application-specific MPEG-4 encoded data, either audio or video. * Constant alias for string: `"application/mp4"`. */ const z_loaned_encoding_t *z_encoding_application_mp4(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_MP4; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_MP4; /** * A SOAP 1.2 message serialized as XML 1.0. * Constant alias for string: `"application/soap+xml"`. */ const z_loaned_encoding_t *z_encoding_application_soap_xml(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_SOAP_XML; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_SOAP_XML; /** * A YANG-encoded data commonly used by the Network Configuration Protocol (NETCONF). * Constant alias for string: `"application/yang"`. */ const z_loaned_encoding_t *z_encoding_application_yang(void); -extern const z_owned_encoding_t ENCODING_APPLICATION_YANG; +extern const z_owned_encoding_t ZP_ENCODING_APPLICATION_YANG; /** * A MPEG-4 Advanced Audio Coding (AAC) media. * Constant alias for string: `"audio/aac"`. */ const z_loaned_encoding_t *z_encoding_audio_aac(void); -extern const z_owned_encoding_t ENCODING_AUDIO_AAC; +extern const z_owned_encoding_t ZP_ENCODING_AUDIO_AAC; /** * A Free Lossless Audio Codec (FLAC) media. * Constant alias for string: `"audio/flac"`. */ const z_loaned_encoding_t *z_encoding_audio_flac(void); -extern const z_owned_encoding_t ENCODING_AUDIO_FLAC; +extern const z_owned_encoding_t ZP_ENCODING_AUDIO_FLAC; /** * An audio codec defined in MPEG-1, MPEG-2, MPEG-4, or registered at the MP4 registration authority. * Constant alias for string: `"audio/mp4"`. */ const z_loaned_encoding_t *z_encoding_audio_mp4(void); -extern const z_owned_encoding_t ENCODING_AUDIO_MP4; +extern const z_owned_encoding_t ZP_ENCODING_AUDIO_MP4; /** * An Ogg-encapsulated audio stream. * Constant alias for string: `"audio/ogg"`. */ const z_loaned_encoding_t *z_encoding_audio_ogg(void); -extern const z_owned_encoding_t ENCODING_AUDIO_OGG; +extern const z_owned_encoding_t ZP_ENCODING_AUDIO_OGG; /** * A Vorbis-encoded audio stream. * Constant alias for string: `"audio/vorbis"`. */ const z_loaned_encoding_t *z_encoding_audio_vorbis(void); -extern const z_owned_encoding_t ENCODING_AUDIO_VORBIS; +extern const z_owned_encoding_t ZP_ENCODING_AUDIO_VORBIS; /** * A h261-encoded video stream. * Constant alias for string: `"video/h261"`. */ const z_loaned_encoding_t *z_encoding_video_h261(void); -extern const z_owned_encoding_t ENCODING_VIDEO_H261; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_H261; /** * A h263-encoded video stream. * Constant alias for string: `"video/h263"`. */ const z_loaned_encoding_t *z_encoding_video_h263(void); -extern const z_owned_encoding_t ENCODING_VIDEO_H263; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_H263; /** * A h264-encoded video stream. * Constant alias for string: `"video/h264"`. */ const z_loaned_encoding_t *z_encoding_video_h264(void); -extern const z_owned_encoding_t ENCODING_VIDEO_H264; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_H264; /** * A h265-encoded video stream. * Constant alias for string: `"video/h265"`. */ const z_loaned_encoding_t *z_encoding_video_h265(void); -extern const z_owned_encoding_t ENCODING_VIDEO_H265; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_H265; /** * A h266-encoded video stream. * Constant alias for string: `"video/h266"`. */ const z_loaned_encoding_t *z_encoding_video_h266(void); -extern const z_owned_encoding_t ENCODING_VIDEO_H266; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_H266; /** * A video codec defined in MPEG-1, MPEG-2, MPEG-4, or registered at the MP4 registration authority. * Constant alias for string: `"video/mp4"`. */ const z_loaned_encoding_t *z_encoding_video_mp4(void); -extern const z_owned_encoding_t ENCODING_VIDEO_MP4; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_MP4; /** * An Ogg-encapsulated video stream. * Constant alias for string: `"video/ogg"`. */ const z_loaned_encoding_t *z_encoding_video_ogg(void); -extern const z_owned_encoding_t ENCODING_VIDEO_OGG; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_OGG; /** * An uncompressed, studio-quality video stream. * Constant alias for string: `"video/raw"`. */ const z_loaned_encoding_t *z_encoding_video_raw(void); -extern const z_owned_encoding_t ENCODING_VIDEO_RAW; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_RAW; /** * A VP8-encoded video stream. * Constant alias for string: `"video/vp8"`. */ const z_loaned_encoding_t *z_encoding_video_vp8(void); -extern const z_owned_encoding_t ENCODING_VIDEO_VP8; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_VP8; /** * A VP9-encoded video stream. * Constant alias for string: `"video/vp9"`. */ const z_loaned_encoding_t *z_encoding_video_vp9(void); -extern const z_owned_encoding_t ENCODING_VIDEO_VP9; +extern const z_owned_encoding_t ZP_ENCODING_VIDEO_VP9; /** * Returns a loaned default `z_loaned_encoding_t`. diff --git a/include/zenoh-pico/api/handlers.h b/include/zenoh-pico/api/handlers.h index 52e3f2ce4..c3342302a 100644 --- a/include/zenoh-pico/api/handlers.h +++ b/include/zenoh-pico/api/handlers.h @@ -145,22 +145,37 @@ extern "C" { /* elem_drop_f */ z_##item_name##_drop, \ /* elem_null */ z_internal_##item_name##_null) -#define _Z_CHANNEL_DEFINE_DUMMY(item_name, kind_name) \ - typedef struct { \ - uint8_t _foo; \ - } z_owned_##kind_name##_handler_##item_name##_t; \ - typedef struct { \ - uint8_t _foo; \ - } z_loaned_##kind_name##_handler_##item_name##_t; \ - typedef struct { \ - z_owned_##kind_name##_handler_##item_name##_t *_ptr; \ - } z_moved_##kind_name##_handler_##item_name##_t; \ - void *z_##kind_name##_handler_##item_name##_loan(void); \ - void *z_##kind_name##_handler_##item_name##_move(void); \ - void *z_##kind_name##_handler_##item_name##_drop(void); \ - void *z_##kind_name##_handler_##item_name##_recv(void); \ - void *z_##kind_name##_handler_##item_name##_take(void); \ - void *z_##kind_name##_handler_##item_name##_try_recv(void); +#define _Z_CHANNEL_DUMMY_IMPL(handler_type, handler_name, item_name) \ + _Z_OWNED_TYPE_VALUE(handler_type, handler_name) \ + static inline void _z_##handler_name##_clear(handler_type *handler) { _ZP_UNUSED(handler); } \ + static inline bool _z_##handler_name##_check(const handler_type *handler) { \ + _ZP_UNUSED(handler); \ + return false; \ + } \ + static inline handler_type _z_##handler_name##_null(void) { \ + handler_type h = {0}; \ + return h; \ + } \ + _Z_OWNED_FUNCTIONS_VALUE_NO_COPY_INLINE_IMPL(handler_type, handler_name, _z_##handler_name##_check, \ + _z_##handler_name##_null, _z_##handler_name##_clear) \ + static inline z_result_t z_##handler_name##_try_recv(const z_loaned_##handler_name##_t *handler, \ + z_owned_##item_name##_t *e) { \ + _ZP_UNUSED(handler); \ + _ZP_UNUSED(e); \ + return Z_CHANNEL_DISCONNECTED; \ + } \ + static inline z_result_t z_##handler_name##_recv(const z_loaned_##handler_name##_t *handler, \ + z_owned_##item_name##_t *e) { \ + _ZP_UNUSED(handler); \ + _ZP_UNUSED(e); \ + return Z_CHANNEL_DISCONNECTED; \ + } + +#define _Z_CHANNEL_DEFINE_DUMMY(item_name, kind_name) \ + typedef struct { \ + uint8_t _foo; \ + } _z_##kind_name##_handler_##item_name##_t; \ + _Z_CHANNEL_DUMMY_IMPL(_z_##kind_name##_handler_##item_name##_t, kind_name##_handler_##item_name, item_name) // This macro defines: // z_ring_channel_sample_new() diff --git a/include/zenoh-pico/api/macros.h b/include/zenoh-pico/api/macros.h index 0d1c9aea8..ca17781d0 100644 --- a/include/zenoh-pico/api/macros.h +++ b/include/zenoh-pico/api/macros.h @@ -545,8 +545,8 @@ inline void z_call(const z_loaned_closure_zid_t &closure, const z_id_t *zid) inline void z_closure( z_owned_closure_hello_t* closure, void (*call)(z_loaned_hello_t*, void*), - void (*drop)(void*) = NULL, - void *context = NULL) { + void (*drop)(void*), + void *context) { closure->_val.context = context; closure->_val.drop = drop; closure->_val.call = call; @@ -554,8 +554,8 @@ inline void z_closure( inline void z_closure( z_owned_closure_query_t* closure, void (*call)(z_loaned_query_t*, void*), - void (*drop)(void*) = NULL, - void *context = NULL) { + void (*drop)(void*), + void *context) { closure->_val.context = context; closure->_val.drop = drop; closure->_val.call = call; @@ -563,8 +563,8 @@ inline void z_closure( inline void z_closure( z_owned_closure_reply_t* closure, void (*call)(z_loaned_reply_t*, void*), - void (*drop)(void*) = NULL, - void *context = NULL) { + void (*drop)(void*), + void *context) { closure->_val.context = context; closure->_val.drop = drop; closure->_val.call = call; @@ -572,8 +572,8 @@ inline void z_closure( inline void z_closure( z_owned_closure_sample_t* closure, void (*call)(z_loaned_sample_t*, void*), - void (*drop)(void*) = NULL, - void *context = NULL) { + void (*drop)(void*), + void *context) { closure->_val.context = context; closure->_val.drop = drop; closure->_val.call = call; @@ -581,8 +581,8 @@ inline void z_closure( inline void z_closure( z_owned_closure_zid_t* closure, void (*call)(const z_id_t*, void*), - void (*drop)(void*) = NULL, - void *context = NULL) { + void (*drop)(void*), + void *context) { closure->_val.context = context; closure->_val.drop = drop; closure->_val.call = call; diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index a944149c6..b28f3ec6c 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -982,8 +982,8 @@ const z_loaned_keyexpr_t *z_query_keyexpr(const z_loaned_query_t *query); * Return: * ``0`` in case of success, negative error code otherwise */ -z_result_t z_closure_sample(z_owned_closure_sample_t *closure, z_sample_handler_t call, z_dropper_handler_t drop, - void *context); +z_result_t z_closure_sample(z_owned_closure_sample_t *closure, z_closure_sample_callback_t call, + z_closure_drop_callback_t drop, void *context); /** * Calls a sample closure. @@ -1007,8 +1007,8 @@ void z_closure_sample_call(const z_loaned_closure_sample_t *closure, z_loaned_sa * Return: * ``0`` in case of success, negative error code otherwise */ -z_result_t z_closure_query(z_owned_closure_query_t *closure, z_query_handler_t call, z_dropper_handler_t drop, - void *context); +z_result_t z_closure_query(z_owned_closure_query_t *closure, z_closure_query_callback_t call, + z_closure_drop_callback_t drop, void *context); /** * Calls a query closure. @@ -1032,8 +1032,8 @@ void z_closure_query_call(const z_loaned_closure_query_t *closure, z_loaned_quer * Return: * ``0`` in case of success, negative error code otherwise */ -z_result_t z_closure_reply(z_owned_closure_reply_t *closure, z_reply_handler_t call, z_dropper_handler_t drop, - void *context); +z_result_t z_closure_reply(z_owned_closure_reply_t *closure, z_closure_reply_callback_t call, + z_closure_drop_callback_t drop, void *context); /** * Calls a reply closure. @@ -1057,8 +1057,8 @@ void z_closure_reply_call(const z_loaned_closure_reply_t *closure, z_loaned_repl * Return: * ``0`` in case of success, negative error code otherwise */ -z_result_t z_closure_hello(z_owned_closure_hello_t *closure, z_loaned_hello_handler_t call, z_dropper_handler_t drop, - void *context); +z_result_t z_closure_hello(z_owned_closure_hello_t *closure, z_closure_hello_callback_t call, + z_closure_drop_callback_t drop, void *context); /** * Calls a hello closure. @@ -1074,7 +1074,7 @@ void z_closure_hello_call(const z_loaned_closure_hello_t *closure, z_loaned_hell * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Parameters: - * closure: Pointer to an uninitialized :c:type:`z_owned_closure_zit_t`. + * closure: Pointer to an uninitialized :c:type:`z_owned_closure_zid_t`. * call: Pointer to the callback function. ``context`` will be passed as its last argument. * drop: Pointer to the function that will free the callback state. ``context`` will be passed as its last argument. * context: Pointer to an arbitrary state. @@ -1082,7 +1082,8 @@ void z_closure_hello_call(const z_loaned_closure_hello_t *closure, z_loaned_hell * Return: * ``0`` in case of success, negative error code otherwise */ -z_result_t z_closure_zid(z_owned_closure_zid_t *closure, z_zid_handler_t call, z_dropper_handler_t drop, void *context); +z_result_t z_closure_zid(z_owned_closure_zid_t *closure, z_closure_zid_callback_t call, z_closure_drop_callback_t drop, + void *context); /** * Calls a zid closure. @@ -1706,6 +1707,7 @@ const z_loaned_sample_t *z_reply_ok(const z_loaned_reply_t *reply); */ const z_loaned_reply_err_t *z_reply_err(const z_loaned_reply_t *reply); +#ifdef Z_FEATURE_UNSTABLE_API /** * Gets the id of the zenoh instance that answered this Reply. * @@ -1716,7 +1718,9 @@ const z_loaned_reply_err_t *z_reply_err(const z_loaned_reply_t *reply); * `true` if id is present */ bool z_reply_replier_id(const z_loaned_reply_t *reply, z_id_t *out_id); -#endif +#endif // Z_FEATURE_UNSTABLE_API + +#endif // Z_FEATURE_QUERY == 1 #if Z_FEATURE_QUERYABLE == 1 /** @@ -2056,6 +2060,7 @@ z_result_t z_declare_background_subscriber(const z_loaned_session_t *zs, const z const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *subscriber); #endif +#ifdef Z_FEATURE_UNSTABLE_API #if Z_FEATURE_BATCHING == 1 /** * Activate the batching mechanism. @@ -2081,6 +2086,7 @@ z_result_t zp_batch_start(const z_loaned_session_t *zs); */ z_result_t zp_batch_stop(const z_loaned_session_t *zs); #endif +#endif /************* Multi Thread Tasks helpers **************/ /** diff --git a/include/zenoh-pico/api/serialization.h b/include/zenoh-pico/api/serialization.h index d6e579557..d8ff0d648 100644 --- a/include/zenoh-pico/api/serialization.h +++ b/include/zenoh-pico/api/serialization.h @@ -458,6 +458,7 @@ z_result_t ze_deserializer_deserialize_slice(ze_deserializer_t *deserializer, z_ /** * Serializes a null-terminated string and writes it into an underlying :c:type:`z_owned_bytes_t`. + * The string should be a valid UTF-8. * * Parameters: * serializer: A serializer instance. @@ -468,8 +469,23 @@ z_result_t ze_deserializer_deserialize_slice(ze_deserializer_t *deserializer, z_ */ z_result_t ze_serializer_serialize_str(ze_loaned_serializer_t *serializer, const char *val); +/** + * Serializes a substring and writes it into an underlying :c:type:`z_owned_bytes_t`. + * The substring should be a valid UTF-8. + * + * Parameters: + * serializer: A serializer instance. + * start: Pointer to the start of the substring to serialize. + * len: Length of the substring to serialize. + * + * Return: + * ``0`` if serialization is successful, ``negative value`` otherwise. + */ +z_result_t ze_serializer_serialize_substr(ze_loaned_serializer_t *serializer, const char *start, size_t len); + /** * Serializes a string and writes it into an underlying :c:type:`z_owned_bytes_t`. + * The string should be a valid UTF-8. * * Parameters: * serializer: A serializer instance. @@ -523,7 +539,7 @@ z_result_t ze_deserializer_deserialize_sequence_length(ze_deserializer_t *deseri * * Parameters: * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the serialized data. - * data: Pointer to the data to serialize. Ownership is transferred to the `bytes`. + * data: Pointer to the data to serialize. * len: Number of bytes to serialize. * * Return: @@ -534,6 +550,7 @@ z_result_t ze_serialize_buf(z_owned_bytes_t *bytes, const uint8_t *data, size_t /** * Serializes a string into a :c:type:`z_owned_bytes_t`. * + * The string should be a valid UTF-8. * Parameters: * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the serialized string. * s: Pointer to the string to serialize. @@ -545,16 +562,31 @@ z_result_t ze_serialize_string(z_owned_bytes_t *bytes, const z_loaned_string_t * /** * Serializes a null-terminated string into a :c:type:`z_owned_bytes_t`. + * The string should be a valid UTF-8. * * Parameters: * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the serialized string. - * value: Pointer to the string to serialize. Ownership is transferred to the `bytes`. + * value: Pointer to the string to serialize. * * Return: * ``0`` if serialization is successful, ``negative value`` otherwise. */ z_result_t ze_serialize_str(z_owned_bytes_t *bytes, const char *value); +/** + * Serializes a substring into a :c:type:`z_owned_bytes_t`. + * The substring should be a valid UTF-8. + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the serialized string. + * start: Pointer to the the start of string to serialize. + * len: Length of the substring to serialize. + * + * Return: + * ``0`` if serialization is successful, ``negative value`` otherwise. + */ +z_result_t ze_serialize_substr(z_owned_bytes_t *bytes, const char *start, size_t len); + /** * Serializes a slice into a :c:type:`z_owned_bytes_t`. * diff --git a/include/zenoh-pico/api/types.h b/include/zenoh-pico/api/types.h index 26c703161..fd89c4972 100644 --- a/include/zenoh-pico/api/types.h +++ b/include/zenoh-pico/api/types.h @@ -34,13 +34,6 @@ extern "C" { #endif -/** - * Represents a variable-length encoding unsigned integer. - * - * It is equivalent to the size of a ``size_t``. - */ -typedef _z_zint_t z_zint_t; - /** * Represents a Zenoh ID. * @@ -417,13 +410,13 @@ _Z_OWNED_TYPE_VALUE(_z_reply_t, reply) */ _Z_OWNED_TYPE_VALUE(_z_string_svec_t, string_array) -typedef void (*z_dropper_handler_t)(void *arg); -typedef _z_sample_handler_t z_sample_handler_t; +typedef void (*z_closure_drop_callback_t)(void *arg); +typedef _z_closure_sample_callback_t z_closure_sample_callback_t; typedef struct { void *context; - z_sample_handler_t call; - z_dropper_handler_t drop; + z_closure_sample_callback_t call; + z_closure_drop_callback_t drop; } _z_closure_sample_t; /** @@ -431,12 +424,12 @@ typedef struct { */ _Z_OWNED_TYPE_VALUE(_z_closure_sample_t, closure_sample) -typedef _z_query_handler_t z_query_handler_t; +typedef _z_closure_query_callback_t z_closure_query_callback_t; typedef struct { void *context; - z_query_handler_t call; - z_dropper_handler_t drop; + z_closure_query_callback_t call; + z_closure_drop_callback_t drop; } _z_closure_query_t; /** @@ -444,12 +437,12 @@ typedef struct { */ _Z_OWNED_TYPE_VALUE(_z_closure_query_t, closure_query) -typedef _z_reply_handler_t z_reply_handler_t; +typedef _z_closure_reply_callback_t z_closure_reply_callback_t; typedef struct { void *context; - z_reply_handler_t call; - z_dropper_handler_t drop; + z_closure_reply_callback_t call; + z_closure_drop_callback_t drop; } _z_closure_reply_t; /** @@ -457,12 +450,12 @@ typedef struct { */ _Z_OWNED_TYPE_VALUE(_z_closure_reply_t, closure_reply) -typedef void (*z_loaned_hello_handler_t)(z_loaned_hello_t *hello, void *arg); +typedef void (*z_closure_hello_callback_t)(z_loaned_hello_t *hello, void *arg); typedef struct { void *context; - z_loaned_hello_handler_t call; - z_dropper_handler_t drop; + z_closure_hello_callback_t call; + z_closure_drop_callback_t drop; } _z_closure_hello_t; /** @@ -470,12 +463,12 @@ typedef struct { */ _Z_OWNED_TYPE_VALUE(_z_closure_hello_t, closure_hello) -typedef void (*z_zid_handler_t)(const z_id_t *id, void *arg); +typedef void (*z_closure_zid_callback_t)(const z_id_t *id, void *arg); typedef struct { void *context; - z_zid_handler_t call; - z_dropper_handler_t drop; + z_closure_zid_callback_t call; + z_closure_drop_callback_t drop; } _z_closure_zid_t; /** diff --git a/include/zenoh-pico/collections/arc_slice.h b/include/zenoh-pico/collections/arc_slice.h index ebc21bb56..782373141 100644 --- a/include/zenoh-pico/collections/arc_slice.h +++ b/include/zenoh-pico/collections/arc_slice.h @@ -24,6 +24,10 @@ #include "slice.h" #include "zenoh-pico/system/platform_common.h" +#ifdef __cplusplus +extern "C" { +#endif + _Z_SIMPLE_REFCOUNT_DEFINE(_z_slice, _z_slice) /*-------- ArcSlice --------*/ @@ -53,4 +57,8 @@ z_result_t _z_arc_slice_copy(_z_arc_slice_t* dst, const _z_arc_slice_t* src); z_result_t _z_arc_slice_move(_z_arc_slice_t* dst, _z_arc_slice_t* src); z_result_t _z_arc_slice_drop(_z_arc_slice_t* s); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_ARC_SLICE_H */ diff --git a/include/zenoh-pico/collections/array.h b/include/zenoh-pico/collections/array.h index 0c08d9af2..b5d077433 100644 --- a/include/zenoh-pico/collections/array.h +++ b/include/zenoh-pico/collections/array.h @@ -19,6 +19,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Internal Array Macros ------------------*/ #define _Z_ARRAY_DEFINE(name, type) \ typedef struct { \ @@ -71,4 +75,8 @@ } \ } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_ARRAY_H */ diff --git a/include/zenoh-pico/collections/bytes.h b/include/zenoh-pico/collections/bytes.h index fa2ea573c..e452d8b4a 100644 --- a/include/zenoh-pico/collections/bytes.h +++ b/include/zenoh-pico/collections/bytes.h @@ -23,6 +23,10 @@ #include "vec.h" #include "zenoh-pico/protocol/iobuf.h" +#ifdef __cplusplus +extern "C" { +#endif + inline size_t _z_arc_slice_size(const _z_arc_slice_t *s) { (void)s; return sizeof(_z_arc_slice_t); @@ -96,4 +100,8 @@ void _z_bytes_writer_clear(_z_bytes_writer_t *writer); void _z_bytes_writer_move(_z_bytes_writer_t *dst, _z_bytes_writer_t *src); size_t _z_bytes_reader_remaining(const _z_bytes_reader_t *reader); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_BYTES_H */ diff --git a/include/zenoh-pico/collections/element.h b/include/zenoh-pico/collections/element.h index 7a435abb3..5657a63b9 100644 --- a/include/zenoh-pico/collections/element.h +++ b/include/zenoh-pico/collections/element.h @@ -21,6 +21,10 @@ #include "zenoh-pico/system/platform.h" #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- element functions --------*/ typedef size_t (*z_element_size_f)(void *e); typedef void (*z_element_clear_f)(void *e); @@ -75,4 +79,8 @@ static inline void _z_noop_move(void *dst, void *src) { _Z_ELEM_DEFINE(_z_noop, _z_noop_t, _z_noop_size, _z_noop_clear, _z_noop_copy, _z_noop_move) +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_ELEMENT_H */ diff --git a/include/zenoh-pico/collections/fifo.h b/include/zenoh-pico/collections/fifo.h index 3e36bb509..0f4a887ce 100644 --- a/include/zenoh-pico/collections/fifo.h +++ b/include/zenoh-pico/collections/fifo.h @@ -20,6 +20,10 @@ #include "zenoh-pico/collections/element.h" #include "zenoh-pico/collections/ring.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- Fifo Buffer --------*/ typedef struct { _z_ring_t _ring; @@ -60,4 +64,8 @@ void _z_fifo_free(_z_fifo_t **xs, z_element_free_f f_f); static inline void name##_fifo_clear(name##_fifo_t *r) { _z_fifo_clear(r, name##_elem_free); } \ static inline void name##_fifo_free(name##_fifo_t **r) { _z_fifo_free(r, name##_elem_free); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_FIFO_H */ diff --git a/include/zenoh-pico/collections/intmap.h b/include/zenoh-pico/collections/intmap.h index c897e2e50..136cf9772 100644 --- a/include/zenoh-pico/collections/intmap.h +++ b/include/zenoh-pico/collections/intmap.h @@ -22,6 +22,10 @@ #include "zenoh-pico/collections/list.h" #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- int-void map --------*/ #define _Z_DEFAULT_INT_MAP_CAPACITY 16 @@ -113,4 +117,8 @@ void _z_int_void_map_free(_z_int_void_map_t **map, z_element_free_f f); _z_int_void_map_free(m, name##_intmap_entry_elem_free); \ } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_INTMAP_H */ diff --git a/include/zenoh-pico/collections/lifo.h b/include/zenoh-pico/collections/lifo.h index cf696b994..b6142b05a 100644 --- a/include/zenoh-pico/collections/lifo.h +++ b/include/zenoh-pico/collections/lifo.h @@ -19,6 +19,10 @@ #include "zenoh-pico/collections/element.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- Ring Buffer --------*/ typedef struct { void **_val; @@ -61,4 +65,8 @@ void _z_lifo_free(_z_lifo_t **xs, z_element_free_f f_f); static inline void name##_lifo_clear(name##_lifo_t *r) { _z_lifo_clear(r, name##_elem_free); } \ static inline void name##_lifo_free(name##_lifo_t **r) { _z_lifo_free(r, name##_elem_free); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_LIFO_H */ diff --git a/include/zenoh-pico/collections/list.h b/include/zenoh-pico/collections/list.h index a779706f0..590d0f32d 100644 --- a/include/zenoh-pico/collections/list.h +++ b/include/zenoh-pico/collections/list.h @@ -20,6 +20,10 @@ #include "zenoh-pico/collections/element.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- Single-linked List --------*/ /** * A single-linked list. @@ -72,4 +76,8 @@ void _z_list_free(_z_list_t **xs, z_element_free_f f_f); static inline name##_list_t *name##_list_clone(name##_list_t *l) { return _z_list_clone(l, name##_elem_clone); } \ static inline void name##_list_free(name##_list_t **l) { _z_list_free(l, name##_elem_free); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_LIST_H */ diff --git a/include/zenoh-pico/collections/ring.h b/include/zenoh-pico/collections/ring.h index de8743e58..d1e26ec57 100644 --- a/include/zenoh-pico/collections/ring.h +++ b/include/zenoh-pico/collections/ring.h @@ -19,6 +19,10 @@ #include "zenoh-pico/collections/element.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- Ring Buffer --------*/ typedef struct { void **_val; @@ -65,4 +69,8 @@ void _z_ring_free(_z_ring_t **xs, z_element_free_f f_f); static inline void name##_ring_clear(name##_ring_t *r) { _z_ring_clear(r, name##_elem_free); } \ static inline void name##_ring_free(name##_ring_t **r) { _z_ring_free(r, name##_elem_free); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_RING_H */ diff --git a/include/zenoh-pico/collections/slice.h b/include/zenoh-pico/collections/slice.h index 58bc8d610..de0c5987a 100644 --- a/include/zenoh-pico/collections/slice.h +++ b/include/zenoh-pico/collections/slice.h @@ -21,6 +21,10 @@ #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { void (*deleter)(void *data, void *context); void *context; @@ -73,4 +77,8 @@ void _z_slice_clear(_z_slice_t *bs); void _z_slice_free(_z_slice_t **bs); bool _z_slice_is_alloced(const _z_slice_t *s); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_SLICE_H */ diff --git a/include/zenoh-pico/collections/string.h b/include/zenoh-pico/collections/string.h index 6291db854..78fc0e5e5 100644 --- a/include/zenoh-pico/collections/string.h +++ b/include/zenoh-pico/collections/string.h @@ -21,6 +21,10 @@ #include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/vec.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- str --------*/ typedef char *_z_str_t; @@ -95,12 +99,18 @@ void _z_string_clear(_z_string_t *s); void _z_string_free(_z_string_t **s); void _z_string_reset(_z_string_t *s); bool _z_string_equals(const _z_string_t *left, const _z_string_t *right); -_z_string_t _z_string_convert_bytes(const _z_slice_t *bs); +_z_string_t _z_string_convert_bytes_le(const _z_slice_t *bs); _z_string_t _z_string_preallocate(const size_t len); +char *_z_str_from_string_clone(const _z_string_t *str); + _Z_ELEM_DEFINE(_z_string, _z_string_t, _z_string_len, _z_string_clear, _z_string_copy, _z_string_move) _Z_SVEC_DEFINE(_z_string, _z_string_t) _Z_LIST_DEFINE(_z_string, _z_string_t) _Z_INT_MAP_DEFINE(_z_string, _z_string_t) +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_STRING_H */ diff --git a/include/zenoh-pico/collections/vec.h b/include/zenoh-pico/collections/vec.h index c3d9ff525..08ac8207d 100644 --- a/include/zenoh-pico/collections/vec.h +++ b/include/zenoh-pico/collections/vec.h @@ -19,6 +19,10 @@ #include "zenoh-pico/collections/element.h" +#ifdef __cplusplus +extern "C" { +#endif + /*-------- Dynamically allocated vector --------*/ /** * A dynamically allocated vector. Elements are stored as pointers. @@ -142,4 +146,8 @@ void _z_svec_release(_z_svec_t *v); static inline void name##_svec_release(name##_svec_t *v) { _z_svec_release(v); } \ static inline void name##_svec_free(name##_svec_t **v) { _z_svec_free(v, name##_elem_clear, sizeof(type)); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_VECTOR_H */ diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index 5b946505f..060afd51b 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -43,9 +43,9 @@ #define Z_FEATURE_ENCODING_VALUES 1 #define Z_FEATURE_TCP_NODELAY 1 #define Z_FEATURE_LOCAL_SUBSCRIBER 0 -#define Z_FEATURE_PUBLISHER_SESSION_CHECK 1 +#define Z_FEATURE_PUBLISHER_SESSION_CHECK 0 #define Z_FEATURE_BATCHING 1 -#define Z_FEATURE_RX_CACHE 0 +#define Z_FEATURE_RX_CACHE 1 // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/include/zenoh-pico/link/config/bt.h b/include/zenoh-pico/link/config/bt.h index 630b9ae41..fca0740d1 100644 --- a/include/zenoh-pico/link/config/bt.h +++ b/include/zenoh-pico/link/config/bt.h @@ -19,6 +19,10 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_BLUETOOTH == 1 #define BT_CONFIG_ARGC 3 @@ -50,4 +54,8 @@ z_result_t _z_bt_config_from_str(_z_str_intmap_t *strint, const char *s); z_result_t _z_bt_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_BT_H */ diff --git a/include/zenoh-pico/link/config/raweth.h b/include/zenoh-pico/link/config/raweth.h index c30cc6403..65700aaba 100644 --- a/include/zenoh-pico/link/config/raweth.h +++ b/include/zenoh-pico/link/config/raweth.h @@ -20,6 +20,10 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/link/link.h" +#ifdef __cplusplus +extern "C" { +#endif + #define RAWETH_SCHEMA "reth" z_result_t _z_endpoint_raweth_valid(_z_endpoint_t *endpoint); @@ -29,4 +33,8 @@ char *_z_raweth_config_to_str(const _z_str_intmap_t *s); z_result_t _z_raweth_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); z_result_t _z_raweth_config_from_str(_z_str_intmap_t *strint, const char *s); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_RAWETH_H */ diff --git a/include/zenoh-pico/link/config/serial.h b/include/zenoh-pico/link/config/serial.h index 6180d0a59..3b9f6530a 100644 --- a/include/zenoh-pico/link/config/serial.h +++ b/include/zenoh-pico/link/config/serial.h @@ -20,6 +20,10 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_SERIAL == 1 #define SERIAL_CONFIG_ARGC 1 @@ -66,4 +70,8 @@ z_result_t _z_serial_config_from_str(_z_str_intmap_t *strint, const char *s); z_result_t _z_serial_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_SERIAL_H */ diff --git a/include/zenoh-pico/link/config/tcp.h b/include/zenoh-pico/link/config/tcp.h index 51792c8ac..c521a1751 100644 --- a/include/zenoh-pico/link/config/tcp.h +++ b/include/zenoh-pico/link/config/tcp.h @@ -19,6 +19,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_TCP == 1 #define TCP_CONFIG_ARGC 1 @@ -40,4 +44,8 @@ z_result_t _z_tcp_config_from_str(_z_str_intmap_t *strint, const char *s); z_result_t _z_tcp_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_TCP_H */ diff --git a/include/zenoh-pico/link/config/udp.h b/include/zenoh-pico/link/config/udp.h index 8af8b5d47..87cd6655e 100644 --- a/include/zenoh-pico/link/config/udp.h +++ b/include/zenoh-pico/link/config/udp.h @@ -18,6 +18,10 @@ #include "zenoh-pico/collections/intmap.h" #include "zenoh-pico/collections/string.h" +#ifdef __cplusplus +extern "C" { +#endif + #define UDP_CONFIG_ARGC 3 #define UDP_CONFIG_IFACE_KEY 0x01 @@ -48,4 +52,8 @@ z_result_t _z_udp_config_from_str(_z_str_intmap_t *strint, const char *s); z_result_t _z_udp_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_UDP_H */ diff --git a/include/zenoh-pico/link/config/ws.h b/include/zenoh-pico/link/config/ws.h index e9c3e6be6..a845807c5 100644 --- a/include/zenoh-pico/link/config/ws.h +++ b/include/zenoh-pico/link/config/ws.h @@ -19,6 +19,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_WS == 1 #define WS_CONFIG_TOUT_KEY 0x01 @@ -39,4 +43,8 @@ z_result_t _z_ws_config_from_str(_z_str_intmap_t *strint, const char *s); z_result_t _z_ws_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_CONFIG_WS_H */ diff --git a/include/zenoh-pico/link/endpoint.h b/include/zenoh-pico/link/endpoint.h index 4003608e5..8aa03390e 100644 --- a/include/zenoh-pico/link/endpoint.h +++ b/include/zenoh-pico/link/endpoint.h @@ -21,6 +21,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Locator ------------------*/ #if Z_FEATURE_LINK_TCP == 1 #define TCP_SCHEMA "tcp" @@ -72,4 +76,8 @@ z_result_t _z_endpoint_from_string(_z_endpoint_t *ep, _z_string_t *s); void _z_endpoint_clear(_z_endpoint_t *ep); void _z_endpoint_free(_z_endpoint_t **ep); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_ENDPOINT_H */ diff --git a/include/zenoh-pico/link/link.h b/include/zenoh-pico/link/link.h index 6356af3cf..522721fe8 100644 --- a/include/zenoh-pico/link/link.h +++ b/include/zenoh-pico/link/link.h @@ -46,6 +46,10 @@ #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Link transport capability enum. * @@ -144,4 +148,8 @@ z_result_t _z_link_send_wbuf(const _z_link_t *zl, const _z_wbuf_t *wbf); size_t _z_link_recv_zbuf(const _z_link_t *zl, _z_zbuf_t *zbf, _z_slice_t *addr); size_t _z_link_recv_exact_zbuf(const _z_link_t *zl, _z_zbuf_t *zbf, size_t len, _z_slice_t *addr); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_H */ diff --git a/include/zenoh-pico/link/manager.h b/include/zenoh-pico/link/manager.h index d9e716ecc..43146ae01 100644 --- a/include/zenoh-pico/link/manager.h +++ b/include/zenoh-pico/link/manager.h @@ -19,6 +19,10 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/link/link.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_endpoint_tcp_valid(_z_endpoint_t *ep); z_result_t _z_new_link_tcp(_z_link_t *zl, _z_endpoint_t *ep); @@ -43,4 +47,8 @@ z_result_t _z_endpoint_ws_valid(_z_endpoint_t *ep); z_result_t _z_new_link_ws(_z_link_t *zl, _z_endpoint_t *ep); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LINK_MANAGER_H */ diff --git a/include/zenoh-pico/net/config.h b/include/zenoh-pico/net/config.h index fabc7415f..4977f1b5c 100644 --- a/include/zenoh-pico/net/config.h +++ b/include/zenoh-pico/net/config.h @@ -18,6 +18,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/utils/config.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Create an empty set of properties for zenoh-net session configuration. * @@ -50,4 +54,8 @@ z_result_t _z_config_default(_z_config_t *config); */ z_result_t _z_config_client(_z_config_t *config, const char *locator); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_CONFIG_NETAPI_H */ diff --git a/include/zenoh-pico/net/encoding.h b/include/zenoh-pico/net/encoding.h index 969f0c34e..79a678084 100644 --- a/include/zenoh-pico/net/encoding.h +++ b/include/zenoh-pico/net/encoding.h @@ -17,6 +17,10 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/collections/string.h" +#ifdef __cplusplus +extern "C" { +#endif + #define _Z_ENCODING_ID_DEFAULT 0 /** @@ -39,4 +43,8 @@ z_result_t _z_encoding_copy(_z_encoding_t *dst, const _z_encoding_t *src); void _z_encoding_move(_z_encoding_t *dst, _z_encoding_t *src); _z_encoding_t _z_encoding_steal(_z_encoding_t *val); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_ENCODING_NETAPI_H */ diff --git a/include/zenoh-pico/net/filtering.h b/include/zenoh-pico/net/filtering.h index 18023b66d..14461a322 100644 --- a/include/zenoh-pico/net/filtering.h +++ b/include/zenoh-pico/net/filtering.h @@ -20,6 +20,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef enum { WRITE_FILTER_INIT = 0, WRITE_FILTER_ACTIVE = 1, @@ -45,4 +49,8 @@ z_result_t _z_write_filter_create(_z_publisher_t *pub); z_result_t _z_write_filter_destroy(_z_publisher_t *pub); bool _z_write_filter_active(const _z_publisher_t *pub); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_FILTERING_NETAPI_H */ diff --git a/include/zenoh-pico/net/logger.h b/include/zenoh-pico/net/logger.h index 73a4bede1..b9bbede1a 100644 --- a/include/zenoh-pico/net/logger.h +++ b/include/zenoh-pico/net/logger.h @@ -15,9 +15,17 @@ #ifndef ZENOH_PICO_LOGGER_NETAPI_H #define ZENOH_PICO_LOGGER_NETAPI_H +#ifdef __cplusplus +extern "C" { +#endif + /** * Initialise the zenoh runtime logger */ void _z_init_logger(void); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_LOGGER_NETAPI_H */ diff --git a/include/zenoh-pico/net/primitives.h b/include/zenoh-pico/net/primitives.h index f5a27034a..95b47078b 100644 --- a/include/zenoh-pico/net/primitives.h +++ b/include/zenoh-pico/net/primitives.h @@ -26,6 +26,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/utils/config.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Discovery ------------------*/ /** @@ -38,7 +42,7 @@ * timeout: The time that should be spent scouting before returning the results. */ void _z_scout(const z_what_t what, const _z_id_t zid, _z_string_t *locator, const uint32_t timeout, - _z_hello_handler_t callback, void *arg_call, _z_drop_handler_t dropper, void *arg_drop); + _z_closure_hello_callback_t callback, void *arg_call, _z_drop_handler_t dropper, void *arg_drop); /*------------------ Declarations ------------------*/ @@ -144,8 +148,8 @@ z_result_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, _z_bytes_t pay * Returns: * The created :c:type:`_z_subscriber_t` (in null state if the declaration failed). */ -_z_subscriber_t _z_declare_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, _z_sample_handler_t callback, - _z_drop_handler_t dropper, void *arg); +_z_subscriber_t _z_declare_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, + _z_closure_sample_callback_t callback, _z_drop_handler_t dropper, void *arg); /** * Undeclare a :c:type:`_z_subscriber_t`. @@ -175,7 +179,7 @@ z_result_t _z_undeclare_subscriber(_z_subscriber_t *sub); * The created :c:type:`_z_queryable_t` (in null state if the declaration failed).. */ _z_queryable_t _z_declare_queryable(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, bool complete, - _z_query_handler_t callback, _z_drop_handler_t dropper, void *arg); + _z_closure_query_callback_t callback, _z_drop_handler_t dropper, void *arg); /** * Undeclare a :c:type:`_z_queryable_t`. @@ -245,9 +249,10 @@ z_result_t _z_send_reply_err(const _z_query_t *query, const _z_session_rc_t *zsr * */ z_result_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *parameters, const z_query_target_t target, - const z_consolidation_mode_t consolidation, const _z_value_t value, _z_reply_handler_t callback, - _z_drop_handler_t dropper, void *arg, uint64_t timeout_ms, const _z_bytes_t attachment, - z_congestion_control_t cong_ctrl, z_priority_t priority, bool is_express); + const z_consolidation_mode_t consolidation, const _z_value_t value, + _z_closure_reply_callback_t callback, _z_drop_handler_t dropper, void *arg, uint64_t timeout_ms, + const _z_bytes_t attachment, z_congestion_control_t cong_ctrl, z_priority_t priority, + bool is_express); #endif #if Z_FEATURE_INTEREST == 1 @@ -256,4 +261,8 @@ uint32_t _z_add_interest(_z_session_t *zn, _z_keyexpr_t keyexpr, _z_interest_han z_result_t _z_remove_interest(_z_session_t *zn, uint32_t interest_id); #endif +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_NET_PRIMITIVES_H */ diff --git a/include/zenoh-pico/net/publish.h b/include/zenoh-pico/net/publish.h index b3bc40891..b270f4eb3 100644 --- a/include/zenoh-pico/net/publish.h +++ b/include/zenoh-pico/net/publish.h @@ -19,6 +19,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Return type when declaring a publisher. */ @@ -44,4 +48,8 @@ void _z_publisher_clear(_z_publisher_t *pub); void _z_publisher_free(_z_publisher_t **pub); #endif +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_NET_PUBLISH_H */ diff --git a/include/zenoh-pico/net/query.h b/include/zenoh-pico/net/query.h index 4cf60a4f7..82dbe9d8c 100644 --- a/include/zenoh-pico/net/query.h +++ b/include/zenoh-pico/net/query.h @@ -21,6 +21,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * The query to be answered by a queryable. */ @@ -74,4 +78,8 @@ void _z_queryable_free(_z_queryable_t **qbl); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_QUERY_NETAPI_H */ diff --git a/include/zenoh-pico/net/reply.h b/include/zenoh-pico/net/reply.h index f352be9a1..17008c14e 100644 --- a/include/zenoh-pico/net/reply.h +++ b/include/zenoh-pico/net/reply.h @@ -23,6 +23,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/session/session.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Reply tag values. * @@ -113,4 +117,8 @@ void _z_pending_reply_clear(_z_pending_reply_t *res); _Z_ELEM_DEFINE(_z_pending_reply, _z_pending_reply_t, _z_noop_size, _z_pending_reply_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_pending_reply, _z_pending_reply_t) +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_REPLY_NETAPI_H */ diff --git a/include/zenoh-pico/net/sample.h b/include/zenoh-pico/net/sample.h index 718fe95da..1a93909dc 100644 --- a/include/zenoh-pico/net/sample.h +++ b/include/zenoh-pico/net/sample.h @@ -18,6 +18,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/session/session.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * A zenoh-net data sample. * @@ -74,4 +78,7 @@ void _z_sample_free(_z_sample_t **sample); z_result_t _z_sample_copy(_z_sample_t *dst, const _z_sample_t *src); _z_sample_t _z_sample_duplicate(const _z_sample_t *src); +#ifdef __cplusplus +} +#endif #endif /* ZENOH_PICO_SAMPLE_NETAPI_H */ diff --git a/include/zenoh-pico/net/session.h b/include/zenoh-pico/net/session.h index 5362c1921..1d3d1e6a5 100644 --- a/include/zenoh-pico/net/session.h +++ b/include/zenoh-pico/net/session.h @@ -26,6 +26,10 @@ #include "zenoh-pico/session/subscription.h" #include "zenoh-pico/utils/config.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * A zenoh-net session. */ @@ -207,4 +211,8 @@ z_result_t _zp_start_lease_task(_z_session_t *z, z_task_attr_t *attr); z_result_t _zp_stop_lease_task(_z_session_t *z); #endif // Z_FEATURE_MULTI_THREAD == 1 +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_NET_SESSION_H */ diff --git a/include/zenoh-pico/net/subscribe.h b/include/zenoh-pico/net/subscribe.h index b8129673e..2357a0c8a 100644 --- a/include/zenoh-pico/net/subscribe.h +++ b/include/zenoh-pico/net/subscribe.h @@ -20,6 +20,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Return type when declaring a subscriber. */ @@ -37,4 +41,8 @@ void _z_subscriber_free(_z_subscriber_t **sub); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SUBSCRIBE_NETAPI_H */ diff --git a/include/zenoh-pico/protocol/codec/core.h b/include/zenoh-pico/protocol/codec/core.h index 16cdef966..db0acee39 100644 --- a/include/zenoh-pico/protocol/codec/core.h +++ b/include/zenoh-pico/protocol/codec/core.h @@ -24,6 +24,10 @@ #include "zenoh-pico/utils/config.h" #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef z_result_t (*__z_single_byte_reader_t)(uint8_t *, void *context); /*------------------ Internal Zenoh-net Macros ------------------*/ z_result_t _z_consolidation_mode_encode(_z_wbuf_t *wbf, z_consolidation_mode_t en); @@ -84,4 +88,8 @@ z_result_t _z_timestamp_encode(_z_wbuf_t *buf, const _z_timestamp_t *ts); z_result_t _z_timestamp_encode_ext(_z_wbuf_t *buf, const _z_timestamp_t *ts); z_result_t _z_timestamp_decode(_z_timestamp_t *ts, _z_zbuf_t *buf); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_CORE_H */ diff --git a/include/zenoh-pico/protocol/codec/declarations.h b/include/zenoh-pico/protocol/codec/declarations.h index 86efb1a64..840061d92 100644 --- a/include/zenoh-pico/protocol/codec/declarations.h +++ b/include/zenoh-pico/protocol/codec/declarations.h @@ -17,6 +17,11 @@ #include "zenoh-pico/protocol/definitions/declarations.h" #include "zenoh-pico/protocol/iobuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + #define _Z_DECL_KEXPR_MID 0 #define _Z_DECL_KEXPR_FLAG_N 0x20 #define _Z_UNDECL_KEXPR_MID 1 @@ -50,4 +55,8 @@ z_result_t _z_undecl_token_decode(_z_undecl_token_t *decl, _z_zbuf_t *zbf, uint8 z_result_t _z_declaration_encode(_z_wbuf_t *wbf, const _z_declaration_t *decl); z_result_t _z_declaration_decode(_z_declaration_t *decl, _z_zbuf_t *zbf); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_DECLARATIONS_H */ diff --git a/include/zenoh-pico/protocol/codec/ext.h b/include/zenoh-pico/protocol/codec/ext.h index 7efd7063e..cc339dd0d 100644 --- a/include/zenoh-pico/protocol/codec/ext.h +++ b/include/zenoh-pico/protocol/codec/ext.h @@ -21,6 +21,10 @@ #include "zenoh-pico/protocol/ext.h" #include "zenoh-pico/protocol/iobuf.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Message Extension ------------------*/ z_result_t _z_msg_ext_encode(_z_wbuf_t *wbf, const _z_msg_ext_t *ext, bool has_next); z_result_t _z_msg_ext_decode(_z_msg_ext_t *ext, _z_zbuf_t *zbf, bool *has_next); @@ -66,4 +70,8 @@ z_result_t _z_msg_ext_encode_zbuf(_z_wbuf_t *wbf, const _z_msg_ext_zbuf_t *pld); z_result_t _z_msg_ext_decode_zbuf(_z_msg_ext_zbuf_t *pld, _z_zbuf_t *zbf); z_result_t _z_msg_ext_decode_zbuf_na(_z_msg_ext_zbuf_t *pld, _z_zbuf_t *zbf); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TEST_H */ diff --git a/include/zenoh-pico/protocol/codec/interest.h b/include/zenoh-pico/protocol/codec/interest.h index 4e8aa4921..b8781efbe 100644 --- a/include/zenoh-pico/protocol/codec/interest.h +++ b/include/zenoh-pico/protocol/codec/interest.h @@ -18,7 +18,15 @@ #include "zenoh-pico/protocol/definitions/interest.h" #include "zenoh-pico/protocol/iobuf.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_interest_encode(_z_wbuf_t *wbf, const _z_interest_t *interest, bool is_final); z_result_t _z_interest_decode(_z_interest_t *decl, _z_zbuf_t *zbf, bool is_final, bool has_ext); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_DECLARATIONS_H */ diff --git a/include/zenoh-pico/protocol/codec/message.h b/include/zenoh-pico/protocol/codec/message.h index b2d5c625c..c877ea884 100644 --- a/include/zenoh-pico/protocol/codec/message.h +++ b/include/zenoh-pico/protocol/codec/message.h @@ -18,6 +18,10 @@ #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/iobuf.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb); z_result_t _z_push_body_decode(_z_push_body_t *body, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); @@ -36,4 +40,8 @@ z_result_t _z_put_decode(_z_msg_put_t *put, _z_zbuf_t *zbf, uint8_t header, _z_a z_result_t _z_del_encode(_z_wbuf_t *wbf, const _z_msg_del_t *del); z_result_t _z_del_decode(_z_msg_del_t *del, _z_zbuf_t *zbf, uint8_t header); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_MESSAGE_H */ diff --git a/include/zenoh-pico/protocol/codec/network.h b/include/zenoh-pico/protocol/codec/network.h index e3bce1f14..661ee9de2 100644 --- a/include/zenoh-pico/protocol/codec/network.h +++ b/include/zenoh-pico/protocol/codec/network.h @@ -19,6 +19,11 @@ #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/iobuf.h" + +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_push_encode(_z_wbuf_t *wbf, const _z_n_msg_push_t *msg); z_result_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header, _z_arc_slice_t *arcs); z_result_t _z_request_encode(_z_wbuf_t *wbf, const _z_n_msg_request_t *msg); @@ -35,4 +40,8 @@ z_result_t _z_n_interest_decode(_z_n_msg_interest_t *interest, _z_zbuf_t *zbf, u z_result_t _z_network_message_encode(_z_wbuf_t *wbf, const _z_network_message_t *msg); z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf, _z_arc_slice_t *arcs); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_NETWORK_H */ diff --git a/include/zenoh-pico/protocol/codec/transport.h b/include/zenoh-pico/protocol/codec/transport.h index 4a83857b1..eee9feb47 100644 --- a/include/zenoh-pico/protocol/codec/transport.h +++ b/include/zenoh-pico/protocol/codec/transport.h @@ -18,6 +18,10 @@ #include "zenoh-pico/protocol/definitions/transport.h" #include "zenoh-pico/protocol/iobuf.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_scouting_message_encode(_z_wbuf_t *buf, const _z_scouting_message_t *msg); z_result_t _z_scouting_message_decode(_z_scouting_message_t *msg, _z_zbuf_t *buf); @@ -47,4 +51,8 @@ z_result_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header z_result_t _z_fragment_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_fragment_t *msg); z_result_t _z_fragment_decode(_z_t_msg_fragment_t *msg, _z_zbuf_t *zbf, uint8_t header); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_TRANSPORT_H */ diff --git a/include/zenoh-pico/protocol/core.h b/include/zenoh-pico/protocol/core.h index c793656bd..7a9a79efb 100644 --- a/include/zenoh-pico/protocol/core.h +++ b/include/zenoh-pico/protocol/core.h @@ -29,6 +29,10 @@ #include "zenoh-pico/net/encoding.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #define _Z_OPTIONAL #define _Z_MOVE(x) x * @@ -225,4 +229,8 @@ typedef struct { uint32_t _entity_id; } _z_reply_context_t; +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CORE_H */ diff --git a/include/zenoh-pico/protocol/definitions/declarations.h b/include/zenoh-pico/protocol/definitions/declarations.h index cb8224239..35c5e3a8e 100644 --- a/include/zenoh-pico/protocol/definitions/declarations.h +++ b/include/zenoh-pico/protocol/definitions/declarations.h @@ -20,6 +20,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/keyexpr.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { uint16_t _id; _z_keyexpr_t _keyexpr; @@ -122,4 +126,8 @@ _z_declaration_t _z_make_undecl_token(uint32_t id, _Z_OPTIONAL const _z_keyexpr_ _z_declaration_t _z_make_decl_final(void); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_DECLARATIONS_H */ diff --git a/include/zenoh-pico/protocol/definitions/interest.h b/include/zenoh-pico/protocol/definitions/interest.h index 8479f090f..46a9ac7a3 100644 --- a/include/zenoh-pico/protocol/definitions/interest.h +++ b/include/zenoh-pico/protocol/definitions/interest.h @@ -20,6 +20,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/keyexpr.h" +#ifdef __cplusplus +extern "C" { +#endif + #define _Z_INTEREST_FLAG_KEYEXPRS (1) #define _Z_INTEREST_FLAG_SUBSCRIBERS (1 << 1) #define _Z_INTEREST_FLAG_QUERYABLES (1 << 2) @@ -43,4 +47,8 @@ void _z_interest_clear(_z_interest_t* decl); _z_interest_t _z_make_interest(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, uint8_t flags); _z_interest_t _z_make_interest_final(uint32_t id); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_INTEREST_H */ diff --git a/include/zenoh-pico/protocol/definitions/message.h b/include/zenoh-pico/protocol/definitions/message.h index 5d43defa4..2cfa93cd3 100644 --- a/include/zenoh-pico/protocol/definitions/message.h +++ b/include/zenoh-pico/protocol/definitions/message.h @@ -18,6 +18,11 @@ #include "zenoh-pico/net/encoding.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/core.h" + +#ifdef __cplusplus +extern "C" { +#endif + /* Zenoh Messages */ #define _Z_MID_Z_OAM 0x00 #define _Z_MID_Z_PUT 0x01 @@ -140,4 +145,8 @@ typedef struct { void _z_msg_reply_clear(_z_msg_reply_t *msg); #define _Z_FLAG_Z_R_C 0x20 +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_MESSAGE_H */ diff --git a/include/zenoh-pico/protocol/definitions/network.h b/include/zenoh-pico/protocol/definitions/network.h index 24d86102c..f828d48f1 100644 --- a/include/zenoh-pico/protocol/definitions/network.h +++ b/include/zenoh-pico/protocol/definitions/network.h @@ -25,6 +25,11 @@ #include "zenoh-pico/protocol/definitions/message.h" #include "zenoh-pico/protocol/ext.h" #include "zenoh-pico/protocol/keyexpr.h" + +#ifdef __cplusplus +extern "C" { +#endif + /* Network Messages */ #define _Z_MID_N_OAM 0x1f #define _Z_MID_N_DECLARE 0x1e @@ -304,4 +309,8 @@ _z_network_message_t _z_n_msg_make_push(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_pu _z_network_message_t _z_n_msg_make_interest(_z_interest_t interest); z_result_t _z_n_msg_copy(_z_network_message_t *dst, const _z_network_message_t *src); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_NETWORK_H */ diff --git a/include/zenoh-pico/protocol/definitions/transport.h b/include/zenoh-pico/protocol/definitions/transport.h index d2d6ae726..046cd815b 100644 --- a/include/zenoh-pico/protocol/definitions/transport.h +++ b/include/zenoh-pico/protocol/definitions/transport.h @@ -21,6 +21,10 @@ #include "zenoh-pico/link/endpoint.h" #include "zenoh-pico/protocol/definitions/network.h" +#ifdef __cplusplus +extern "C" { +#endif + #define _Z_MID_SCOUT 0x01 #define _Z_MID_HELLO 0x02 @@ -541,4 +545,8 @@ void _z_s_msg_copy(_z_scouting_message_t *clone, _z_scouting_message_t *msg); void _z_s_msg_copy_scout(_z_s_msg_scout_t *clone, _z_s_msg_scout_t *msg); void _z_s_msg_copy_hello(_z_s_msg_hello_t *clone, _z_s_msg_hello_t *msg); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_TRANSPORT_H */ diff --git a/include/zenoh-pico/protocol/ext.h b/include/zenoh-pico/protocol/ext.h index 3ec4198bb..989d7491d 100644 --- a/include/zenoh-pico/protocol/ext.h +++ b/include/zenoh-pico/protocol/ext.h @@ -20,6 +20,10 @@ #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + /*=============================*/ /* Message header */ /*=============================*/ @@ -99,4 +103,8 @@ void _z_msg_ext_copy_zbuf(_z_msg_ext_zbuf_t *clone, const _z_msg_ext_zbuf_t *ext _Z_ELEM_DEFINE(_z_msg_ext, _z_msg_ext_t, _z_noop_size, _z_msg_ext_clear, _z_msg_ext_copy, _z_noop_move) _Z_VEC_DEFINE(_z_msg_ext, _z_msg_ext_t) +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_PROTOCOL_EXTENSION_H */ diff --git a/include/zenoh-pico/protocol/iobuf.h b/include/zenoh-pico/protocol/iobuf.h index f2617b897..bea659d34 100644 --- a/include/zenoh-pico/protocol/iobuf.h +++ b/include/zenoh-pico/protocol/iobuf.h @@ -24,6 +24,10 @@ #include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/vec.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ IOSli ------------------*/ typedef struct { @@ -139,4 +143,8 @@ void _z_wbuf_reset(_z_wbuf_t *wbf); void _z_wbuf_clear(_z_wbuf_t *wbf); void _z_wbuf_free(_z_wbuf_t **wbf); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_PROTOCOL_IOBUF_H */ diff --git a/include/zenoh-pico/protocol/keyexpr.h b/include/zenoh-pico/protocol/keyexpr.h index 61a16e634..0c347c251 100644 --- a/include/zenoh-pico/protocol/keyexpr.h +++ b/include/zenoh-pico/protocol/keyexpr.h @@ -19,6 +19,10 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + zp_keyexpr_canon_status_t _z_keyexpr_is_canon(const char *start, size_t len); zp_keyexpr_canon_status_t _z_keyexpr_canonize(char *start, size_t *len); bool _z_keyexpr_suffix_includes(const _z_keyexpr_t *left, const _z_keyexpr_t *right); @@ -50,4 +54,8 @@ void _z_keyexpr_move(_z_keyexpr_t *dst, _z_keyexpr_t *src); void _z_keyexpr_clear(_z_keyexpr_t *rk); void _z_keyexpr_free(_z_keyexpr_t **rk); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_KEYEXPR_H */ diff --git a/include/zenoh-pico/session/interest.h b/include/zenoh-pico/session/interest.h index 3e1f6d4da..d8792ca77 100644 --- a/include/zenoh-pico/session/interest.h +++ b/include/zenoh-pico/session/interest.h @@ -19,6 +19,10 @@ #include "zenoh-pico/net/session.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_INTEREST == 1 _z_session_interest_rc_t *_z_get_interest_by_id(_z_session_t *zn, const _z_zint_t id); _z_session_interest_rc_t *_z_register_interest(_z_session_t *zn, _z_session_interest_t *intr); @@ -32,4 +36,8 @@ z_result_t _z_interest_process_declare_final(_z_session_t *zn, uint32_t id); z_result_t _z_interest_process_interest_final(_z_session_t *zn, uint32_t id); z_result_t _z_interest_process_interest(_z_session_t *zn, _z_keyexpr_t key, uint32_t id, uint8_t flags); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SESSION_INTEREST_H */ diff --git a/include/zenoh-pico/session/push.h b/include/zenoh-pico/session/push.h index 5c774b704..49da5bf21 100644 --- a/include/zenoh-pico/session/push.h +++ b/include/zenoh-pico/session/push.h @@ -21,6 +21,14 @@ #ifndef ZENOH_PICO_SESSION_PUSH_H #define ZENOH_PICO_SESSION_PUSH_H +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_trigger_push(_z_session_t *zn, _z_n_msg_push_t *push, z_reliability_t reliability); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SESSION_PUSH_H */ diff --git a/include/zenoh-pico/session/query.h b/include/zenoh-pico/session/query.h index c1267e348..f7a671a05 100644 --- a/include/zenoh-pico/session/query.h +++ b/include/zenoh-pico/session/query.h @@ -18,6 +18,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + void _z_pending_query_process_timeout(_z_session_t *zn); #if Z_FEATURE_QUERY == 1 @@ -35,4 +39,8 @@ void _z_unregister_pending_query(_z_session_t *zn, _z_pending_query_t *pq); void _z_flush_pending_queries(_z_session_t *zn); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SESSION_QUERY_H */ diff --git a/include/zenoh-pico/session/queryable.h b/include/zenoh-pico/session/queryable.h index 6e8e8eeed..684880c17 100644 --- a/include/zenoh-pico/session/queryable.h +++ b/include/zenoh-pico/session/queryable.h @@ -24,7 +24,7 @@ typedef struct _z_session_rc_t _z_session_rc_t; // Queryable infos typedef struct { - _z_query_handler_t callback; + _z_closure_query_callback_t callback; void *arg; } _z_queryable_infos_t; diff --git a/include/zenoh-pico/session/reply.h b/include/zenoh-pico/session/reply.h index 083fed40f..b2aea9e5c 100644 --- a/include/zenoh-pico/session/reply.h +++ b/include/zenoh-pico/session/reply.h @@ -19,6 +19,10 @@ #include "zenoh-pico/protocol/definitions/message.h" #include "zenoh-pico/protocol/definitions/network.h" +#ifdef __cplusplus +extern "C" { +#endif + #ifndef ZENOH_PICO_SESSION_REPLY_H #define ZENOH_PICO_SESSION_REPLY_H @@ -28,4 +32,8 @@ z_result_t _z_trigger_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *er z_result_t _z_trigger_reply_final(_z_session_t *zn, _z_n_msg_response_final_t *final); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SESSION_REPLY_H */ diff --git a/include/zenoh-pico/session/resource.h b/include/zenoh-pico/session/resource.h index e1d9c1c62..61af9989b 100644 --- a/include/zenoh-pico/session/resource.h +++ b/include/zenoh-pico/session/resource.h @@ -19,6 +19,10 @@ #include "zenoh-pico/net/session.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Entity ------------------*/ uint32_t _z_get_entity_id(_z_session_t *zn); @@ -36,4 +40,8 @@ _z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_key _z_resource_t *__unsafe_z_get_resource_by_id(_z_session_t *zn, uint16_t mapping, _z_zint_t id); _z_resource_t *__unsafe_z_get_resource_matching_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_SESSION_RESOURCE_H */ diff --git a/include/zenoh-pico/session/session.h b/include/zenoh-pico/session/session.h index 6296ad1f1..e1a39584e 100644 --- a/include/zenoh-pico/session/session.h +++ b/include/zenoh-pico/session/session.h @@ -26,6 +26,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/transport/manager.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * The callback signature of the cleanup functions. */ @@ -54,13 +58,13 @@ typedef struct _z_sample_t _z_sample_t; /** * The callback signature of the functions handling data messages. */ -typedef void (*_z_sample_handler_t)(_z_sample_t *sample, void *arg); +typedef void (*_z_closure_sample_callback_t)(_z_sample_t *sample, void *arg); typedef struct { _z_keyexpr_t _key; uint16_t _key_id; uint32_t _id; - _z_sample_handler_t _callback; + _z_closure_sample_callback_t _callback; _z_drop_handler_t _dropper; void *_arg; } _z_subscription_t; @@ -85,12 +89,12 @@ typedef struct _z_query_t _z_query_t; /** * The callback signature of the functions handling query messages. */ -typedef void (*_z_query_handler_t)(_z_query_t *query, void *arg); +typedef void (*_z_closure_query_callback_t)(_z_query_t *query, void *arg); typedef struct { _z_keyexpr_t _key; uint32_t _id; - _z_query_handler_t _callback; + _z_closure_query_callback_t _callback; _z_drop_handler_t _dropper; void *_arg; bool _complete; @@ -115,12 +119,12 @@ typedef struct _z_reply_t _z_reply_t; /** * The callback signature of the functions handling query replies. */ -typedef void (*_z_reply_handler_t)(_z_reply_t *reply, void *arg); +typedef void (*_z_closure_reply_callback_t)(_z_reply_t *reply, void *arg); typedef struct { _z_keyexpr_t _key; _z_zint_t _id; - _z_reply_handler_t _callback; + _z_closure_reply_callback_t _callback; _z_drop_handler_t _dropper; z_clock_t _start_time; uint64_t _timeout; @@ -145,11 +149,11 @@ typedef struct { _z_reply_data_list_t *_replies; } _z_pending_query_collect_t; -struct __z_hello_handler_wrapper_t; // Forward declaration to be used in _z_hello_handler_t +struct __z_hello_handler_wrapper_t; // Forward declaration to be used in _z_closure_hello_callback_t /** * The callback signature of the functions handling hello messages. */ -typedef void (*_z_hello_handler_t)(_z_hello_t *hello, struct __z_hello_handler_wrapper_t *arg); +typedef void (*_z_closure_hello_callback_t)(_z_hello_t *hello, struct __z_hello_handler_wrapper_t *arg); z_result_t _z_session_generate_zid(_z_id_t *bs, uint8_t size); @@ -207,4 +211,8 @@ void _z_declare_data_clear(_z_declare_data_t *data); _Z_ELEM_DEFINE(_z_declare_data, _z_declare_data_t, _z_noop_size, _z_declare_data_clear, _z_noop_copy, _z_noop_move) _Z_LIST_DEFINE(_z_declare_data, _z_declare_data_t) +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_SESSION_SESSION_H */ diff --git a/include/zenoh-pico/session/subscription.h b/include/zenoh-pico/session/subscription.h index 852e6cd9d..a103b0c21 100644 --- a/include/zenoh-pico/session/subscription.h +++ b/include/zenoh-pico/session/subscription.h @@ -24,7 +24,7 @@ typedef struct _z_session_t _z_session_t; // Subscription infos typedef struct { - _z_sample_handler_t callback; + _z_closure_sample_callback_t callback; void *arg; } _z_subscription_infos_t; @@ -38,6 +38,10 @@ typedef struct { size_t sub_nb; } _z_subscription_cache_t; +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Subscription ------------------*/ void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, @@ -58,4 +62,8 @@ void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscript void _z_flush_subscriptions(_z_session_t *zn); #endif +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_SESSION_SUBSCRIPTION_H */ diff --git a/include/zenoh-pico/session/utils.h b/include/zenoh-pico/session/utils.h index 6d8c381b2..44c48ff91 100644 --- a/include/zenoh-pico/session/utils.h +++ b/include/zenoh-pico/session/utils.h @@ -22,6 +22,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Session ------------------*/ _z_hello_list_t *_z_scout_inner(const z_what_t what, _z_id_t id, _z_string_t *locator, const uint32_t timeout, const bool exit_on_first); @@ -40,4 +44,8 @@ static inline void _z_session_mutex_lock(_z_session_t *zn) { _ZP_UNUSED(zn); } static inline void _z_session_mutex_unlock(_z_session_t *zn) { _ZP_UNUSED(zn); } #endif +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_SESSION_UTILS_H */ diff --git a/include/zenoh-pico/system/link/raweth.h b/include/zenoh-pico/system/link/raweth.h index c9c58381e..b1fa878fe 100644 --- a/include/zenoh-pico/system/link/raweth.h +++ b/include/zenoh-pico/system/link/raweth.h @@ -21,6 +21,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_RAWETH_TRANSPORT == 1 // Ethernet types (big endian) @@ -93,4 +97,8 @@ uint16_t _z_raweth_htons(uint16_t val); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_LINK_RAWETH_H */ diff --git a/include/zenoh-pico/system/link/serial.h b/include/zenoh-pico/system/link/serial.h index 21d832c65..21679d996 100644 --- a/include/zenoh-pico/system/link/serial.h +++ b/include/zenoh-pico/system/link/serial.h @@ -21,6 +21,10 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_SERIAL == 1 #define _Z_SERIAL_MTU_SIZE 1500 @@ -43,4 +47,8 @@ size_t _z_send_serial(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_LINK_BT_H */ diff --git a/include/zenoh-pico/system/link/tcp.h b/include/zenoh-pico/system/link/tcp.h index 22bdc3efc..c6dcd7032 100644 --- a/include/zenoh-pico/system/link/tcp.h +++ b/include/zenoh-pico/system/link/tcp.h @@ -20,6 +20,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_TCP == 1 typedef struct { @@ -38,4 +42,8 @@ size_t _z_read_tcp(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len); size_t _z_send_tcp(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t len); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_LINK_TCP_H */ diff --git a/include/zenoh-pico/system/link/udp.h b/include/zenoh-pico/system/link/udp.h index 47899c04a..a0eb9cb01 100644 --- a/include/zenoh-pico/system/link/udp.h +++ b/include/zenoh-pico/system/link/udp.h @@ -20,6 +20,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_UDP_UNICAST == 1 || Z_FEATURE_LINK_UDP_MULTICAST == 1 typedef struct { @@ -56,4 +60,8 @@ size_t _z_send_udp_multicast(const _z_sys_net_socket_t sock, const uint8_t *ptr, const _z_sys_net_endpoint_t rep); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_LINK_UDP_H */ diff --git a/include/zenoh-pico/system/link/ws.h b/include/zenoh-pico/system/link/ws.h index aa57fcbf8..c3fcadc14 100644 --- a/include/zenoh-pico/system/link/ws.h +++ b/include/zenoh-pico/system/link/ws.h @@ -20,6 +20,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/system/platform.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_LINK_WS == 1 typedef struct { @@ -38,4 +42,8 @@ size_t _z_read_ws(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len); size_t _z_send_ws(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t len); #endif +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_LINK_WS_H */ diff --git a/include/zenoh-pico/system/platform/arduino/esp32.h b/include/zenoh-pico/system/platform/arduino/esp32.h index af09722a2..9e8df7a07 100644 --- a/include/zenoh-pico/system/platform/arduino/esp32.h +++ b/include/zenoh-pico/system/platform/arduino/esp32.h @@ -21,6 +21,10 @@ #include #endif // Z_FEATURE_MULTI_THREAD == 1 +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef void *_z_task_t; typedef void *z_task_attr_t; // Not used in ESP32 @@ -56,4 +60,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_ESP32_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/arduino/opencr.h b/include/zenoh-pico/system/platform/arduino/opencr.h index c9c374d2d..e1fa1da4a 100644 --- a/include/zenoh-pico/system/platform/arduino/opencr.h +++ b/include/zenoh-pico/system/platform/arduino/opencr.h @@ -20,6 +20,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef void *_z_task_t; typedef void *z_task_attr_t; @@ -60,4 +64,8 @@ typedef struct { bool _err; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_ARDUINO_OPENCR_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/emscripten.h b/include/zenoh-pico/system/platform/emscripten.h index edb9c6b44..068cca9f2 100644 --- a/include/zenoh-pico/system/platform/emscripten.h +++ b/include/zenoh-pico/system/platform/emscripten.h @@ -19,6 +19,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 #include @@ -50,4 +54,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_WASM_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/espidf.h b/include/zenoh-pico/system/platform/espidf.h index 1f35832a6..aadeb782f 100644 --- a/include/zenoh-pico/system/platform/espidf.h +++ b/include/zenoh-pico/system/platform/espidf.h @@ -22,6 +22,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 #include @@ -69,4 +73,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_ESPIDF_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/flipper.h b/include/zenoh-pico/system/platform/flipper.h index 4a51074f6..8eb94b4c7 100644 --- a/include/zenoh-pico/system/platform/flipper.h +++ b/include/zenoh-pico/system/platform/flipper.h @@ -21,6 +21,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #define FLIPPER_DEFAULT_THREAD_STACK_SIZE 2048 #define FLIPPER_SERIAL_STREAM_BUFFER_SIZE 512 #define FLIPPER_SERIAL_STREAM_TRIGGERED_LEVEL 10 @@ -43,4 +47,8 @@ typedef struct { #endif } _z_sys_net_socket_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_FLIPPER_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/freertos_plus_tcp.h b/include/zenoh-pico/system/platform/freertos_plus_tcp.h index 7332889c5..31a2dfc83 100644 --- a/include/zenoh-pico/system/platform/freertos_plus_tcp.h +++ b/include/zenoh-pico/system/platform/freertos_plus_tcp.h @@ -18,6 +18,10 @@ #include "FreeRTOS_IP.h" #include "semphr.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef struct { const char *name; @@ -58,4 +62,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; -#endif \ No newline at end of file +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/zenoh-pico/system/platform/mbed.h b/include/zenoh-pico/system/platform/mbed.h index 08bb09c83..87fdb4626 100644 --- a/include/zenoh-pico/system/platform/mbed.h +++ b/include/zenoh-pico/system/platform/mbed.h @@ -20,6 +20,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef int _z_socket_t; #if Z_FEATURE_MULTI_THREAD == 1 @@ -61,4 +65,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_MBED_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/unix.h b/include/zenoh-pico/system/platform/unix.h index cea7b5868..b83dbb424 100644 --- a/include/zenoh-pico/system/platform/unix.h +++ b/include/zenoh-pico/system/platform/unix.h @@ -19,12 +19,17 @@ #include #include #include +#if Z_FEATURE_MULTI_THREAD == 1 +#include +#endif // Z_FEATURE_MULTI_THREAD == 1 #include "zenoh-pico/config.h" -#if Z_FEATURE_MULTI_THREAD == 1 -#include +#ifdef __cplusplus +extern "C" { +#endif +#if Z_FEATURE_MULTI_THREAD == 1 typedef pthread_t _z_task_t; typedef pthread_attr_t z_task_attr_t; typedef pthread_mutex_t _z_mutex_t; @@ -51,4 +56,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_UNIX_TYPES_H */ diff --git a/include/zenoh-pico/system/platform/void.h b/include/zenoh-pico/system/platform/void.h index cda1b50ab..f46217281 100644 --- a/include/zenoh-pico/system/platform/void.h +++ b/include/zenoh-pico/system/platform/void.h @@ -17,6 +17,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef void *_z_task_t; typedef void *z_task_attr_t; @@ -27,4 +31,8 @@ typedef void *_z_condvar_t; typedef void *z_clock_t; typedef void *z_time_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_VOID_H */ diff --git a/include/zenoh-pico/system/platform/windows.h b/include/zenoh-pico/system/platform/windows.h index cb41f243d..7ccd38509 100644 --- a/include/zenoh-pico/system/platform/windows.h +++ b/include/zenoh-pico/system/platform/windows.h @@ -20,6 +20,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef HANDLE *_z_task_t; typedef void *z_task_attr_t; // Not used in Windows @@ -48,4 +52,8 @@ typedef struct { inline void __asm__(char *instruction) { (void)(instruction); } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_VOID_H */ diff --git a/include/zenoh-pico/system/platform/zephyr.h b/include/zenoh-pico/system/platform/zephyr.h index 966edaa52..1f25e839c 100644 --- a/include/zenoh-pico/system/platform/zephyr.h +++ b/include/zenoh-pico/system/platform/zephyr.h @@ -30,6 +30,10 @@ #include "zenoh-pico/config.h" +#ifdef __cplusplus +extern "C" { +#endif + #if Z_FEATURE_MULTI_THREAD == 1 typedef pthread_t _z_task_t; typedef pthread_attr_t z_task_attr_t; @@ -59,4 +63,8 @@ typedef struct { }; } _z_sys_net_endpoint_t; +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_SYSTEM_ZEPHYR_TYPES_H */ diff --git a/include/zenoh-pico/transport/common/lease.h b/include/zenoh-pico/transport/common/lease.h index 900a2f887..858282636 100644 --- a/include/zenoh-pico/transport/common/lease.h +++ b/include/zenoh-pico/transport/common/lease.h @@ -17,7 +17,15 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_send_join(_z_transport_t *zt); z_result_t _z_send_keep_alive(_z_transport_t *zt); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_LEASE_H */ diff --git a/include/zenoh-pico/transport/common/read.h b/include/zenoh-pico/transport/common/read.h index f298d1878..fe6b79b6a 100644 --- a/include/zenoh-pico/transport/common/read.h +++ b/include/zenoh-pico/transport/common/read.h @@ -17,7 +17,15 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_read(_z_transport_t *zt); void *_zp_read_task(void *zt_arg); // The argument is void* to avoid incompatible pointer types in tasks +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_READ_H */ diff --git a/include/zenoh-pico/transport/common/rx.h b/include/zenoh-pico/transport/common/rx.h index 147273816..e4f548c6e 100644 --- a/include/zenoh-pico/transport/common/rx.h +++ b/include/zenoh-pico/transport/common/rx.h @@ -18,8 +18,16 @@ #include "zenoh-pico/link/link.h" #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ Transmission and Reception helpers ------------------*/ size_t _z_read_stream_size(_z_zbuf_t *zbuf); z_result_t _z_link_recv_t_msg(_z_transport_message_t *t_msg, const _z_link_t *zl); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_RX_H */ diff --git a/include/zenoh-pico/transport/common/tx.h b/include/zenoh-pico/transport/common/tx.h index 5a7b78b4d..6809f20f3 100644 --- a/include/zenoh-pico/transport/common/tx.h +++ b/include/zenoh-pico/transport/common/tx.h @@ -19,6 +19,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + void __unsafe_z_prepare_wbuf(_z_wbuf_t *buf, uint8_t link_flow_capability); void __unsafe_z_finalize_wbuf(_z_wbuf_t *buf, uint8_t link_flow_capability); /*This function is unsafe because it operates in potentially concurrent @@ -33,4 +37,8 @@ z_result_t _z_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_ z_congestion_control_t cong_ctrl); z_result_t _z_send_n_batch(_z_session_t *zn, z_congestion_control_t cong_ctrl); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_TX_H */ diff --git a/include/zenoh-pico/transport/manager.h b/include/zenoh-pico/transport/manager.h index b850e506e..b22eff975 100644 --- a/include/zenoh-pico/transport/manager.h +++ b/include/zenoh-pico/transport/manager.h @@ -19,6 +19,10 @@ #include "zenoh-pico/link/manager.h" #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + enum _z_peer_op_e { _Z_PEER_OP_OPEN = 0, _Z_PEER_OP_LISTEN = 1, @@ -27,4 +31,8 @@ enum _z_peer_op_e { z_result_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, _z_string_t *locator, z_whatami_t mode, int peer_op); void _z_free_transport(_z_transport_t **zt); +#ifdef __cplusplus +} +#endif + #endif /* INCLUDE_ZENOH_PICO_TRANSPORT_MANAGER_H */ diff --git a/include/zenoh-pico/transport/multicast.h b/include/zenoh-pico/transport/multicast.h index 487ef6dae..bdf939514 100644 --- a/include/zenoh-pico/transport/multicast.h +++ b/include/zenoh-pico/transport/multicast.h @@ -17,7 +17,15 @@ #include "zenoh-pico/api/types.h" +#ifdef __cplusplus +extern "C" { +#endif + void _zp_multicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback); void _zp_multicast_info_session(const _z_transport_t *zt, _z_config_t *ps); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_MULTICAST_H */ diff --git a/include/zenoh-pico/transport/multicast/lease.h b/include/zenoh-pico/transport/multicast/lease.h index 09a0b4135..71472bb55 100644 --- a/include/zenoh-pico/transport/multicast/lease.h +++ b/include/zenoh-pico/transport/multicast/lease.h @@ -17,6 +17,10 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _zp_multicast_send_join(_z_transport_multicast_t *ztm); z_result_t _zp_multicast_send_keep_alive(_z_transport_multicast_t *ztm); z_result_t _zp_multicast_stop_lease_task(_z_transport_multicast_t *ztm); @@ -28,4 +32,8 @@ z_result_t _zp_multicast_start_lease_task(_z_transport_multicast_t *ztm, z_task_ z_result_t _zp_multicast_start_lease_task(_z_transport_multicast_t *ztm, void *attr, void *task); #endif /* Z_FEATURE_MULTI_THREAD == 1 && (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) */ +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_MULTICAST_LEASE_H */ diff --git a/include/zenoh-pico/transport/multicast/read.h b/include/zenoh-pico/transport/multicast/read.h index acaa82308..63c9a0eda 100644 --- a/include/zenoh-pico/transport/multicast/read.h +++ b/include/zenoh-pico/transport/multicast/read.h @@ -17,6 +17,10 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _zp_multicast_read(_z_transport_multicast_t *ztm); z_result_t _zp_multicast_stop_read_task(_z_transport_t *zt); void *_zp_multicast_read_task(void *ztm_arg); // The argument is void* to avoid incompatible pointer types in tasks @@ -27,4 +31,8 @@ z_result_t _zp_multicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr z_result_t _zp_multicast_start_read_task(_z_transport_t *zt, void *attr, void *task); #endif /* #if Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_MULTICAST_TRANSPORT == 1 */ +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_MULTICAST_READ_H */ diff --git a/include/zenoh-pico/transport/multicast/rx.h b/include/zenoh-pico/transport/multicast/rx.h index 97b1e8960..f7a81e00a 100644 --- a/include/zenoh-pico/transport/multicast/rx.h +++ b/include/zenoh-pico/transport/multicast/rx.h @@ -17,9 +17,17 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_multicast_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); z_result_t _z_multicast_update_rx_buffer(_z_transport_multicast_t *ztm); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_LINK_RX_H */ diff --git a/include/zenoh-pico/transport/multicast/transport.h b/include/zenoh-pico/transport/multicast/transport.h index 4947ac894..3e61f4bc1 100644 --- a/include/zenoh-pico/transport/multicast/transport.h +++ b/include/zenoh-pico/transport/multicast/transport.h @@ -17,6 +17,10 @@ #include "zenoh-pico/api/types.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, _z_transport_multicast_establish_param_t *param); z_result_t _z_multicast_open_peer(_z_transport_multicast_establish_param_t *param, const _z_link_t *zl, @@ -34,4 +38,8 @@ static inline void _z_multicast_peer_mutex_unlock(_z_transport_multicast_t *ztm) static inline void _z_multicast_peer_mutex_lock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } static inline void _z_multicast_peer_mutex_unlock(_z_transport_multicast_t *ztm) { _ZP_UNUSED(ztm); } #endif // (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) && Z_FEATURE_MULTI_THREAD == 1 -#endif /* ZENOH_PICO_MULTICAST_TRANSPORT_H */ + +#ifdef __cplusplus +} +#endif +#endif /* ZENOH_PICO_MULTICAST_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/raweth/read.h b/include/zenoh-pico/transport/raweth/read.h index 6ead7be9b..f5cc3a6ee 100644 --- a/include/zenoh-pico/transport/raweth/read.h +++ b/include/zenoh-pico/transport/raweth/read.h @@ -17,6 +17,10 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _zp_raweth_read(_z_transport_multicast_t *ztm); z_result_t _zp_raweth_stop_read_task(_z_transport_t *zt); void *_zp_raweth_read_task(void *ztm_arg); // The argument is void* to avoid incompatible pointer types in tasks @@ -27,4 +31,8 @@ z_result_t _zp_raweth_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, _ z_result_t _zp_raweth_start_read_task(_z_transport_t *zt, void *attr, void *task); #endif /* Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_RAWETH_TRANSPORT == 1 */ +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_RAWETH_READ_H */ diff --git a/include/zenoh-pico/transport/raweth/rx.h b/include/zenoh-pico/transport/raweth/rx.h index 4607dd6b2..19901b68f 100644 --- a/include/zenoh-pico/transport/raweth/rx.h +++ b/include/zenoh-pico/transport/raweth/rx.h @@ -17,8 +17,16 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); z_result_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); z_result_t _z_raweth_update_rx_buff(_z_transport_multicast_t *ztm); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_RAWETH_RX_H */ diff --git a/include/zenoh-pico/transport/raweth/tx.h b/include/zenoh-pico/transport/raweth/tx.h index 9b18d2004..a338c16f3 100644 --- a/include/zenoh-pico/transport/raweth/tx.h +++ b/include/zenoh-pico/transport/raweth/tx.h @@ -18,9 +18,17 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_raweth_link_send_t_msg(const _z_link_t *zl, const _z_transport_message_t *t_msg); z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl); z_result_t _z_raweth_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_RAWETH_TX_H */ diff --git a/include/zenoh-pico/transport/transport.h b/include/zenoh-pico/transport/transport.h index e78de9366..d4fcf7ea7 100644 --- a/include/zenoh-pico/transport/transport.h +++ b/include/zenoh-pico/transport/transport.h @@ -25,6 +25,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + enum _z_dbuf_state_e { _Z_DBUF_STATE_NULL = 0, _Z_DBUF_STATE_INIT = 1, @@ -195,4 +199,8 @@ static inline void _z_transport_tx_mutex_unlock(_z_transport_common_t *ztc) { _Z static inline void _z_transport_rx_mutex_lock(_z_transport_common_t *ztc) { _ZP_UNUSED(ztc); } static inline void _z_transport_rx_mutex_unlock(_z_transport_common_t *ztc) { _ZP_UNUSED(ztc); } #endif // Z_FEATURE_MULTI_THREAD == 1 -#endif /* INCLUDE_ZENOH_PICO_TRANSPORT_TRANSPORT_H */ + +#ifdef __cplusplus +} +#endif +#endif /* INCLUDE_ZENOH_PICO_TRANSPORT_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/unicast.h b/include/zenoh-pico/transport/unicast.h index 652384e47..4c0d525bd 100644 --- a/include/zenoh-pico/transport/unicast.h +++ b/include/zenoh-pico/transport/unicast.h @@ -17,7 +17,15 @@ #include "zenoh-pico/api/types.h" +#ifdef __cplusplus +extern "C" { +#endif + void _zp_unicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback); void _zp_unicast_info_session(const _z_transport_t *zt, _z_config_t *ps); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UNICAST_H */ diff --git a/include/zenoh-pico/transport/unicast/lease.h b/include/zenoh-pico/transport/unicast/lease.h index 469fd1333..0d607afd6 100644 --- a/include/zenoh-pico/transport/unicast/lease.h +++ b/include/zenoh-pico/transport/unicast/lease.h @@ -17,6 +17,10 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _zp_unicast_send_keep_alive(_z_transport_unicast_t *ztu); z_result_t _zp_unicast_stop_lease_task(_z_transport_t *zt); void *_zp_unicast_lease_task(void *ztu_arg); // The argument is void* to avoid incompatible pointer types in tasks @@ -27,4 +31,8 @@ z_result_t _zp_unicast_start_lease_task(_z_transport_t *zt, z_task_attr_t *attr, z_result_t _zp_unicast_start_lease_task(_z_transport_t *zt, void *attr, void *task); #endif /* Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_UNICAST_TRANSPORT == 1 */ +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_LINK_TASK_LEASE_H */ diff --git a/include/zenoh-pico/transport/unicast/read.h b/include/zenoh-pico/transport/unicast/read.h index 63a8976bb..e703a1ee1 100644 --- a/include/zenoh-pico/transport/unicast/read.h +++ b/include/zenoh-pico/transport/unicast/read.h @@ -17,6 +17,10 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _zp_unicast_read(_z_transport_unicast_t *ztu); z_result_t _zp_unicast_stop_read_task(_z_transport_t *zt); void *_zp_unicast_read_task(void *ztu_arg); // The argument is void* to avoid incompatible pointer types in tasks @@ -27,4 +31,8 @@ z_result_t _zp_unicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, z_result_t _zp_unicast_start_read_task(_z_transport_t *zt, void *attr, void *task); #endif /* Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_UNICAST_TRANSPORT == 1 */ +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UNICAST_READ_H */ diff --git a/include/zenoh-pico/transport/unicast/rx.h b/include/zenoh-pico/transport/unicast/rx.h index 1fa5b60d7..8052ebd88 100644 --- a/include/zenoh-pico/transport/unicast/rx.h +++ b/include/zenoh-pico/transport/unicast/rx.h @@ -17,9 +17,17 @@ #include "zenoh-pico/transport/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_unicast_recv_t_msg(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg); z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg); z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg); z_result_t _z_unicast_update_rx_buffer(_z_transport_unicast_t *ztu); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UNICAST_RX_H */ diff --git a/include/zenoh-pico/transport/unicast/transport.h b/include/zenoh-pico/transport/unicast/transport.h index b2ab36425..3ca322c42 100644 --- a/include/zenoh-pico/transport/unicast/transport.h +++ b/include/zenoh-pico/transport/unicast/transport.h @@ -17,6 +17,10 @@ #include "zenoh-pico/api/types.h" +#ifdef __cplusplus +extern "C" { +#endif + z_result_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, _z_transport_unicast_establish_param_t *param); z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, @@ -27,4 +31,8 @@ z_result_t _z_unicast_send_close(_z_transport_unicast_t *ztu, uint8_t reason, bo z_result_t _z_unicast_transport_close(_z_transport_unicast_t *ztu, uint8_t reason); void _z_unicast_transport_clear(_z_transport_t *zt); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UNICAST_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/utils.h b/include/zenoh-pico/transport/utils.h index aff81dc03..62fa319b4 100644 --- a/include/zenoh-pico/transport/utils.h +++ b/include/zenoh-pico/transport/utils.h @@ -20,6 +20,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/transport.h" +#ifdef __cplusplus +extern "C" { +#endif + /*------------------ SN helpers ------------------*/ _z_zint_t _z_sn_max(uint8_t bits); _z_zint_t _z_sn_half(_z_zint_t sn); @@ -31,4 +35,8 @@ _z_zint_t _z_sn_decrement(const _z_zint_t sn_resolution, const _z_zint_t sn); void _z_conduit_sn_list_copy(_z_conduit_sn_list_t *dst, const _z_conduit_sn_list_t *src); void _z_conduit_sn_list_decrement(const _z_zint_t sn_resolution, _z_conduit_sn_list_t *sns); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_TRANSPORT_UTILS_H */ diff --git a/include/zenoh-pico/utils/checksum.h b/include/zenoh-pico/utils/checksum.h index b649ad02b..aad153f9c 100644 --- a/include/zenoh-pico/utils/checksum.h +++ b/include/zenoh-pico/utils/checksum.h @@ -18,6 +18,14 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + uint32_t _z_crc32(const uint8_t *message, size_t len); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UTILS_CHECKSUM_H */ diff --git a/include/zenoh-pico/utils/config.h b/include/zenoh-pico/utils/config.h index de17a1239..cf67d4189 100644 --- a/include/zenoh-pico/utils/config.h +++ b/include/zenoh-pico/utils/config.h @@ -21,6 +21,10 @@ #include "zenoh-pico/collections/string.h" #include "zenoh-pico/utils/result.h" +#ifdef __cplusplus +extern "C" { +#endif + // Properties returned by _z_info() #define Z_INFO_PID_KEY 0x00 #define Z_INFO_PEER_PID_KEY 0x01 @@ -46,6 +50,7 @@ z_result_t _z_config_init(_z_config_t *ps); * value: The value of the property to add. */ z_result_t _zp_config_insert(_z_config_t *ps, uint8_t key, const char *value); +z_result_t _zp_config_insert_string(_z_config_t *ps, uint8_t key, const _z_string_t *value); /** * Get the property with the given key from a properties map. @@ -109,4 +114,8 @@ char *_z_config_get(const _z_config_t *ps, uint8_t key); */ #define _z_config_free _z_str_intmap_free +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UTILS_PROPERTY_H */ diff --git a/include/zenoh-pico/utils/encoding.h b/include/zenoh-pico/utils/encoding.h index 266eb4db1..3ff2c6988 100644 --- a/include/zenoh-pico/utils/encoding.h +++ b/include/zenoh-pico/utils/encoding.h @@ -18,7 +18,15 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + size_t _z_cobs_encode(const uint8_t *input, size_t input_len, uint8_t *output); size_t _z_cobs_decode(const uint8_t *input, size_t input_len, uint8_t *output); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UTILS_ENCODING_H */ diff --git a/include/zenoh-pico/utils/logging.h b/include/zenoh-pico/utils/logging.h index 2c9f3ab0d..b50110bdf 100644 --- a/include/zenoh-pico/utils/logging.h +++ b/include/zenoh-pico/utils/logging.h @@ -19,6 +19,10 @@ #include "zenoh-pico/system/platform_common.h" +#ifdef __cplusplus +extern "C" { +#endif + // Logging values #define _Z_LOG_LVL_ERROR 1 #define _Z_LOG_LVL_INFO 2 @@ -72,4 +76,8 @@ static inline void __z_print_timestamp(void) { } while (false) #endif // ZENOH_DEBUG == 0 && !defined(Z_BUILD_DEBUG) +#ifdef __cplusplus +} +#endif + #endif // ZENOH_PICO_UTILS_LOGGING_H diff --git a/include/zenoh-pico/utils/pointers.h b/include/zenoh-pico/utils/pointers.h index 7ce798c64..a5f5156df 100644 --- a/include/zenoh-pico/utils/pointers.h +++ b/include/zenoh-pico/utils/pointers.h @@ -18,6 +18,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /** * Computes the distance between two ``uint8_t`` pointers as an absolute value. * Note that ``l_ptr`` must be higher than ``r_ptr``. @@ -92,4 +96,8 @@ const char *_z_cptr_char_offset(const char *ptr, ptrdiff_t off); */ char *_z_ptr_char_offset(char *ptr, ptrdiff_t off); +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UTILS_POINTERS_H */ diff --git a/include/zenoh-pico/utils/result.h b/include/zenoh-pico/utils/result.h index 4dd16f141..6b1061d21 100644 --- a/include/zenoh-pico/utils/result.h +++ b/include/zenoh-pico/utils/result.h @@ -17,6 +17,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + #define _ZP_UNUSED(x) (void)(x) #define _ZP_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) @@ -106,4 +110,8 @@ typedef enum { #define _Z_IS_OK(expr) (expr == _Z_RES_OK) #define _Z_IS_ERR(expr) (expr != _Z_RES_OK) +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_UTILS_RESULT_H */ diff --git a/include/zenoh-pico/utils/string.h b/include/zenoh-pico/utils/string.h index ca9b5a6b6..e4ffd69d2 100644 --- a/include/zenoh-pico/utils/string.h +++ b/include/zenoh-pico/utils/string.h @@ -12,10 +12,17 @@ // ZettaScale Zenoh Team, // +#ifndef ZENOH_PICO_UTILS_STRING_H +#define ZENOH_PICO_UTILS_STRING_H + #include #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { char const *start; char const *end; @@ -55,3 +62,9 @@ _z_str_se_t _z_splitstr_nextback(_z_splitstr_t *str); size_t _z_strcnt(char const *haystack_start, const char *harstack_end, const char *needle_start); size_t _z_str_startswith(const char *s, const char *needle); + +#ifdef __cplusplus +} +#endif + +#endif /* ZENOH_PICO_UTILS_STRING_H */ diff --git a/include/zenoh-pico/utils/uuid.h b/include/zenoh-pico/utils/uuid.h index 4bd581a91..13631460b 100644 --- a/include/zenoh-pico/utils/uuid.h +++ b/include/zenoh-pico/utils/uuid.h @@ -14,6 +14,16 @@ #include +#include "zenoh-pico/collections/string.h" +#include "zenoh-pico/protocol/core.h" + +#ifndef ZENOH_PICO_UTILS_UUID_H +#define ZENOH_PICO_UTILS_UUID_H + +#ifdef __cplusplus +extern "C" { +#endif + /** * Converts an UUID in string format to a byte array. * @@ -22,3 +32,20 @@ * uuid_str: A valid UUID string. */ void _z_uuid_to_bytes(uint8_t *bytes, const char *uuid_str); + +/** + * Converts an Zenoh ID to string. + * + * Parameters: + * id: Zenoh ID. + * + * Returns: + * ID string representation + */ +_z_string_t _z_id_to_string(const _z_id_t *id); + +#ifdef __cplusplus +} +#endif + +#endif /* ZENOH_PICO_UTILS_UUID_H */ diff --git a/src/api/api.c b/src/api/api.c index 93c811f0b..37b2e0037 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -546,15 +546,15 @@ static _z_encoding_t _z_encoding_from_owned(const z_owned_encoding_t *encoding) _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_sample_t, sample, _z_sample_check, _z_sample_null, _z_sample_copy, _z_sample_clear) _Z_OWNED_FUNCTIONS_RC_IMPL(session) -_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_sample, _z_sample_handler_t, z_dropper_handler_t) -_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_query, _z_query_handler_t, z_dropper_handler_t) -_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_reply, _z_reply_handler_t, z_dropper_handler_t) -_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_hello, z_loaned_hello_handler_t, z_dropper_handler_t) -_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_zid, z_zid_handler_t, z_dropper_handler_t) +_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_sample, _z_closure_sample_callback_t, z_closure_drop_callback_t) +_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_query, _z_closure_query_callback_t, z_closure_drop_callback_t) +_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_reply, _z_closure_reply_callback_t, z_closure_drop_callback_t) +_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_hello, z_closure_hello_callback_t, z_closure_drop_callback_t) +_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_zid, z_closure_zid_callback_t, z_closure_drop_callback_t) /************* Primitives **************/ typedef struct __z_hello_handler_wrapper_t { - z_loaned_hello_handler_t user_call; + z_closure_hello_callback_t user_call; void *ctx; } __z_hello_handler_wrapper_t; @@ -712,8 +712,7 @@ z_result_t z_info_routers_zid(const z_loaned_session_t *zs, z_moved_closure_zid_ z_id_t z_info_zid(const z_loaned_session_t *zs) { return _Z_RC_IN_VAL(zs)->_local_zid; } z_result_t z_id_to_string(const z_id_t *id, z_owned_string_t *str) { - _z_slice_t buf = _z_slice_alias_buf(id->id, sizeof(id->id)); - str->_val = _z_string_convert_bytes(&buf); + str->_val = _z_id_to_string(id); if (!_z_string_check(&str->_val)) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } @@ -1107,6 +1106,7 @@ const z_loaned_sample_t *z_reply_ok(const z_loaned_reply_t *reply) { return &rep const z_loaned_reply_err_t *z_reply_err(const z_loaned_reply_t *reply) { return &reply->data._result.error; } +#ifdef Z_FEATURE_UNSTABLE_API bool z_reply_replier_id(const z_loaned_reply_t *reply, z_id_t *out_id) { if (_z_id_check(reply->data.replier_id)) { *out_id = reply->data.replier_id; @@ -1114,7 +1114,9 @@ bool z_reply_replier_id(const z_loaned_reply_t *reply, z_id_t *out_id) { } return false; } -#endif +#endif // Z_FEATURE_UNSTABLE_API + +#endif // Z_FEATURE_QUERY == 1 #if Z_FEATURE_QUERYABLE == 1 _Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_query_t, query, _z_query_check, _z_query_null, _z_query_copy, _z_query_clear) @@ -1418,6 +1420,7 @@ const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *sub) } #endif +#ifdef Z_FEATURE_UNSTABLE_API #if Z_FEATURE_BATCHING == 1 z_result_t zp_batch_start(const z_loaned_session_t *zs) { if (_Z_RC_IS_NULL(zs)) { @@ -1437,6 +1440,7 @@ z_result_t zp_batch_stop(const z_loaned_session_t *zs) { return _z_send_n_batch(session, Z_CONGESTION_CONTROL_DEFAULT); } #endif +#endif /**************** Tasks ****************/ void zp_task_read_options_default(zp_task_read_options_t *options) { diff --git a/src/api/encoding.c b/src/api/encoding.c index 8cbe24ae1..b4ff4cb18 100644 --- a/src/api/encoding.c +++ b/src/api/encoding.c @@ -262,4 +262,6 @@ z_result_t z_encoding_to_string(const z_loaned_encoding_t *encoding, z_owned_str return _Z_RES_OK; } +#if Z_FEATURE_ENCODING_VALUES == 1 const z_loaned_encoding_t *z_encoding_loan_default(void) { return z_encoding_zenoh_bytes(); } +#endif diff --git a/src/api/serialization.c b/src/api/serialization.c index b5ff623d6..c6b018593 100644 --- a/src/api/serialization.c +++ b/src/api/serialization.c @@ -84,9 +84,13 @@ z_result_t ze_deserializer_deserialize_slice(ze_deserializer_t *deserializer, z_ return Z_OK; } +z_result_t ze_serializer_serialize_substr(ze_loaned_serializer_t *serializer, const char *start, size_t len) { + // TODO: perform a UTF-8 correctness check. + return ze_serializer_serialize_buf(serializer, (const uint8_t *)start, len); +} + z_result_t ze_serializer_serialize_str(ze_loaned_serializer_t *serializer, const char *val) { - size_t len = strlen(val); - return ze_serializer_serialize_buf(serializer, (const uint8_t *)val, len); + return ze_serializer_serialize_substr(serializer, val, strlen(val)); } z_result_t ze_serializer_serialize_string(ze_loaned_serializer_t *serializer, const z_loaned_string_t *val) { @@ -121,6 +125,11 @@ z_result_t ze_deserialize_slice(const z_loaned_bytes_t *bytes, z_owned_slice_t * return ze_deserializer_deserialize_slice(&deserializer, data); } +z_result_t ze_serialize_substr(z_owned_bytes_t *bytes, const char *start, size_t len) { + _Z_BUILD_BYTES_FROM_SERIALIZER(ze_serializer_serialize_substr(&serializer, start, len)); + return _Z_RES_OK; +} + z_result_t ze_serialize_str(z_owned_bytes_t *bytes, const char *data) { _Z_BUILD_BYTES_FROM_SERIALIZER(ze_serializer_serialize_str(&serializer, data)); return _Z_RES_OK; diff --git a/src/collections/string.c b/src/collections/string.c index 2dad38f40..236b85077 100644 --- a/src/collections/string.c +++ b/src/collections/string.c @@ -108,7 +108,7 @@ bool _z_string_equals(const _z_string_t *left, const _z_string_t *right) { return (strncmp(_z_string_data(left), _z_string_data(right), _z_string_len(left)) == 0); } -_z_string_t _z_string_convert_bytes(const _z_slice_t *bs) { +_z_string_t _z_string_convert_bytes_le(const _z_slice_t *bs) { _z_string_t s = _z_string_null(); size_t len = bs->len * (size_t)2; char *s_val = (char *)z_malloc((len) * sizeof(char)); @@ -116,10 +116,11 @@ _z_string_t _z_string_convert_bytes(const _z_slice_t *bs) { return s; } - const char c[] = "0123456789ABCDEF"; + const char c[] = "0123456789abcdef"; + size_t pos = bs->len * 2; for (size_t i = 0; i < bs->len; i++) { - s_val[i * (size_t)2] = c[(bs->start[i] & (uint8_t)0xF0) >> (uint8_t)4]; - s_val[(i * (size_t)2) + 1] = c[bs->start[i] & (uint8_t)0x0F]; + s_val[--pos] = c[bs->start[i] & (uint8_t)0x0F]; + s_val[--pos] = c[(bs->start[i] & (uint8_t)0xF0) >> (uint8_t)4]; } s._slice = _z_slice_from_buf_custom_deleter((const uint8_t *)s_val, len, _z_delete_context_default()); return s; @@ -215,4 +216,8 @@ char *_z_str_n_clone(const char *src, size_t len) { return dst; } +char *_z_str_from_string_clone(const _z_string_t *str) { + return _z_str_n_clone((const char *)str->_slice.start, str->_slice.len); +} + bool _z_str_eq(const char *left, const char *right) { return strcmp(left, right) == 0; } diff --git a/src/net/primitives.c b/src/net/primitives.c index 4e235d0d4..baf24fa50 100644 --- a/src/net/primitives.c +++ b/src/net/primitives.c @@ -39,7 +39,7 @@ /*------------------ Scouting ------------------*/ void _z_scout(const z_what_t what, const _z_id_t zid, _z_string_t *locator, const uint32_t timeout, - _z_hello_handler_t callback, void *arg_call, _z_drop_handler_t dropper, void *arg_drop) { + _z_closure_hello_callback_t callback, void *arg_call, _z_drop_handler_t dropper, void *arg_drop) { _z_hello_list_t *hellos = _z_scout_inner(what, zid, locator, timeout, false); while (hellos != NULL) { @@ -193,8 +193,8 @@ z_result_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes #if Z_FEATURE_SUBSCRIPTION == 1 /*------------------ Subscriber Declaration ------------------*/ -_z_subscriber_t _z_declare_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, _z_sample_handler_t callback, - _z_drop_handler_t dropper, void *arg) { +_z_subscriber_t _z_declare_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, + _z_closure_sample_callback_t callback, _z_drop_handler_t dropper, void *arg) { _z_subscription_t s; s._id = _z_get_entity_id(_Z_RC_IN_VAL(zn)); s._key_id = keyexpr._id; @@ -257,7 +257,7 @@ z_result_t _z_undeclare_subscriber(_z_subscriber_t *sub) { #if Z_FEATURE_QUERYABLE == 1 /*------------------ Queryable Declaration ------------------*/ _z_queryable_t _z_declare_queryable(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, bool complete, - _z_query_handler_t callback, _z_drop_handler_t dropper, void *arg) { + _z_closure_query_callback_t callback, _z_drop_handler_t dropper, void *arg) { _z_session_queryable_t q; q._id = _z_get_entity_id(_Z_RC_IN_VAL(zn)); q._key = _z_get_expanded_key_from_key(_Z_RC_IN_VAL(zn), &keyexpr); @@ -453,7 +453,7 @@ z_result_t _z_send_reply_err(const _z_query_t *query, const _z_session_rc_t *zsr #if Z_FEATURE_QUERY == 1 /*------------------ Query ------------------*/ z_result_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *parameters, const z_query_target_t target, - const z_consolidation_mode_t consolidation, _z_value_t value, _z_reply_handler_t callback, + const z_consolidation_mode_t consolidation, _z_value_t value, _z_closure_reply_callback_t callback, _z_drop_handler_t dropper, void *arg, uint64_t timeout_ms, const _z_bytes_t attachment, z_congestion_control_t cong_ctrl, z_priority_t priority, bool is_express) { z_result_t ret = _Z_RES_OK; diff --git a/src/net/session.c b/src/net/session.c index cf3a7e991..c70fdbabe 100644 --- a/src/net/session.c +++ b/src/net/session.c @@ -166,11 +166,8 @@ _z_config_t *_z_info(const _z_session_t *zn) { _z_config_t *ps = (_z_config_t *)z_malloc(sizeof(_z_config_t)); if (ps != NULL) { _z_config_init(ps); - _z_slice_t local_zid = _z_slice_alias_buf(zn->_local_zid.id, _z_id_len(zn->_local_zid)); - // TODO(sasahcmc): is it zero terminated??? - // rework it!!! - _z_string_t s = _z_string_convert_bytes(&local_zid); - _zp_config_insert(ps, Z_INFO_PID_KEY, _z_string_data(&s)); + _z_string_t s = _z_id_to_string(&zn->_local_zid); + _zp_config_insert_string(ps, Z_INFO_PID_KEY, &s); _z_string_clear(&s); switch (zn->_tp._type) { diff --git a/src/protocol/config.c b/src/protocol/config.c index dcdb4f904..1cfcff9c3 100644 --- a/src/protocol/config.c +++ b/src/protocol/config.c @@ -19,6 +19,7 @@ #include #include +#include "zenoh-pico/collections/string.h" #include "zenoh-pico/utils/pointers.h" z_result_t _z_config_init(_z_config_t *ps) { @@ -37,6 +38,18 @@ z_result_t _zp_config_insert(_z_config_t *ps, uint8_t key, const char *value) { return ret; } +z_result_t _zp_config_insert_string(_z_config_t *ps, uint8_t key, const _z_string_t *value) { + z_result_t ret = _Z_RES_OK; + char *str = _z_str_from_string_clone(value); + char *res = _z_str_intmap_insert(ps, key, str); + if (strcmp(res, str) != 0) { + ret = _Z_ERR_CONFIG_FAILED_INSERT; + } + z_free(str); + + return ret; +} + char *_z_config_get(const _z_config_t *ps, uint8_t key) { return _z_str_intmap_get(ps, key); } /*------------------ int-string map ------------------*/ diff --git a/src/system/emscripten/system.c b/src/system/emscripten/system.c index 9bfa8f7d6..52065d2db 100644 --- a/src/system/emscripten/system.c +++ b/src/system/emscripten/system.c @@ -55,11 +55,7 @@ z_result_t _z_task_detach(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_detach(*ta z_result_t _z_task_cancel(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_cancel(*task)); } -void _z_task_free(_z_task_t **task) { - _z_task_t *ptr = *task; - z_free(ptr); - *task = NULL; -} +void _z_task_free(_z_task_t **task) { *task = NULL; } /*------------------ Mutex ------------------*/ z_result_t _z_mutex_init(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_init(m, 0)); } diff --git a/src/system/unix/system.c b/src/system/unix/system.c index beb78ceef..d1c0c5886 100644 --- a/src/system/unix/system.c +++ b/src/system/unix/system.c @@ -114,11 +114,7 @@ z_result_t _z_task_detach(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_detach(*ta z_result_t _z_task_cancel(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_cancel(*task)); } -void _z_task_free(_z_task_t **task) { - _z_task_t *ptr = *task; - z_free(ptr); - *task = NULL; -} +void _z_task_free(_z_task_t **task) { *task = NULL; } /*------------------ Mutex ------------------*/ z_result_t _z_mutex_init(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_init(m, 0)); } diff --git a/src/system/zephyr/system.c b/src/system/zephyr/system.c index c76e26a02..7818c9993 100644 --- a/src/system/zephyr/system.c +++ b/src/system/zephyr/system.c @@ -89,11 +89,7 @@ z_result_t _z_task_detach(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_detach(*ta z_result_t _z_task_cancel(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_cancel(*task)); } -void _z_task_free(_z_task_t **task) { - _z_task_t *ptr = *task; - z_free(ptr); - *task = NULL; -} +void _z_task_free(_z_task_t **task) { *task = NULL; } /*------------------ Mutex ------------------*/ z_result_t _z_mutex_init(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_init(m, 0)); } diff --git a/src/transport/multicast.c b/src/transport/multicast.c index 8425131df..eae7f7bc7 100644 --- a/src/transport/multicast.c +++ b/src/transport/multicast.c @@ -27,6 +27,7 @@ #include "zenoh-pico/transport/unicast/rx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/uuid.h" #if Z_FEATURE_MULTICAST_TRANSPORT == 1 void _zp_multicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback) { @@ -44,9 +45,8 @@ void _zp_multicast_info_session(const _z_transport_t *zt, _z_config_t *ps) { _z_transport_peer_entry_list_t *xs = zt->_transport._multicast._peers; while (xs != NULL) { _z_transport_peer_entry_t *peer = _z_transport_peer_entry_list_head(xs); - _z_slice_t remote_zid = _z_slice_alias_buf(peer->_remote_zid.id, _z_id_len(peer->_remote_zid)); - _z_string_t remote_zid_str = _z_string_convert_bytes(&remote_zid); - _zp_config_insert(ps, Z_INFO_PEER_PID_KEY, _z_string_data(&remote_zid_str)); + _z_string_t remote_zid_str = _z_id_to_string(&peer->_remote_zid); + _zp_config_insert_string(ps, Z_INFO_PEER_PID_KEY, &remote_zid_str); _z_string_clear(&remote_zid_str); xs = _z_transport_peer_entry_list_tail(xs); diff --git a/src/transport/multicast/transport.c b/src/transport/multicast/transport.c index 3f5f1c1bf..bbe13bf19 100644 --- a/src/transport/multicast/transport.c +++ b/src/transport/multicast/transport.c @@ -199,11 +199,11 @@ void _z_multicast_transport_clear(_z_transport_t *zt) { // Clean up tasks if (ztm->_common._read_task != NULL) { _z_task_join(ztm->_common._read_task); - _z_task_free(&ztm->_common._read_task); + z_free(ztm->_common._read_task); } if (ztm->_common._lease_task != NULL) { _z_task_join(ztm->_common._lease_task); - _z_task_free(&ztm->_common._lease_task); + z_free(ztm->_common._lease_task); } // Clean up the mutexes _z_mutex_drop(&ztm->_common._mutex_tx); diff --git a/src/transport/unicast.c b/src/transport/unicast.c index 3c771a126..2387565cc 100644 --- a/src/transport/unicast.c +++ b/src/transport/unicast.c @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include "zenoh-pico/link/link.h" #include "zenoh-pico/transport/common/rx.h" @@ -28,6 +26,7 @@ #include "zenoh-pico/transport/unicast/rx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/uuid.h" #if Z_FEATURE_UNICAST_TRANSPORT == 1 void _zp_unicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback) { @@ -38,9 +37,9 @@ void _zp_unicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback) void _zp_unicast_info_session(const _z_transport_t *zt, _z_config_t *ps) { _z_id_t remote_zid = zt->_transport._unicast._remote_zid; - _z_slice_t remote_zid_bytes = _z_slice_alias_buf(remote_zid.id, _z_id_len(remote_zid)); - _z_string_t remote_zid_str = _z_string_convert_bytes(&remote_zid_bytes); - _zp_config_insert(ps, Z_INFO_ROUTER_PID_KEY, _z_string_data(&remote_zid_str)); + + _z_string_t remote_zid_str = _z_id_to_string(&remote_zid); + _zp_config_insert_string(ps, Z_INFO_ROUTER_PID_KEY, &remote_zid_str); _z_string_clear(&remote_zid_str); } diff --git a/src/transport/unicast/transport.c b/src/transport/unicast/transport.c index 6f90b4397..9ae20a38c 100644 --- a/src/transport/unicast/transport.c +++ b/src/transport/unicast/transport.c @@ -329,11 +329,11 @@ void _z_unicast_transport_clear(_z_transport_t *zt) { // Clean up tasks if (ztu->_common._read_task != NULL) { _z_task_join(ztu->_common._read_task); - _z_task_free(&ztu->_common._read_task); + z_free(ztu->_common._read_task); } if (ztu->_common._lease_task != NULL) { _z_task_join(ztu->_common._lease_task); - _z_task_free(&ztu->_common._lease_task); + z_free(ztu->_common._lease_task); } // Clean up the mutexes diff --git a/src/utils/uuid.c b/src/utils/uuid.c index 7b9984871..1f2d97fe6 100644 --- a/src/utils/uuid.c +++ b/src/utils/uuid.c @@ -17,6 +17,7 @@ #include #include +#include "zenoh-pico/api/types.h" #include "zenoh-pico/utils/pointers.h" #define UUID_SIZE 16 @@ -32,3 +33,8 @@ void _z_uuid_to_bytes(uint8_t *bytes, const char *uuid_str) { bytes = _z_ptr_u8_offset(bytes, 1); } } + +_z_string_t _z_id_to_string(const z_id_t *id) { + _z_slice_t buf = _z_slice_alias_buf(id->id, sizeof(id->id)); + return _z_string_convert_bytes_le(&buf); +} diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index a8b48eb3e..abef93a46 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -132,11 +132,9 @@ int main(int argc, char **argv) { zc_init_logger(); const char *encoding_expected = z_sample_kind(sample) == Z_SAMPLE_KIND_PUT ? "zenoh/bytes" : "zenoh/bytes;test_encoding"; - z_pu #endif - z_view_keyexpr_t key_demo_example, - key_demo_example_a, key_demo_example_starstar; + z_view_keyexpr_t key_demo_example, key_demo_example_a, key_demo_example_starstar; z_view_keyexpr_from_str(&key_demo_example, "demo/example"); z_view_keyexpr_from_str(&key_demo_example_a, "demo/example/a"); z_view_keyexpr_from_str(&key_demo_example_starstar, "demo/example/**"); @@ -199,10 +197,9 @@ int main(int argc, char **argv) { assert(z_internal_check(s1)); z_id_t _ret_zid = z_info_zid(z_loan(s1)); printf("Session 1 with PID: 0x"); - for (unsigned long i = 0; i < sizeof(_ret_zid); i++) { - printf("%.2X", _ret_zid.id[i]); - } - printf("\n"); + z_owned_string_t id_str; + z_id_to_string(&_ret_zid, &id_str); + printf("%.*s\n", (int)z_string_len(z_loan(id_str)), z_string_data(z_loan(id_str))); z_owned_closure_zid_t _ret_closure_zid; z_closure(&_ret_closure_zid, zid_handler, NULL, NULL); @@ -243,10 +240,8 @@ int main(int argc, char **argv) { assert(z_internal_check(s2)); _ret_zid = z_info_zid(z_loan(s2)); printf("Session 2 with PID: 0x"); - for (unsigned long i = 0; i < sizeof(_ret_zid); i++) { - printf("%.2X", _ret_zid.id[i]); - } - printf("\n"); + z_id_to_string(&_ret_zid, &id_str); + printf("%.*s\n", (int)z_string_len(z_loan(id_str)), z_string_data(z_loan(id_str))); #ifdef ZENOH_PICO zp_start_read_task(z_loan_mut(s2), NULL); diff --git a/tests/z_client_test.c b/tests/z_client_test.c index 229722a48..ca230002c 100644 --- a/tests/z_client_test.c +++ b/tests/z_client_test.c @@ -20,6 +20,7 @@ #include "zenoh-pico.h" #include "zenoh-pico/api/types.h" #include "zenoh-pico/collections/string.h" +#include "zenoh-pico/utils/uuid.h" #undef NDEBUG #include @@ -116,11 +117,6 @@ void data_handler(z_loaned_sample_t *sample, void *arg) { free(res); } -_z_string_t format_id(const z_id_t *id) { - _z_slice_t id_as_bytes = _z_slice_alias_buf(id->id, _z_id_len(*id)); - return _z_string_convert_bytes(&id_as_bytes); -} - int main(int argc, char **argv) { setvbuf(stdout, NULL, _IOLBF, 1024); @@ -137,8 +133,8 @@ int main(int argc, char **argv) { z_owned_session_t s1; assert(z_open(&s1, z_move(config), NULL) == Z_OK); - _z_string_t zid1 = format_id(&(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); - printf("Session 1 with PID: %.*s\n", (int)z_string_len(&zid1), _z_string_data(&zid1)); + _z_string_t zid1 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); + printf("Session 1 with PID: %*.s\n", (int)_z_string_len(&zid1), _z_string_data(&zid1)); _z_string_clear(&zid1); // Start the read session session lease loops @@ -153,8 +149,8 @@ int main(int argc, char **argv) { z_owned_session_t s2; assert(z_open(&s2, z_move(config), NULL) == Z_OK); assert(z_internal_check(s2)); - _z_string_t zid2 = format_id(&(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); - printf("Session 2 with PID: %.*s\n", (int)z_string_len(&zid2), _z_string_data(&zid2)); + _z_string_t zid2 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); + printf("Session 2 with PID: %*.s\n", (int)_z_string_len(&zid2), _z_string_data(&zid2)); _z_string_clear(&zid2); // Start the read session session lease loops @@ -213,7 +209,7 @@ int main(int argc, char **argv) { z_view_keyexpr_t ke; z_view_keyexpr_from_str(&ke, s1_res); assert(z_declare_queryable(z_loan(s2), qle, z_loan(ke), z_move(callback), NULL) == _Z_RES_OK); - printf("Declared queryable on session 2: %ju %zu %s\n", (uintmax_t)qle->_val._entity_id, (z_zint_t)0, s1_res); + printf("Declared queryable on session 2: %ju %i %s\n", (uintmax_t)qle->_val._entity_id, 0, s1_res); qles2 = _z_list_push(qles2, qle); } @@ -315,7 +311,7 @@ int main(int argc, char **argv) { z_view_keyexpr_t ke; z_view_keyexpr_from_str(&ke, s1_res); z_get(z_loan(s1), z_loan(ke), "", z_move(callback), NULL); - printf("Queried data from session 1: %zu %s\n", (z_zint_t)0, s1_res); + printf("Queried data from session 1: %i %s\n", 0, s1_res); } } diff --git a/tests/z_data_struct_test.c b/tests/z_data_struct_test.c index 0b7cfa702..e3dff0fa5 100644 --- a/tests/z_data_struct_test.c +++ b/tests/z_data_struct_test.c @@ -233,11 +233,24 @@ void z_string_array_test(void) { z_string_array_drop(z_string_array_move(&a)); } +void z_id_to_string_test(void) { + z_id_t id; + for (uint8_t i = 0; i < sizeof(id.id); i++) { + id.id[i] = i; + } + z_owned_string_t id_str; + z_id_to_string(&id, &id_str); + assert(z_string_len(z_string_loan(&id_str)) == 32); + assert(strncmp("0f0e0d0c0b0a09080706050403020100", z_string_data(z_string_loan(&id_str)), + z_string_len(z_string_loan(&id_str))) == 0); +} + int main(void) { entry_list_test(); str_vec_list_intmap_test(); z_slice_custom_delete_test(); z_string_array_test(); + z_id_to_string_test(); return 0; } diff --git a/tests/z_peer_multicast_test.c b/tests/z_peer_multicast_test.c index 1319083ba..b0cf8e699 100644 --- a/tests/z_peer_multicast_test.c +++ b/tests/z_peer_multicast_test.c @@ -20,6 +20,7 @@ #include "zenoh-pico.h" #include "zenoh-pico/collections/slice.h" #include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/utils/uuid.h" #undef NDEBUG #include @@ -76,10 +77,8 @@ int main(int argc, char **argv) { z_owned_session_t s1; assert(z_open(&s1, z_move(config), NULL) == Z_OK); - _z_slice_t id_as_bytes = - _z_slice_alias_buf(_Z_RC_IN_VAL(z_loan(s1))->_local_zid.id, _z_id_len(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); - _z_string_t zid1 = _z_string_convert_bytes(&id_as_bytes); - printf("Session 1 with PID: %.*s\n", (int)z_string_len(&zid1), z_string_data(&zid1)); + _z_string_t zid1 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); + printf("Session 1 with PID: %*.s\n", (int)_z_string_len(&zid1), _z_string_data(&zid1)); _z_string_clear(&zid1); // Start the read session session lease loops @@ -95,10 +94,8 @@ int main(int argc, char **argv) { z_owned_session_t s2; assert(z_open(&s2, z_move(config), NULL) == Z_OK); - id_as_bytes = - _z_slice_alias_buf(_Z_RC_IN_VAL(z_loan(s2))->_local_zid.id, _z_id_len(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); - _z_string_t zid2 = _z_string_convert_bytes(&id_as_bytes); - printf("Session 2 with PID: %.*s\n", (int)z_string_len(&zid2), z_string_data(&zid2)); + _z_string_t zid2 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); + printf("Session 2 with PID: %*.s\n", (int)_z_string_len(&zid2), _z_string_data(&zid2)); _z_string_clear(&zid2); // Start the read session session lease loops @@ -119,8 +116,8 @@ int main(int argc, char **argv) { z_view_keyexpr_from_str(&ke, s1_res); z_result_t res = z_declare_subscriber(z_loan(s2), sub, z_loan(ke), z_move(callback), NULL); assert(res == _Z_RES_OK); - printf("Declared subscription on session 2: %ju %zu %s\n", (uintmax_t)z_subscriber_loan(sub)->_entity_id, - (z_zint_t)0, s1_res); + printf("Declared subscription on session 2: %ju %i %s\n", (uintmax_t)z_subscriber_loan(sub)->_entity_id, 0, + s1_res); subs2 = _z_list_push(subs2, sub); } diff --git a/tests/z_test_fragment_rx.c b/tests/z_test_fragment_rx.c index 21184df52..d5dde99a3 100644 --- a/tests/z_test_fragment_rx.c +++ b/tests/z_test_fragment_rx.c @@ -80,7 +80,7 @@ int main(int argc, char **argv) { } // Declare subscriber z_owned_closure_sample_t callback; - z_closure(&callback, data_handler); + z_closure(&callback, data_handler, NULL, NULL); z_owned_subscriber_t sub; z_view_keyexpr_t ke; z_view_keyexpr_from_str(&ke, keyexpr); diff --git a/zenohpico.pc b/zenohpico.pc index f3f450c20..0bfb73da3 100644 --- a/zenohpico.pc +++ b/zenohpico.pc @@ -3,6 +3,6 @@ prefix=/usr/local Name: zenohpico Description: URL: -Version: 1.0.20241004dev +Version: 1.0.20241113dev Cflags: -I${prefix}/include Libs: -L${prefix}/lib -lzenohpico diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 3559a1c90..f358d4659 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -37,6 +37,7 @@ file(GLOB_RECURSE Sources "../src/session/*.c" "../src/transport/*.c" "../src/utils/*.c" + "../src/system/platform_common.c" ) file (GLOB Sources_Zephyr "../src/system/zephyr/*.c") From d427b0a637ee9f7ee26f624a40b0a5288e2ca500 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Mon, 18 Nov 2024 12:38:19 +0100 Subject: [PATCH 13/17] Merge liveliness in 1.1 (#786) * Update closure handlers documentaion (#736) * Rename closure callback/dropper types (#739) * Remove legacy z_zint_t from public API (#741) * Add `export "C"` for all header files (#740) * Add `export "C"` for proper closures callbacks export * Add `export "C"` for all headers * add serialize from substr functions (#742) * Rename z_loaned_hello_handler_t to z_closure_hello_callback_t (#743) * Mark z_reply_replier_id as unstable (#745) * Add documentation about logging (#744) * Update README.md (#746) * hardcode clang-format runner to Ubuntu24.04 (#748) * fix build granularity (#747) * fix: badly named constant (#750) * fix packages * fix: update debian packaging - include libzenohpico.so in debian package - change the package name to libzenohpico in line with libzenohc - set correct debian version for pre releases - fix wrong version used in Release mode * fix: debian dev package name * fix: package version for releases (#753) * fix: debian_version for official releases otherwise they would be undefined * fix: align cpack version with zenoh-c * chore: review comments move cpack version closer to where it's used * build shared lib for packages instead of static one (#757) * Fix z_task cleanup for platforms with pthread support (#759) * Fix read/lease task cleanup (#760) * Align ID string representation with zenoh (lowercase) (#761) * Remove default parameters from z_closure (#755) * build both libraries:shared and static when packaging; (#766) add static library to dev package; * Publish debian packages (#769) * fix: add workflow to release debian packages * fix: align with zenoh-c - update package names - set version string in the same way - set DEBARCH/RPMARCH - set CPACK_PACKAGE_FILE_NAME - add -j to zip archive to not include parent folder * fix: use CPACK_PACKAGE_NAME * fix: pass package name to all build targets * fix: Don't tag release branch during dry-run * Replace exit with return in zephyr examples (#774) * Add platform_common.c to zephyr CMakeLists.txt file * Rework Zenoh ID conversion * chore: Update org secrets (#782) As per eclipse-zenoh/.eclipsefdn#18, secrets were updated to follow eclipse foundation naming convention. * Implement liveliness support (#632) * fix: merge shenanigans * fix: integration test issues * fix: missing send reply final * fix: liveliness double free --------- Co-authored-by: Alexander Bushnev Co-authored-by: DenisBiryukov91 <155981813+DenisBiryukov91@users.noreply.github.com> Co-authored-by: Denis Biryukov Co-authored-by: Diogo Mendes Matsubara Co-authored-by: Luca Cominardi --- CMakeLists.txt | 5 + docs/api.rst | 26 ++ docs/conf.py | 3 +- examples/CMakeLists.txt | 3 + examples/unix/c11/z_get_liveliness.c | 116 ++++++++ examples/unix/c11/z_liveliness.c | 121 ++++++++ examples/unix/c11/z_sub_liveliness.c | 134 +++++++++ include/zenoh-pico.h | 1 + include/zenoh-pico.h.in | 1 + include/zenoh-pico/api/handlers.h | 4 +- include/zenoh-pico/api/liveliness.h | 153 ++++++++++ include/zenoh-pico/api/macros.h | 115 +++++--- include/zenoh-pico/collections/intmap.h | 31 +- include/zenoh-pico/config.h | 1 + include/zenoh-pico/config.h.in | 1 + include/zenoh-pico/net/liveliness.h | 84 ++++++ include/zenoh-pico/net/primitives.h | 17 +- include/zenoh-pico/net/query.h | 1 + include/zenoh-pico/net/session.h | 14 +- include/zenoh-pico/protocol/keyexpr.h | 3 + include/zenoh-pico/session/liveliness.h | 71 +++++ include/zenoh-pico/session/session.h | 10 +- include/zenoh-pico/session/subscription.h | 36 ++- src/api/api.c | 16 +- src/api/liveliness.c | 144 +++++++++ src/collections/fifo_mt.c | 1 + src/collections/intmap.c | 38 +++ src/net/liveliness.c | 174 +++++++++++ src/net/primitives.c | 35 ++- src/net/query.c | 23 +- src/protocol/iobuf.c | 2 +- src/protocol/keyexpr.c | 19 +- src/session/interest.c | 49 +++- src/session/liveliness.c | 339 ++++++++++++++++++++++ src/session/push.c | 11 +- src/session/queryable.c | 2 + src/session/resource.c | 5 + src/session/rx.c | 34 ++- src/session/subscription.c | 143 ++++++--- src/session/utils.c | 13 +- tests/z_api_liveliness_test.c | 229 +++++++++++++++ tests/z_client_test.c | 4 +- tests/z_collections_test.c | 43 +++ tests/z_msgcodec_test.c | 103 ++++++- tests/z_peer_multicast_test.c | 4 +- zenohpico.pc | 2 +- 46 files changed, 2215 insertions(+), 169 deletions(-) create mode 100644 examples/unix/c11/z_get_liveliness.c create mode 100644 examples/unix/c11/z_liveliness.c create mode 100644 examples/unix/c11/z_sub_liveliness.c create mode 100644 include/zenoh-pico/api/liveliness.h create mode 100644 include/zenoh-pico/net/liveliness.h create mode 100644 include/zenoh-pico/session/liveliness.h create mode 100644 src/api/liveliness.c create mode 100644 src/net/liveliness.c create mode 100644 src/session/liveliness.c create mode 100644 tests/z_api_liveliness_test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f2df3631..7920bdc68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,6 +216,7 @@ set(Z_FEATURE_PUBLICATION 1 CACHE STRING "Toggle publication feature") set(Z_FEATURE_SUBSCRIPTION 1 CACHE STRING "Toggle subscription feature") set(Z_FEATURE_QUERY 1 CACHE STRING "Toggle query feature") set(Z_FEATURE_QUERYABLE 1 CACHE STRING "Toggle queryable feature") +set(Z_FEATURE_LIVELINESS 1 CACHE STRING "Toggle liveliness feature") set(Z_FEATURE_INTEREST 1 CACHE STRING "Toggle interests") set(Z_FEATURE_FRAGMENTATION 1 CACHE STRING "Toggle fragmentation") set(Z_FEATURE_ENCODING_VALUES 1 CACHE STRING "Toggle encoding values") @@ -246,6 +247,7 @@ message(STATUS "Building with feature confing:\n\ * SUBSCRIPTION: ${Z_FEATURE_SUBSCRIPTION}\n\ * QUERY: ${Z_FEATURE_QUERY}\n\ * QUERYABLE: ${Z_FEATURE_QUERYABLE}\n\ +* LIVELINESS: ${Z_FEATURE_LIVELINESS}\n\ * INTEREST: ${Z_FEATURE_INTEREST}\n\ * RAWETH: ${Z_FEATURE_RAWETH_TRANSPORT}") @@ -540,10 +542,12 @@ if(UNIX OR MSVC) add_executable(z_client_test ${PROJECT_SOURCE_DIR}/tests/z_client_test.c) add_executable(z_api_alignment_test ${PROJECT_SOURCE_DIR}/tests/z_api_alignment_test.c) add_executable(z_session_test ${PROJECT_SOURCE_DIR}/tests/z_session_test.c) + add_executable(z_api_liveliness_test ${PROJECT_SOURCE_DIR}/tests/z_api_liveliness_test.c) target_link_libraries(z_client_test zenohpico::lib) target_link_libraries(z_api_alignment_test zenohpico::lib) target_link_libraries(z_session_test zenohpico::lib) + target_link_libraries(z_api_liveliness_test zenohpico::lib) configure_file(${PROJECT_SOURCE_DIR}/tests/routed.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/routed.sh COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/api.sh ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/api.sh COPYONLY) @@ -552,6 +556,7 @@ if(UNIX OR MSVC) add_test(z_client_test bash ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/routed.sh z_client_test) add_test(z_api_alignment_test bash ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/api.sh z_api_alignment_test) add_test(z_session_test bash ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/api.sh z_session_test) + add_test(z_api_liveliness_test bash ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/api.sh z_api_liveliness_test) endif() endif() endif() diff --git a/docs/api.rst b/docs/api.rst index b76f7a040..7271209eb 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1271,6 +1271,32 @@ Functions .. autocfunction:: serialization.h::ze_serialize_substr +Liveliness +======================== +Types +----- +.. autoctype:: liveliness.h::z_liveliness_token_options_t +.. autoctype:: liveliness.h::z_liveliness_subscriber_options_t +.. autoctype:: liveliness.h::z_liveliness_get_options_t + +Represents a Liveliness token entity. +See details at :ref:`owned_types_concept` + +.. c:type:: z_owned_liveliness_token_t +.. c:type:: z_loaned_liveliness_token_t +.. c:type:: z_moved_liveliness_token_t + + +Functions +--------- +.. autocfunction:: liveliness.h::z_liveliness_token_options_t_default +.. autocfunction:: liveliness.h::z_liveliness_declare_token +.. autocfunction:: liveliness.h::z_liveliness_undeclare_token +.. autocfunction:: liveliness.h::z_liveliness_subscriber_options_default +.. autocfunction:: liveliness.h::z_liveliness_declare_subscriber +.. autocfunction:: liveliness.h::z_liveliness_get + + Others ====== diff --git a/docs/conf.py b/docs/conf.py index 9b980bcfb..e1ee877ba 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,7 +36,8 @@ "-DZ_FEATURE_SUBSCRIPTION=1", "-DZ_FEATURE_QUERY=1", "-DZ_FEATURE_QUERYABLE=1", - "-DZ_FEATURE_ENCODING_VALUES=1" + "-DZ_FEATURE_ENCODING_VALUES=1", + "-DZ_FEATURE_LIVELINESS=1", ] # -- Options for HTML output ------------------------------------------------- diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a001356e8..96309c42c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -41,10 +41,12 @@ if(UNIX) add_example(z_sub_channel unix/c11/z_sub_channel.c) add_example(z_sub_st unix/c11/z_sub_st.c) add_example(z_sub_attachment unix/c11/z_sub_attachment.c) + add_example(z_sub_liveliness unix/c11/z_sub_liveliness.c) add_example(z_pull unix/c11/z_pull.c) add_example(z_get unix/c11/z_get.c) add_example(z_get_channel unix/c11/z_get_channel.c) add_example(z_get_attachment unix/c11/z_get_attachment.c) + add_example(z_get_liveliness unix/c11/z_get_liveliness.c) add_example(z_queryable unix/c11/z_queryable.c) add_example(z_queryable_channel unix/c11/z_queryable_channel.c) add_example(z_queryable_attachment unix/c11/z_queryable_attachment.c) @@ -55,6 +57,7 @@ if(UNIX) add_example(z_pub_thr unix/c11/z_pub_thr.c) add_example(z_sub_thr unix/c11/z_sub_thr.c) add_example(z_bytes unix/c11/z_bytes.c) + add_example(z_liveliness unix/c11/z_liveliness.c) endif() elseif(MSVC) add_example(z_put windows/z_put.c) diff --git a/examples/unix/c11/z_get_liveliness.c b/examples/unix/c11/z_get_liveliness.c new file mode 100644 index 000000000..cefa20175 --- /dev/null +++ b/examples/unix/c11/z_get_liveliness.c @@ -0,0 +1,116 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, + +#include +#include +#include +#include + +#if Z_FEATURE_LIVELINESS == 1 && Z_FEATURE_QUERY == 1 + +int main(int argc, char **argv) { + const char *keyexpr = "group1/**"; + const char *mode = "client"; + const char *clocator = NULL; + const char *llocator = NULL; + + int opt; + while ((opt = getopt(argc, argv, "k:e:m:l:")) != -1) { + switch (opt) { + case 'k': + keyexpr = optarg; + break; + case 'e': + clocator = optarg; + break; + case 'm': + mode = optarg; + break; + case 'l': + llocator = optarg; + break; + case '?': + if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'v' || optopt == 'l') { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } else { + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + } + return 1; + default: + return -1; + } + } + + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); + if (clocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); + } + if (llocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); + } + + printf("Opening session...\n"); + z_owned_session_t s; + if (z_open(&s, z_move(config), NULL) < 0) { + printf("Unable to open session!\n"); + return -1; + } + + // Start read and lease tasks for zenoh-pico + if (zp_start_read_task(z_loan_mut(s), NULL) < 0 || zp_start_lease_task(z_loan_mut(s), NULL) < 0) { + printf("Unable to start read and lease tasks\n"); + z_session_drop(z_session_move(&s)); + return -1; + } + + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { + printf("%s is not a valid key expression", keyexpr); + return -1; + } + + printf("Sending liveliness query '%s'...\n", keyexpr); + z_owned_fifo_handler_reply_t handler; + z_owned_closure_reply_t closure; + z_fifo_channel_reply_new(&closure, &handler, 16); + if (z_liveliness_get(z_loan(s), z_loan(ke), z_move(closure), NULL) < 0) { + printf("Liveliness query failed"); + return -1; + } + z_owned_reply_t reply; + for (z_result_t res = z_recv(z_loan(handler), &reply); res == Z_OK; res = z_recv(z_loan(handler), &reply)) { + if (z_reply_is_ok(z_loan(reply))) { + const z_loaned_sample_t *sample = z_reply_ok(z_loan(reply)); + z_view_string_t key_str; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &key_str); + printf(">> Alive token ('%.*s')\n", (int)z_string_len(z_loan(key_str)), z_string_data(z_loan(key_str))); + } else { + printf("Received an error\n"); + } + } + + z_drop(z_move(reply)); + z_drop(z_move(handler)); + z_drop(z_move(s)); + return 0; +} +#else +int main(void) { + printf( + "ERROR: Zenoh pico was compiled without Z_FEATURE_QUERY or Z_FEATURE_LIVELINESS but this example requires " + "them.\n"); + return -2; +} +#endif diff --git a/examples/unix/c11/z_liveliness.c b/examples/unix/c11/z_liveliness.c new file mode 100644 index 000000000..0798621fe --- /dev/null +++ b/examples/unix/c11/z_liveliness.c @@ -0,0 +1,121 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, + +#include +#include +#include +#include +#include +#include + +#if Z_FEATURE_LIVELINESS == 1 + +static volatile int keepRunning = 1; + +void intHandler(int dummy) { + (void)dummy; + keepRunning = 0; +} + +int main(int argc, char **argv) { + const char *keyexpr = "group1/zenoh-pico"; + const char *mode = "client"; + const char *clocator = NULL; + const char *llocator = NULL; + + int opt; + while ((opt = getopt(argc, argv, "k:e:m:l:")) != -1) { + switch (opt) { + case 'k': + keyexpr = optarg; + break; + case 'e': + clocator = optarg; + break; + case 'm': + mode = optarg; + break; + case 'l': + llocator = optarg; + break; + case '?': + if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'v' || optopt == 'l') { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } else { + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + } + return 1; + default: + return -1; + } + } + + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); + if (clocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); + } + if (llocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); + } + + printf("Opening session...\n"); + z_owned_session_t s; + if (z_open(&s, z_move(config), NULL) < 0) { + printf("Unable to open session!\n"); + return -1; + } + + // Start read and lease tasks for zenoh-pico + if (zp_start_read_task(z_loan_mut(s), NULL) < 0 || zp_start_lease_task(z_loan_mut(s), NULL) < 0) { + printf("Unable to start read and lease tasks\n"); + z_session_drop(z_session_move(&s)); + return -1; + } + + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { + printf("%s is not a valid key expression", keyexpr); + return -1; + } + + printf("Declaring liveliness token '%s'...\n", keyexpr); + z_owned_liveliness_token_t token; + if (z_liveliness_declare_token(z_loan(s), &token, z_loan(ke), NULL) < 0) { + printf("Unable to create liveliness token!\n"); + exit(-1); + } + + printf("Press CTRL-C to undeclare liveliness token and quit...\n"); + signal(SIGINT, intHandler); + while (keepRunning) { + z_sleep_s(1); + } + + // LivelinessTokens are automatically closed when dropped + // Use the code below to manually undeclare it if needed + printf("Undeclaring liveliness token...\n"); + z_drop(z_move(token)); + + z_drop(z_move(s)); + return 0; +} +#else +int main(void) { + printf( + "ERROR: Zenoh pico was compiled without Z_FEATURE_QUERY or Z_FEATURE_MULTI_THREAD but this example requires " + "them.\n"); + return -2; +} +#endif diff --git a/examples/unix/c11/z_sub_liveliness.c b/examples/unix/c11/z_sub_liveliness.c new file mode 100644 index 000000000..a302d10a3 --- /dev/null +++ b/examples/unix/c11/z_sub_liveliness.c @@ -0,0 +1,134 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +#include +#include +#include +#include +#include +#include + +#if Z_FEATURE_SUBSCRIPTION == 1 && Z_FEATURE_LIVELINESS == 1 + +void data_handler(z_loaned_sample_t *sample, void *ctx) { + (void)(ctx); + z_view_string_t key_string; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &key_string); + switch (z_sample_kind(sample)) { + case Z_SAMPLE_KIND_PUT: + printf(">> [LivelinessSubscriber] New alive token ('%.*s')\n", (int)z_string_len(z_loan(key_string)), + z_string_data(z_loan(key_string))); + break; + case Z_SAMPLE_KIND_DELETE: + printf(">> [LivelinessSubscriber] Dropped token ('%.*s')\n", (int)z_string_len(z_loan(key_string)), + z_string_data(z_loan(key_string))); + break; + } +} + +int main(int argc, char **argv) { + const char *keyexpr = "group1/**"; + const char *mode = "client"; + char *clocator = NULL; + char *llocator = NULL; + bool history = false; + + int opt; + while ((opt = getopt(argc, argv, "k:e:m:l:n:h")) != -1) { + switch (opt) { + case 'k': + keyexpr = optarg; + break; + case 'e': + clocator = optarg; + break; + case 'm': + mode = optarg; + break; + case 'l': + llocator = optarg; + break; + case 'h': + history = true; + break; + case '?': + if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'l') { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } else { + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + } + return 1; + default: + return -1; + } + } + + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); + if (clocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); + } + if (llocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); + } + + printf("Opening session...\n"); + z_owned_session_t s; + if (z_open(&s, z_move(config), NULL) < 0) { + printf("Unable to open session!\n"); + return -1; + } + + // Start read and lease tasks for zenoh-pico + if (zp_start_read_task(z_loan_mut(s), NULL) < 0 || zp_start_lease_task(z_loan_mut(s), NULL) < 0) { + printf("Unable to start read and lease tasks\n"); + z_session_drop(z_session_move(&s)); + return -1; + } + + printf("Declaring liveliness subscriber on '%s'...\n", keyexpr); + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler, NULL, NULL); + z_owned_subscriber_t sub; + + z_liveliness_subscriber_options_t sub_opt; + z_liveliness_subscriber_options_default(&sub_opt); + sub_opt.history = history; + + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_liveliness_declare_subscriber(z_loan(s), &sub, z_loan(ke), z_move(callback), &sub_opt) < 0) { + printf("Unable to declare liveliness subscriber.\n"); + exit(-1); + } + + printf("Press CTRL-C to quit...\n"); + while (1) { + z_sleep_s(1); + } + + // Clean up + z_drop(z_move(sub)); + z_drop(z_move(s)); + return 0; +} +#else +int main(void) { + printf( + "ERROR: Zenoh pico was compiled without Z_FEATURE_SUBSCRIPTION and Z_FEATURE_LIVELINESS but this example " + "requires it.\n"); + return -2; +} +#endif diff --git a/include/zenoh-pico.h b/include/zenoh-pico.h index b34291ca4..75d392ee9 100644 --- a/include/zenoh-pico.h +++ b/include/zenoh-pico.h @@ -26,6 +26,7 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/api/encoding.h" #include "zenoh-pico/api/handlers.h" +#include "zenoh-pico/api/liveliness.h" #include "zenoh-pico/api/macros.h" #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/types.h" diff --git a/include/zenoh-pico.h.in b/include/zenoh-pico.h.in index bd4790b1e..b19efad0e 100644 --- a/include/zenoh-pico.h.in +++ b/include/zenoh-pico.h.in @@ -26,6 +26,7 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/api/encoding.h" #include "zenoh-pico/api/handlers.h" +#include "zenoh-pico/api/liveliness.h" #include "zenoh-pico/api/macros.h" #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/types.h" diff --git a/include/zenoh-pico/api/handlers.h b/include/zenoh-pico/api/handlers.h index c3342302a..e2d939162 100644 --- a/include/zenoh-pico/api/handlers.h +++ b/include/zenoh-pico/api/handlers.h @@ -140,10 +140,10 @@ extern "C" { /* collection_close_f */ _z_##kind_name##_mt_close, \ /* elem_owned_type */ z_owned_##item_name##_t, \ /* elem_loaned_type */ z_loaned_##item_name##_t, \ - /* elem_clone_f */ z_##item_name##_clone, \ + /* elem_clone_f */ z_##item_name##_clone, \ /* elem_move_f */ z_##item_name##_move, \ /* elem_drop_f */ z_##item_name##_drop, \ - /* elem_null */ z_internal_##item_name##_null) + /* elem_null_f */ z_internal_##item_name##_null) #define _Z_CHANNEL_DUMMY_IMPL(handler_type, handler_name, item_name) \ _Z_OWNED_TYPE_VALUE(handler_type, handler_name) \ diff --git a/include/zenoh-pico/api/liveliness.h b/include/zenoh-pico/api/liveliness.h new file mode 100644 index 000000000..43e3012fc --- /dev/null +++ b/include/zenoh-pico/api/liveliness.h @@ -0,0 +1,153 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// +#ifndef INCLUDE_ZENOH_PICO_API_LIVELINESS_H +#define INCLUDE_ZENOH_PICO_API_LIVELINESS_H + +#include +#include + +#include "olv_macros.h" +#include "zenoh-pico/api/types.h" +#include "zenoh-pico/protocol/core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t _id; + _z_keyexpr_t _key; + _z_session_weak_t _zn; +} _z_liveliness_token_t; + +_Z_OWNED_TYPE_VALUE(_z_liveliness_token_t, liveliness_token) +_Z_OWNED_FUNCTIONS_DEF(liveliness_token) + +#if Z_FEATURE_LIVELINESS == 1 + +/**************** Liveliness Token ****************/ + +/** + * The options for :c:func:`z_liveliness_declare_token()`. + */ +typedef struct z_liveliness_token_options_t { + uint8_t __dummy; +} z_liveliness_token_options_t; + +/** + * Constructs default value for :c:type:`z_liveliness_token_options_t`. + */ +z_result_t z_liveliness_token_options_t_default(z_liveliness_token_options_t *options); + +/** + * Constructs and declares a liveliness token on the network. + * + * Liveliness token subscribers on an intersecting key expression will receive a PUT sample when connectivity + * is achieved, and a DELETE sample if it's lost. + * + * Parameters: + * zs: A Zenos session to declare the liveliness token. + * token: An uninitialized memory location where liveliness token will be constructed. + * keyexpr: A keyexpr to declare a liveliess token for. + * options: Liveliness token declaration options. + * + * Return: + * ``0`` if put operation is successful, ``negative value`` otherwise. + */ +z_result_t z_liveliness_declare_token(const z_loaned_session_t *zs, z_owned_liveliness_token_t *token, + const z_loaned_keyexpr_t *keyexpr, const z_liveliness_token_options_t *options); + +/** + * Undeclare a liveliness token, notifying subscribers of its destruction. + * + * Parameters: + * token: Moved :c:type:`z_owned_liveliness_token_t` to undeclare. + * + * Return: + * ``0`` if put operation is successful, ``negative value`` otherwise. + */ +z_result_t z_liveliness_undeclare_token(z_moved_liveliness_token_t *token); + +/**************** Liveliness Subscriber ****************/ + +#if Z_FEATURE_SUBSCRIPTION == 1 +/** + * The options for :c:func:`z_liveliness_declare_subscriber()` + */ +typedef struct z_liveliness_subscriber_options_t { + bool history; +} z_liveliness_subscriber_options_t; + +/** + * Constucts default value for :c:type:`z_liveliness_subscriber_options_t`. + */ +z_result_t z_liveliness_subscriber_options_default(z_liveliness_subscriber_options_t *options); + +/** + * Declares a subscriber on liveliness tokens that intersect `keyexpr`. + * + * Parameters: + * zs: The Zenoh session. + * sub: An uninitialized memory location where subscriber will be constructed. + * keyexpr: The key expression to subscribe to. + * callback: The callback function that will be called each time a liveliness token status is changed. + * options: The options to be passed to the liveliness subscriber declaration. + * + * Return: + * ``0`` if put operation is successful, ``negative value`` otherwise. + */ +z_result_t z_liveliness_declare_subscriber(const z_loaned_session_t *zs, z_owned_subscriber_t *sub, + const z_loaned_keyexpr_t *keyexpr, z_moved_closure_sample_t *callback, + z_liveliness_subscriber_options_t *options); +#endif // Z_FEATURE_SUBSCRIPTION == 1 + +/**************** Liveliness Query ****************/ + +#if Z_FEATURE_QUERY == 1 +/** + * The options for :c:func:`z_liveliness_get()` + */ +typedef struct z_liveliness_get_options_t { + uint32_t timeout_ms; +} z_liveliness_get_options_t; + +/** + * Constructs default value :c:type:`z_liveliness_get_options_t`. + */ +z_result_t z_liveliness_get_options_default(z_liveliness_get_options_t *options); + +/** + * Queries liveliness tokens currently on the network with a key expression intersecting with `keyexpr`. + * + * Parameters: + * zs: The Zenoh session. + * keyexpr: The key expression to query liveliness tokens for. + * callback: The callback function that will be called for each received reply. + * options: Additional options for the liveliness get operation. + * + * Return: + * ``0`` if put operation is successful, ``negative value`` otherwise. + */ +z_result_t z_liveliness_get(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, + z_moved_closure_reply_t *callback, z_liveliness_get_options_t *options); + +#endif // Z_FEATURE_QUERY == 1 + +#endif // Z_FEATURE_LIVELINESS == 1 + +#ifdef __cplusplus +} +#endif + +#endif // INCLUDE_ZENOH_PICO_API_LIVELINESS_H diff --git a/include/zenoh-pico/api/macros.h b/include/zenoh-pico/api/macros.h index ca17781d0..f60ba22bd 100644 --- a/include/zenoh-pico/api/macros.h +++ b/include/zenoh-pico/api/macros.h @@ -15,6 +15,7 @@ #define ZENOH_PICO_API_MACROS_H #include "zenoh-pico/api/handlers.h" +#include "zenoh-pico/api/liveliness.h" #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/serialization.h" #include "zenoh-pico/api/types.h" @@ -43,6 +44,7 @@ z_owned_subscriber_t : z_subscriber_loan, \ z_owned_publisher_t : z_publisher_loan, \ z_owned_queryable_t : z_queryable_loan, \ + z_owned_liveliness_token_t : z_liveliness_token_loan, \ z_owned_reply_t : z_reply_loan, \ z_owned_hello_t : z_hello_loan, \ z_owned_string_t : z_string_loan, \ @@ -74,28 +76,29 @@ )(&x) #define z_loan_mut(x) _Generic((x), \ - z_owned_keyexpr_t : z_keyexpr_loan_mut, \ - z_owned_config_t : z_config_loan_mut, \ - z_owned_session_t : z_session_loan_mut, \ - z_owned_publisher_t : z_publisher_loan_mut, \ - z_owned_queryable_t : z_queryable_loan_mut, \ - z_owned_subscriber_t : z_subscriber_loan_mut, \ - z_owned_reply_t : z_reply_loan_mut, \ - z_owned_hello_t : z_hello_loan_mut, \ - z_owned_string_t : z_string_loan_mut, \ - z_view_string_t : z_view_string_loan_mut, \ - z_owned_string_array_t : z_string_array_loan_mut, \ - z_owned_sample_t : z_sample_loan_mut, \ - z_owned_query_t : z_query_loan_mut, \ - z_owned_slice_t : z_slice_loan_mut, \ - z_view_slice_t : z_view_slice_loan_mut, \ - z_owned_bytes_t : z_bytes_loan_mut, \ - z_owned_task_t : z_task_loan_mut, \ - z_owned_mutex_t : z_mutex_loan_mut, \ - z_owned_condvar_t : z_condvar_loan_mut, \ - z_owned_reply_err_t : z_reply_err_loan_mut, \ - ze_owned_serializer_t : ze_serializer_loan_mut, \ - z_owned_bytes_writer_t : z_bytes_writer_loan_mut \ + z_owned_keyexpr_t : z_keyexpr_loan_mut, \ + z_owned_config_t : z_config_loan_mut, \ + z_owned_session_t : z_session_loan_mut, \ + z_owned_publisher_t : z_publisher_loan_mut, \ + z_owned_queryable_t : z_queryable_loan_mut, \ + z_owned_liveliness_token_t : z_liveliness_token_loan_mut, \ + z_owned_subscriber_t : z_subscriber_loan_mut, \ + z_owned_reply_t : z_reply_loan_mut, \ + z_owned_hello_t : z_hello_loan_mut, \ + z_owned_string_t : z_string_loan_mut, \ + z_view_string_t : z_view_string_loan_mut, \ + z_owned_string_array_t : z_string_array_loan_mut, \ + z_owned_sample_t : z_sample_loan_mut, \ + z_owned_query_t : z_query_loan_mut, \ + z_owned_slice_t : z_slice_loan_mut, \ + z_view_slice_t : z_view_slice_loan_mut, \ + z_owned_bytes_t : z_bytes_loan_mut, \ + z_owned_task_t : z_task_loan_mut, \ + z_owned_mutex_t : z_mutex_loan_mut, \ + z_owned_condvar_t : z_condvar_loan_mut, \ + z_owned_reply_err_t : z_reply_err_loan_mut, \ + ze_owned_serializer_t : ze_serializer_loan_mut, \ + z_owned_bytes_writer_t : z_bytes_writer_loan_mut \ )(&x) /** @@ -111,6 +114,7 @@ z_moved_subscriber_t* : z_subscriber_drop, \ z_moved_publisher_t* : z_publisher_drop, \ z_moved_queryable_t* : z_queryable_drop, \ + z_moved_liveliness_token_t* : z_liveliness_token_drop, \ z_moved_reply_t* : z_reply_drop, \ z_moved_hello_t* : z_hello_drop, \ z_moved_string_t* : z_string_drop, \ @@ -150,29 +154,30 @@ */ #define z_internal_check(x) _Generic((x), \ - z_owned_keyexpr_t : z_internal_keyexpr_check, \ - z_owned_reply_err_t : z_internal_reply_err_check, \ - z_owned_config_t : z_internal_config_check, \ - z_owned_session_t : z_internal_session_check, \ - z_owned_subscriber_t : z_internal_subscriber_check, \ - z_owned_publisher_t : z_internal_publisher_check, \ - z_owned_queryable_t : z_internal_queryable_check, \ - z_owned_reply_t : z_internal_reply_check, \ - z_owned_hello_t : z_internal_hello_check, \ - z_owned_string_t : z_internal_string_check, \ - z_owned_string_array_t : z_internal_string_array_check, \ - z_owned_closure_sample_t : z_internal_closure_sample_check, \ - z_owned_closure_query_t : z_internal_closure_query_check, \ - z_owned_closure_reply_t : z_internal_closure_reply_check, \ - z_owned_closure_hello_t : z_internal_closure_hello_check, \ - z_owned_closure_zid_t : z_internal_closure_zid_check, \ - z_owned_slice_t : z_internal_slice_check, \ - z_owned_bytes_t : z_internal_bytes_check, \ - z_owned_sample_t : z_internal_sample_check, \ - z_owned_query_t : z_internal_query_check, \ - z_owned_encoding_t : z_internal_encoding_check, \ - ze_owned_serializer_t : ze_internal_serializer_check, \ - z_owned_bytes_writer_t : z_internal_bytes_writer_check \ + z_owned_keyexpr_t : z_internal_keyexpr_check, \ + z_owned_reply_err_t : z_internal_reply_err_check, \ + z_owned_config_t : z_internal_config_check, \ + z_owned_session_t : z_internal_session_check, \ + z_owned_subscriber_t : z_internal_subscriber_check, \ + z_owned_publisher_t : z_internal_publisher_check, \ + z_owned_queryable_t : z_internal_queryable_check, \ + z_owned_liveliness_token_t : z_internal_liveliness_token_check, \ + z_owned_reply_t : z_internal_reply_check, \ + z_owned_hello_t : z_internal_hello_check, \ + z_owned_string_t : z_internal_string_check, \ + z_owned_string_array_t : z_internal_string_array_check, \ + z_owned_closure_sample_t : z_internal_closure_sample_check, \ + z_owned_closure_query_t : z_internal_closure_query_check, \ + z_owned_closure_reply_t : z_internal_closure_reply_check, \ + z_owned_closure_hello_t : z_internal_closure_hello_check, \ + z_owned_closure_zid_t : z_internal_closure_zid_check, \ + z_owned_slice_t : z_internal_slice_check, \ + z_owned_bytes_t : z_internal_bytes_check, \ + z_owned_sample_t : z_internal_sample_check, \ + z_owned_query_t : z_internal_query_check, \ + z_owned_encoding_t : z_internal_encoding_check, \ + ze_owned_serializer_t : ze_internal_serializer_check, \ + z_owned_bytes_writer_t : z_internal_bytes_writer_check \ )(&x) /** @@ -225,6 +230,7 @@ z_owned_subscriber_t : z_subscriber_move, \ z_owned_publisher_t : z_publisher_move, \ z_owned_queryable_t : z_queryable_move, \ + z_owned_liveliness_token_t : z_liveliness_token_move, \ z_owned_reply_t : z_reply_move, \ z_owned_hello_t : z_hello_move, \ z_owned_string_t : z_string_move, \ @@ -283,6 +289,7 @@ z_owned_publisher_t *: z_publisher_take, \ z_owned_query_t *: z_query_take, \ z_owned_queryable_t *: z_queryable_take, \ + z_owned_liveliness_token_t *: z_liveliness_token_take, \ z_owned_reply_t *: z_reply_take, \ z_owned_reply_err_t *: z_reply_err_take, \ z_owned_ring_handler_query_t *: z_ring_handler_query_take, \ @@ -336,6 +343,7 @@ z_owned_config_t * : z_internal_config_null, \ z_owned_subscriber_t * : z_internal_subscriber_null, \ z_owned_queryable_t * : z_internal_queryable_null, \ + z_owned_liveliness_token_t * : z_internal_liveliness_token_null, \ z_owned_query_t * : z_internal_query_null, \ z_owned_reply_t * : z_internal_reply_null, \ z_owned_hello_t * : z_internal_hello_null, \ @@ -389,6 +397,7 @@ inline const z_loaned_session_t* z_loan(const z_owned_session_t& x) { return z_s inline const z_loaned_subscriber_t* z_loan(const z_owned_subscriber_t& x) { return z_subscriber_loan(&x); } inline const z_loaned_publisher_t* z_loan(const z_owned_publisher_t& x) { return z_publisher_loan(&x); } inline const z_loaned_queryable_t* z_loan(const z_owned_queryable_t& x) { return z_queryable_loan(&x); } +inline const z_loaned_liveliness_token_t* z_loan(const z_owned_liveliness_token_t& x) { return z_liveliness_token_loan(&x); } inline const z_loaned_reply_t* z_loan(const z_owned_reply_t& x) { return z_reply_loan(&x); } inline const z_loaned_hello_t* z_loan(const z_owned_hello_t& x) { return z_hello_loan(&x); } inline const z_loaned_string_t* z_loan(const z_owned_string_t& x) { return z_string_loan(&x); } @@ -425,6 +434,7 @@ inline z_loaned_config_t* z_loan_mut(z_owned_config_t& x) { return z_config_loan inline z_loaned_session_t* z_loan_mut(z_owned_session_t& x) { return z_session_loan_mut(&x); } inline z_loaned_publisher_t* z_loan_mut(z_owned_publisher_t& x) { return z_publisher_loan_mut(&x); } inline z_loaned_queryable_t* z_loan_mut(z_owned_queryable_t& x) { return z_queryable_loan_mut(&x); } +inline z_loaned_liveliness_token_t* z_loan_mut(z_owned_liveliness_token_t& x) { return z_liveliness_token_loan_mut(&x); } inline z_loaned_subscriber_t* z_loan_mut(z_owned_subscriber_t& x) { return z_subscriber_loan_mut(&x); } inline z_loaned_reply_t* z_loan_mut(z_owned_reply_t& x) { return z_reply_loan_mut(&x); } inline z_loaned_hello_t* z_loan_mut(z_owned_hello_t& x) { return z_hello_loan_mut(&x); } @@ -451,6 +461,7 @@ inline void z_drop(z_moved_keyexpr_t* v) { z_keyexpr_drop(v); } inline void z_drop(z_moved_config_t* v) { z_config_drop(v); } inline void z_drop(z_moved_subscriber_t* v) { z_subscriber_drop(v); } inline void z_drop(z_moved_queryable_t* v) { z_queryable_drop(v); } +inline void z_drop(z_moved_liveliness_token_t* v) { z_liveliness_token_drop(v); } inline void z_drop(z_moved_reply_t* v) { z_reply_drop(v); } inline void z_drop(z_moved_hello_t* v) { z_hello_drop(v); } inline void z_drop(z_moved_string_t* v) { z_string_drop(v); } @@ -484,6 +495,7 @@ inline void z_internal_null(z_owned_keyexpr_t* v) { z_internal_keyexpr_null(v); inline void z_internal_null(z_owned_config_t* v) { z_internal_config_null(v); } inline void z_internal_null(z_owned_subscriber_t* v) { z_internal_subscriber_null(v); } inline void z_internal_null(z_owned_queryable_t* v) { z_internal_queryable_null(v); } +inline void z_internal_null(z_owned_liveliness_token_t* v) { z_internal_liveliness_token_null(v); } inline void z_internal_null(z_owned_query_t* v) { z_internal_query_null(v); } inline void z_internal_null(z_owned_sample_t* v) { z_internal_sample_null(v); } inline void z_internal_null(z_owned_reply_t* v) { z_internal_reply_null(v); } @@ -513,6 +525,7 @@ inline bool z_internal_check(const z_owned_keyexpr_t& v) { return z_internal_key inline bool z_internal_check(const z_owned_config_t& v) { return z_internal_config_check(&v); } inline bool z_internal_check(const z_owned_subscriber_t& v) { return z_internal_subscriber_check(&v); } inline bool z_internal_check(const z_owned_queryable_t& v) { return z_internal_queryable_check(&v); } +inline bool z_internal_check(const z_owned_liveliness_token_t& v) { return z_internal_liveliness_token_check(&v); } inline bool z_internal_check(const z_owned_reply_t& v) { return z_internal_reply_check(&v); } inline bool z_internal_check(const z_owned_query_t& v) { return z_internal_query_check(&v); } inline bool z_internal_check(const z_owned_hello_t& v) { return z_internal_hello_check(&v); } @@ -643,6 +656,7 @@ inline z_moved_keyexpr_t* z_move(z_owned_keyexpr_t& x) { return z_keyexpr_move(& inline z_moved_publisher_t* z_move(z_owned_publisher_t& x) { return z_publisher_move(&x); } inline z_moved_query_t* z_move(z_owned_query_t& x) { return z_query_move(&x); } inline z_moved_queryable_t* z_move(z_owned_queryable_t& x) { return z_queryable_move(&x); } +inline z_moved_liveliness_token_t* z_move(z_owned_liveliness_token_t& x) { return z_liveliness_token_move(&x); } inline z_moved_reply_t* z_move(z_owned_reply_t& x) { return z_reply_move(&x); } inline z_moved_sample_t* z_move(z_owned_sample_t& x) { return z_sample_move(&x); } inline z_moved_session_t* z_move(z_owned_session_t& x) { return z_session_move(&x); } @@ -670,6 +684,9 @@ inline void z_take(z_owned_keyexpr_t* this_, z_moved_keyexpr_t* v) { z_keyexpr_t inline void z_take(z_owned_config_t* this_, z_moved_config_t* v) { z_config_take(this_, v); } inline void z_take(z_owned_subscriber_t* this_, z_moved_subscriber_t* v) { return z_subscriber_take(this_, v); } inline void z_take(z_owned_queryable_t* this_, z_moved_queryable_t* v) { return z_queryable_take(this_, v); } +inline void z_take(z_owned_liveliness_token_t* this_, z_moved_liveliness_token_t* v) { + return z_liveliness_token_take(this_, v); +} inline void z_take(z_owned_reply_t* this_, z_moved_reply_t* v) { z_reply_take(this_, v); } inline void z_take(z_owned_hello_t* this_, z_moved_hello_t* v) { z_hello_take(this_, v); } inline void z_take(z_owned_string_t* this_, z_moved_string_t* v) { z_string_take(this_, v); } @@ -803,6 +820,14 @@ struct z_owned_to_loaned_type_t { typedef z_loaned_queryable_t type; }; template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_liveliness_token_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_liveliness_token_t type; +}; +template <> struct z_loaned_to_owned_type_t { typedef z_owned_reply_t type; }; diff --git a/include/zenoh-pico/collections/intmap.h b/include/zenoh-pico/collections/intmap.h index 136cf9772..98ea17379 100644 --- a/include/zenoh-pico/collections/intmap.h +++ b/include/zenoh-pico/collections/intmap.h @@ -30,7 +30,7 @@ extern "C" { #define _Z_DEFAULT_INT_MAP_CAPACITY 16 /** - * An entry of an hashmap with integer keys. + * An entry of a hashmap with integer keys. * * Members: * size_t key: the hashed key of the value @@ -54,6 +54,17 @@ typedef struct { _z_list_t **_vals; } _z_int_void_map_t; +/** + * An iterator of an hashmap with integer keys. + */ +typedef struct { + _z_int_void_map_entry_t *_entry; + + const _z_int_void_map_t *_map; + size_t _idx; + _z_list_t *_list_ptr; +} _z_int_void_map_iterator_t; + void _z_int_void_map_init(_z_int_void_map_t *map, size_t capacity); _z_int_void_map_t _z_int_void_map_make(size_t capacity); @@ -71,6 +82,11 @@ _z_int_void_map_t _z_int_void_map_clone(const _z_int_void_map_t *src, z_element_ void _z_int_void_map_clear(_z_int_void_map_t *map, z_element_free_f f); void _z_int_void_map_free(_z_int_void_map_t **map, z_element_free_f f); +_z_int_void_map_iterator_t _z_int_void_map_iterator_make(const _z_int_void_map_t *map); +bool _z_int_void_map_iterator_next(_z_int_void_map_iterator_t *iter); +size_t _z_int_void_map_iterator_key(const _z_int_void_map_iterator_t *iter); +void *_z_int_void_map_iterator_value(const _z_int_void_map_iterator_t *iter); + #define _Z_INT_MAP_DEFINE(name, type) \ typedef _z_int_void_map_entry_t name##_intmap_entry_t; \ static inline void name##_intmap_entry_elem_free(void **e) { \ @@ -89,6 +105,7 @@ void _z_int_void_map_free(_z_int_void_map_t **map, z_element_free_f f); return dst; \ } \ typedef _z_int_void_map_t name##_intmap_t; \ + typedef _z_int_void_map_iterator_t name##_intmap_iterator_t; \ static inline void name##_intmap_init(name##_intmap_t *m) { \ _z_int_void_map_init(m, _Z_DEFAULT_INT_MAP_CAPACITY); \ } \ @@ -115,6 +132,18 @@ void _z_int_void_map_free(_z_int_void_map_t **map, z_element_free_f f); } \ static inline void name##_intmap_free(name##_intmap_t **m) { \ _z_int_void_map_free(m, name##_intmap_entry_elem_free); \ + } \ + static inline name##_intmap_iterator_t name##_intmap_iterator_make(const name##_intmap_t *m) { \ + return _z_int_void_map_iterator_make(m); \ + } \ + static inline bool name##_intmap_iterator_next(name##_intmap_iterator_t *iter) { \ + return _z_int_void_map_iterator_next(iter); \ + } \ + static inline size_t name##_intmap_iterator_key(const name##_intmap_iterator_t *iter) { \ + return _z_int_void_map_iterator_key(iter); \ + } \ + static inline type *name##_intmap_iterator_value(const name##_intmap_iterator_t *iter) { \ + return (type *)_z_int_void_map_iterator_value(iter); \ } #ifdef __cplusplus diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index 060afd51b..4e4ae9f99 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -27,6 +27,7 @@ #define Z_FEATURE_SUBSCRIPTION 1 #define Z_FEATURE_QUERY 1 #define Z_FEATURE_QUERYABLE 1 +#define Z_FEATURE_LIVELINESS 1 #define Z_FEATURE_RAWETH_TRANSPORT 0 #define Z_FEATURE_INTEREST 1 #define Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION 0 diff --git a/include/zenoh-pico/config.h.in b/include/zenoh-pico/config.h.in index 4e75ac0cb..48929af42 100644 --- a/include/zenoh-pico/config.h.in +++ b/include/zenoh-pico/config.h.in @@ -27,6 +27,7 @@ #define Z_FEATURE_SUBSCRIPTION @Z_FEATURE_SUBSCRIPTION@ #define Z_FEATURE_QUERY @Z_FEATURE_QUERY@ #define Z_FEATURE_QUERYABLE @Z_FEATURE_QUERYABLE@ +#define Z_FEATURE_LIVELINESS @Z_FEATURE_LIVELINESS@ #define Z_FEATURE_RAWETH_TRANSPORT @Z_FEATURE_RAWETH_TRANSPORT@ #define Z_FEATURE_INTEREST @Z_FEATURE_INTEREST@ #define Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION @Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION@ diff --git a/include/zenoh-pico/net/liveliness.h b/include/zenoh-pico/net/liveliness.h new file mode 100644 index 000000000..3fb7c6ded --- /dev/null +++ b/include/zenoh-pico/net/liveliness.h @@ -0,0 +1,84 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, + +#ifndef INCLUDE_ZENOH_PICO_NET_LIVELINESS_H +#define INCLUDE_ZENOH_PICO_NET_LIVELINESS_H + +#include "zenoh-pico/api/liveliness.h" +#include "zenoh-pico/net/session.h" +#include "zenoh-pico/net/subscribe.h" +#include "zenoh-pico/protocol/core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if Z_FEATURE_LIVELINESS == 1 + +z_result_t _z_declare_liveliness_token(const _z_session_rc_t *zn, _z_liveliness_token_t *ret_token, + _z_keyexpr_t *keyexpr); +z_result_t _z_undeclare_liveliness_token(_z_liveliness_token_t *token); + +#if Z_FEATURE_SUBSCRIPTION == 1 +/** + * Declare a :c:type:`_z_subscriber_t` for the given liveliness key. + * + * Parameters: + * zn: The zenoh-net session. The caller keeps its ownership. + * keyexpr: The resource key to subscribe. The callee gets the ownership of any allocated value. + * callback: The callback function that will be called each time a matching liveliness token changed. + * history: Enable current interest to return history tokens. + * arg: A pointer that will be passed to the **callback** on each call. + * + * Returns: + * The created :c:type:`_z_subscriber_t` (in null state if the declaration failed). + */ +_z_subscriber_t _z_declare_liveliness_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t *keyexpr, + _z_closure_sample_callback_t callback, _z_drop_handler_t dropper, + bool history, void *arg); + +/** + * Undeclare a liveliness :c:type:`_z_subscriber_t`. + * + * Parameters: + * sub: The :c:type:`_z_subscriber_t` to undeclare. The callee releases the + * subscriber upon successful return. + * Returns: + * 0 if success, or a negative value identifying the error. + */ +z_result_t _z_undeclare_liveliness_subscriber(_z_subscriber_t *sub); +#endif // Z_FEATURE_SUBSCRIPTION == 1 + +#if Z_FEATURE_QUERY == 1 +/** + * Query liveliness token state. + * + * Parameters: + * zn: The zenoh-net session. The caller keeps its ownership. + * keyexpr: The resource key to liveliness token. + * callback: The callback function that will be called on reception of replies for this query. + * dropper: The callback function that will be called on upon completion of the callback. + * arg: A pointer that will be passed to the **callback** on each call. + * timeout_ms: The timeout value of this query. + */ +z_result_t _z_liveliness_query(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_closure_reply_callback_t callback, + _z_drop_handler_t dropper, void *arg, uint64_t timeout_ms); +#endif // Z_FEATURE_QUERY == 1 + +#endif // Z_FEATURE_LIVELINESS == 1 + +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDE_ZENOH_PICO_NET_LIVELINESS_H */ diff --git a/include/zenoh-pico/net/primitives.h b/include/zenoh-pico/net/primitives.h index 95b47078b..53db370e1 100644 --- a/include/zenoh-pico/net/primitives.h +++ b/include/zenoh-pico/net/primitives.h @@ -24,7 +24,10 @@ #include "zenoh-pico/net/session.h" #include "zenoh-pico/net/subscribe.h" #include "zenoh-pico/protocol/core.h" -#include "zenoh-pico/utils/config.h" + +#ifdef __cplusplus +extern "C" { +#endif #ifdef __cplusplus extern "C" { @@ -76,6 +79,18 @@ uint16_t _z_declare_resource(_z_session_t *zn, _z_keyexpr_t keyexpr); */ z_result_t _z_undeclare_resource(_z_session_t *zn, uint16_t rid); +/** + * Declare keyexpr if it is necessary and allowed. + * Returns updated keyexpr. + * + * Parameters: + * zn: The zenoh-net session. The caller keeps its ownership. + * keyexpr: The resource key to declare. + * Returns: + * Updated keyexpr. + */ +_z_keyexpr_t _z_update_keyexpr_to_declared(_z_session_t *zs, _z_keyexpr_t keyexpr); + #if Z_FEATURE_PUBLICATION == 1 /** * Declare a :c:type:`_z_publisher_t` for the given resource key. diff --git a/include/zenoh-pico/net/query.h b/include/zenoh-pico/net/query.h index 82dbe9d8c..433fc1217 100644 --- a/include/zenoh-pico/net/query.h +++ b/include/zenoh-pico/net/query.h @@ -44,6 +44,7 @@ static inline bool _z_query_check(const _z_query_t *query) { return _z_keyexpr_check(&query->_key) || _z_value_check(&query->_value) || _z_bytes_check(&query->_attachment) || _z_string_check(&query->_parameters); } +z_result_t _z_query_send_reply_final(_z_query_t *q); void _z_query_clear(_z_query_t *q); z_result_t _z_query_copy(_z_query_t *dst, const _z_query_t *src); void _z_query_free(_z_query_t **query); diff --git a/include/zenoh-pico/net/session.h b/include/zenoh-pico/net/session.h index 1d3d1e6a5..5ee1556dc 100644 --- a/include/zenoh-pico/net/session.h +++ b/include/zenoh-pico/net/session.h @@ -21,6 +21,7 @@ #include "zenoh-pico/collections/list.h" #include "zenoh-pico/config.h" #include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/session/liveliness.h" #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/session.h" #include "zenoh-pico/session/subscription.h" @@ -56,11 +57,20 @@ typedef struct _z_session_t { // Session subscriptions #if Z_FEATURE_SUBSCRIPTION == 1 - _z_subscription_rc_list_t *_local_subscriptions; - _z_subscription_rc_list_t *_remote_subscriptions; + _z_subscription_rc_list_t *_subscriptions; + _z_subscription_rc_list_t *_liveliness_subscriptions; #if Z_FEATURE_RX_CACHE == 1 _z_subscription_cache_t _subscription_cache; #endif +#endif + +#if Z_FEATURE_LIVELINESS == 1 + _z_keyexpr_intmap_t _local_tokens; + _z_keyexpr_intmap_t _remote_tokens; +#if Z_FEATURE_QUERY == 1 + uint32_t _liveliness_query_id; + _z_liveliness_pending_query_intmap_t _liveliness_pending_queries; +#endif #endif // Session queryables diff --git a/include/zenoh-pico/protocol/keyexpr.h b/include/zenoh-pico/protocol/keyexpr.h index 0c347c251..f8b57a46c 100644 --- a/include/zenoh-pico/protocol/keyexpr.h +++ b/include/zenoh-pico/protocol/keyexpr.h @@ -42,8 +42,11 @@ static inline _z_keyexpr_t _z_keyexpr_alias(const _z_keyexpr_t src) { _z_keyexpr_t _z_keyexpr_from_string(uint16_t rid, _z_string_t *str); _z_keyexpr_t _z_keyexpr_from_substr(uint16_t rid, const char *str, size_t len); +size_t _z_keyexpr_size(_z_keyexpr_t *p); z_result_t _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src); _z_keyexpr_t _z_keyexpr_duplicate(const _z_keyexpr_t *src); +_z_keyexpr_t *_z_keyexpr_clone(const _z_keyexpr_t *src); +_z_keyexpr_t _z_keyexpr_alias(_z_keyexpr_t src); /// Returns either keyexpr defined by id + mapping with null suffix if try_declared is true and id is non-zero, /// or keyexpr defined by its suffix only, with 0 id and no mapping. This is to be used only when forwarding /// keyexpr in user api to properly separate declared keyexpr from its suffix. diff --git a/include/zenoh-pico/session/liveliness.h b/include/zenoh-pico/session/liveliness.h new file mode 100644 index 000000000..a3df1dc04 --- /dev/null +++ b/include/zenoh-pico/session/liveliness.h @@ -0,0 +1,71 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +#ifndef ZENOH_PICO_SESSION_LIVELINESS_H +#define ZENOH_PICO_SESSION_LIVELINESS_H + +#include "zenoh-pico/session/session.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if Z_FEATURE_LIVELINESS == 1 +typedef struct _z_session_t _z_session_t; + +typedef struct { + _z_keyexpr_t _key; + _z_closure_reply_callback_t _callback; + _z_drop_handler_t _dropper; + void *_arg; +} _z_liveliness_pending_query_t; + +void _z_liveliness_pending_query_clear(_z_liveliness_pending_query_t *res); +void _z_liveliness_pending_query_copy(_z_liveliness_pending_query_t *dst, const _z_liveliness_pending_query_t *src); +_z_liveliness_pending_query_t *_z_liveliness_pending_query_clone(const _z_liveliness_pending_query_t *src); + +_Z_ELEM_DEFINE(_z_liveliness_pending_query, _z_liveliness_pending_query_t, _z_noop_size, + _z_liveliness_pending_query_clear, _z_liveliness_pending_query_copy, _z_noop_move) +_Z_INT_MAP_DEFINE(_z_liveliness_pending_query, _z_liveliness_pending_query_t) + +uint32_t _z_liveliness_get_query_id(_z_session_t *zn); + +z_result_t _z_liveliness_register_token(_z_session_t *zn, uint32_t id, const _z_keyexpr_t *keyexpr); +void _z_liveliness_unregister_token(_z_session_t *zn, uint32_t id); + +#if Z_FEATURE_SUBSCRIPTION == 1 +z_result_t _z_liveliness_subscription_declare(_z_session_t *zn, uint32_t id, const _z_keyexpr_t *keyexpr, + const _z_timestamp_t *timestamp); +z_result_t _z_liveliness_subscription_undeclare(_z_session_t *zn, uint32_t id, const _z_timestamp_t *timestamp); +z_result_t _z_liveliness_subscription_trigger_history(_z_session_t *zn, const _z_keyexpr_t *keyexpr); +#endif + +#if Z_FEATURE_QUERY == 1 +z_result_t _z_liveliness_register_pending_query(_z_session_t *zn, uint32_t id, _z_liveliness_pending_query_t *pen_qry); +void _z_liveliness_unregister_pending_query(_z_session_t *zn, uint32_t id); +#endif + +z_result_t _z_liveliness_process_token_declare(_z_session_t *zn, const _z_n_msg_declare_t *decl); +z_result_t _z_liveliness_process_token_undeclare(_z_session_t *zn, const _z_n_msg_declare_t *decl); +z_result_t _z_liveliness_process_declare_final(_z_session_t *zn, const _z_n_msg_declare_t *decl); + +void _z_liveliness_init(_z_session_t *zn); +void _z_liveliness_clear(_z_session_t *zn); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZENOH_PICO_SESSION_LIVELINESS_H */ diff --git a/include/zenoh-pico/session/session.h b/include/zenoh-pico/session/session.h index e1a39584e..d1fefc934 100644 --- a/include/zenoh-pico/session/session.h +++ b/include/zenoh-pico/session/session.h @@ -35,8 +35,10 @@ extern "C" { */ typedef void (*_z_drop_handler_t)(void *arg); -#define _Z_RESOURCE_IS_REMOTE 0 -#define _Z_RESOURCE_IS_LOCAL 1 +typedef enum { + _Z_SUBSCRIBER_KIND_SUBSCRIBER = 0, + _Z_SUBSCRIBER_KIND_LIVELINESS_SUBSCRIBER = 1, +} _z_subscriber_kind_t; typedef struct { _z_keyexpr_t _key; @@ -48,10 +50,14 @@ bool _z_resource_eq(const _z_resource_t *one, const _z_resource_t *two); void _z_resource_clear(_z_resource_t *res); void _z_resource_copy(_z_resource_t *dst, const _z_resource_t *src); void _z_resource_free(_z_resource_t **res); +size_t _z_resource_size(_z_resource_t *p); _Z_ELEM_DEFINE(_z_resource, _z_resource_t, _z_noop_size, _z_resource_clear, _z_resource_copy, _z_noop_move) _Z_LIST_DEFINE(_z_resource, _z_resource_t) +_Z_ELEM_DEFINE(_z_keyexpr, _z_keyexpr_t, _z_keyexpr_size, _z_keyexpr_clear, _z_keyexpr_copy, _z_keyexpr_move) +_Z_INT_MAP_DEFINE(_z_keyexpr, _z_keyexpr_t) + // Forward declaration to avoid cyclical include typedef struct _z_sample_t _z_sample_t; diff --git a/include/zenoh-pico/session/subscription.h b/include/zenoh-pico/session/subscription.h index a103b0c21..b70871b30 100644 --- a/include/zenoh-pico/session/subscription.h +++ b/include/zenoh-pico/session/subscription.h @@ -19,6 +19,10 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/session/session.h" +#ifdef __cplusplus +extern "C" { +#endif + // Forward declaration to avoid cyclical include typedef struct _z_session_t _z_session_t; @@ -38,14 +42,19 @@ typedef struct { size_t sub_nb; } _z_subscription_cache_t; -#ifdef __cplusplus -extern "C" { -#endif - /*------------------ Subscription ------------------*/ -void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, - _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - _z_bytes_t *attachment, z_reliability_t reliability); +z_result_t _z_trigger_subscriptions_put(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, + _z_encoding_t *encoding, const _z_timestamp_t *timestamp, const _z_n_qos_t qos, + _z_bytes_t *attachment, z_reliability_t reliability); + +z_result_t _z_trigger_subscriptions_del(_z_session_t *zn, _z_keyexpr_t *keyexpr, const _z_timestamp_t *timestamp, + const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability); + +z_result_t _z_trigger_liveliness_subscriptions_declare(_z_session_t *zn, _z_keyexpr_t *keyexpr, + const _z_timestamp_t *timestamp); + +z_result_t _z_trigger_liveliness_subscriptions_undeclare(_z_session_t *zn, _z_keyexpr_t *keyexpr, + const _z_timestamp_t *timestamp); #if Z_FEATURE_SUBSCRIPTION == 1 @@ -53,12 +62,13 @@ void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_ void _z_subscription_cache_clear(_z_subscription_cache_t *cache); #endif -_z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id); -_z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_t *sub); -z_result_t _z_trigger_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, - _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, - const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability); -void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub); +_z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, _z_subscriber_kind_t kind, const _z_zint_t id); +_z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, _z_subscriber_kind_t kind, _z_subscription_t *sub); +z_result_t _z_trigger_subscriptions_impl(_z_session_t *zn, _z_subscriber_kind_t sub_kind, _z_keyexpr_t *keyexpr, + _z_bytes_t *payload, _z_encoding_t *encoding, const _z_zint_t sample_kind, + const _z_timestamp_t *timestamp, const _z_n_qos_t qos, _z_bytes_t *attachment, + z_reliability_t reliability); +void _z_unregister_subscription(_z_session_t *zn, _z_subscriber_kind_t kind, _z_subscription_rc_t *sub); void _z_flush_subscriptions(_z_session_t *zn); #endif diff --git a/src/api/api.c b/src/api/api.c index 37b2e0037..40f3e5ed3 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -829,10 +829,10 @@ z_result_t z_put(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr #if Z_FEATURE_LOCAL_SUBSCRIBER == 1 _z_timestamp_t local_timestamp = (opt.timestamp != NULL) ? *opt.timestamp : _z_timestamp_null(); _z_encoding_t local_encoding = (opt.encoding != NULL) ? &opt.encoding->_this._val : _z_encoding_null(); - _z_trigger_local_subscriptions( - _Z_RC_IN_VAL(zs), &keyexpr_aliased, &payload_bytes, &local_encoding, + _z_trigger_subscriptions_put( + _Z_RC_IN_VAL(zs), &keyexpr_aliased, &payload_bytes, &local_encoding, , &local_timestamp, _z_n_qos_make(opt.is_express, opt.congestion_control == Z_CONGESTION_CONTROL_BLOCK, opt.priority), - &local_timestamp, &attachment_bytes, reliability); + &attachment_bytes, reliability); #endif // Clean-up z_encoding_drop(opt.encoding); @@ -976,11 +976,13 @@ z_result_t z_publisher_put(const z_loaned_publisher_t *pub, z_moved_bytes_t *pay // Trigger local subscriptions #if Z_FEATURE_LOCAL_SUBSCRIBER == 1 _z_timestamp_t local_timestamp = (opt.timestamp != NULL) ? *opt.timestamp : _z_timestamp_null(); - _z_trigger_local_subscriptions( - session, &pub_keyexpr, &payload_bytes, &encoding, + _z_trigger_subscriptions_put( + session, &pub_keyexpr, &payload_bytes, &encoding, &local_timestamp, _z_n_qos_make(pub->_is_express, pub->_congestion_control == Z_CONGESTION_CONTROL_BLOCK, pub->_priority), - &local_timestamp, &attachment_bytes, reliability); + &attachment_bytes, reliability); #endif + } else { + ret = _Z_ERR_SESSION_CLOSED; } #if Z_FEATURE_PUBLISHER_SESSION_CHECK == 1 @@ -1408,7 +1410,7 @@ z_result_t z_undeclare_subscriber(z_moved_subscriber_t *sub) { const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *sub) { // Retrieve keyexpr from session uint32_t lookup = sub->_entity_id; - _z_subscription_rc_list_t *tail = _Z_RC_IN_VAL(&sub->_zn)->_local_subscriptions; + _z_subscription_rc_list_t *tail = _Z_RC_IN_VAL(&sub->_zn)->_subscriptions; while (tail != NULL) { _z_subscription_rc_t *head = _z_subscription_rc_list_head(tail); if (_Z_RC_IN_VAL(head)->_id == lookup) { diff --git a/src/api/liveliness.c b/src/api/liveliness.c new file mode 100644 index 000000000..a9403361f --- /dev/null +++ b/src/api/liveliness.c @@ -0,0 +1,144 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +#include "zenoh-pico/api/liveliness.h" + +#include "zenoh-pico/api/primitives.h" +#include "zenoh-pico/net/liveliness.h" +#include "zenoh-pico/net/primitives.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/keyexpr.h" +#include "zenoh-pico/utils/result.h" + +#if Z_FEATURE_LIVELINESS == 1 + +/**************** Liveliness Token ****************/ + +_Bool _z_liveliness_token_check(const _z_liveliness_token_t *token) { + _z_keyexpr_check(&token->_key); + return true; +} + +_z_liveliness_token_t _z_liveliness_token_null(void) { + _z_liveliness_token_t s = {0}; + s._key = _z_keyexpr_null(); + return s; +} + +void _z_liveliness_token_clear(_z_liveliness_token_t *token) { + _z_session_rc_t sess_rc = _z_session_weak_upgrade_if_open(&token->_zn); + if (!_Z_RC_IS_NULL(&sess_rc)) { + _z_undeclare_liveliness_token(token); + _z_session_rc_drop(&sess_rc); + } + _z_keyexpr_clear(&token->_key); +} + +_Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL(_z_liveliness_token_t, liveliness_token, _z_liveliness_token_check, + _z_liveliness_token_null, _z_liveliness_token_clear) + +z_result_t z_liveliness_token_options_t_default(z_liveliness_token_options_t *options) { + options->__dummy = 0; + return _Z_RES_OK; +} + +z_result_t z_liveliness_declare_token(const z_loaned_session_t *zs, z_owned_liveliness_token_t *token, + const z_loaned_keyexpr_t *keyexpr, const z_liveliness_token_options_t *options) { + (void)options; + + _z_keyexpr_t key = _z_update_keyexpr_to_declared(_Z_RC_IN_VAL(zs), *keyexpr); + + return _z_declare_liveliness_token(zs, &token->_val, &key); +} + +z_result_t z_liveliness_undeclare_token(z_moved_liveliness_token_t *token) { + return _z_undeclare_liveliness_token(&token->_this._val); +} + +/**************** Liveliness Subscriber ****************/ + +#if Z_FEATURE_SUBSCRIPTION == 1 +z_result_t z_liveliness_subscriber_options_default(z_liveliness_subscriber_options_t *options) { + options->history = false; + return _Z_RES_OK; +} + +z_result_t z_liveliness_declare_subscriber(const z_loaned_session_t *zs, z_owned_subscriber_t *sub, + const z_loaned_keyexpr_t *keyexpr, z_moved_closure_sample_t *callback, + z_liveliness_subscriber_options_t *options) { + void *ctx = callback->_this._val.context; + callback->_this._val.context = NULL; + + z_liveliness_subscriber_options_t opt; + if (options == NULL) { + z_liveliness_subscriber_options_default(&opt); + } else { + opt = *options; + } + + _z_keyexpr_t key = _z_update_keyexpr_to_declared(_Z_RC_IN_VAL(zs), *keyexpr); + + _z_subscriber_t int_sub = _z_declare_liveliness_subscriber(zs, &key, callback->_this._val.call, + callback->_this._val.drop, opt.history, ctx); + + z_internal_closure_sample_null(&callback->_this); + sub->_val = int_sub; + + if (!_z_subscriber_check(&sub->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + + if (opt.history) { + z_result_t ret = _z_liveliness_subscription_trigger_history(_Z_RC_IN_VAL(zs), keyexpr); + if (ret != _Z_RES_OK) { + return ret; + } + } + + return _Z_RES_OK; +} +#endif // Z_FEATURE_SUBSCRIPTION == 1 + +/**************** Liveliness Query ****************/ + +#if Z_FEATURE_QUERY == 1 +z_result_t z_liveliness_get_options_default(z_liveliness_get_options_t *options) { + options->timeout_ms = Z_GET_TIMEOUT_DEFAULT; + return _Z_RES_OK; +} + +z_result_t z_liveliness_get(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, + z_moved_closure_reply_t *callback, z_liveliness_get_options_t *options) { + z_result_t ret = _Z_RES_OK; + + void *ctx = callback->_this._val.context; + callback->_this._val.context = NULL; + + z_liveliness_get_options_t opt; + if (options == NULL) { + z_liveliness_get_options_default(&opt); + } else { + opt = *options; + } + + ret = _z_liveliness_query(_Z_RC_IN_VAL(zs), keyexpr, callback->_this._val.call, callback->_this._val.drop, ctx, + opt.timeout_ms); + + z_internal_closure_reply_null( + &callback->_this); // call and drop passed to _z_liveliness_query, so we nullify the closure here + return ret; +} +#endif // Z_FEATURE_QUERY == 1 + +#endif // Z_FEATURE_LIVELINESS == 1 diff --git a/src/collections/fifo_mt.c b/src/collections/fifo_mt.c index e8d735f94..91c918673 100644 --- a/src/collections/fifo_mt.c +++ b/src/collections/fifo_mt.c @@ -17,6 +17,7 @@ #include "zenoh-pico/protocol/codec/core.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/result.h" /*-------- Fifo Buffer Multithreaded --------*/ z_result_t _z_fifo_mt_init(_z_fifo_mt_t *fifo, size_t capacity) { diff --git a/src/collections/intmap.c b/src/collections/intmap.c index 004e61bdd..0d7eac9ad 100644 --- a/src/collections/intmap.c +++ b/src/collections/intmap.c @@ -68,6 +68,9 @@ z_result_t _z_int_void_map_copy(_z_int_void_map_t *dst, const _z_int_void_map_t _z_int_void_map_t _z_int_void_map_clone(const _z_int_void_map_t *src, z_element_clone_f f_c, z_element_free_f f_f) { _z_int_void_map_t dst = {._capacity = src->_capacity, ._vals = NULL}; + if (src->_vals == NULL) { + return dst; + } // Lazily allocate and initialize to NULL all the pointers size_t len = dst._capacity * sizeof(_z_list_t *); dst._vals = (_z_list_t **)z_malloc(len); @@ -144,6 +147,41 @@ void *_z_int_void_map_get(const _z_int_void_map_t *map, size_t k) { return ret; } +_z_int_void_map_iterator_t _z_int_void_map_iterator_make(const _z_int_void_map_t *map) { + _z_int_void_map_iterator_t iter = {0}; + + iter._map = map; + + return iter; +} + +bool _z_int_void_map_iterator_next(_z_int_void_map_iterator_t *iter) { + if (iter->_map->_vals == NULL) { + return false; + } + + while (iter->_idx < iter->_map->_capacity) { + if (iter->_list_ptr == NULL) { + iter->_list_ptr = iter->_map->_vals[iter->_idx]; + } else { + iter->_list_ptr = _z_list_tail(iter->_list_ptr); + } + if (iter->_list_ptr == NULL) { + iter->_idx++; + continue; + } + + iter->_entry = iter->_list_ptr->_val; + + return true; + } + return false; +} + +size_t _z_int_void_map_iterator_key(const _z_int_void_map_iterator_t *iter) { return iter->_entry->_key; } + +void *_z_int_void_map_iterator_value(const _z_int_void_map_iterator_t *iter) { return iter->_entry->_val; } + void _z_int_void_map_clear(_z_int_void_map_t *map, z_element_free_f f_f) { if (map->_vals != NULL) { for (size_t idx = 0; idx < map->_capacity; idx++) { diff --git a/src/net/liveliness.c b/src/net/liveliness.c new file mode 100644 index 000000000..b428a234a --- /dev/null +++ b/src/net/liveliness.c @@ -0,0 +1,174 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, + +#include "zenoh-pico/api/liveliness.h" + +#include "zenoh-pico/net/primitives.h" +#include "zenoh-pico/protocol/definitions/interest.h" +#include "zenoh-pico/protocol/definitions/network.h" +#include "zenoh-pico/protocol/keyexpr.h" +#include "zenoh-pico/session/resource.h" +#include "zenoh-pico/session/session.h" +#include "zenoh-pico/session/subscription.h" +#include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/tx.h" +#include "zenoh-pico/utils/result.h" + +#if Z_FEATURE_LIVELINESS == 1 + +/**************** Liveliness Token ****************/ + +z_result_t _z_declare_liveliness_token(const _z_session_rc_t *zn, _z_liveliness_token_t *ret_token, + _z_keyexpr_t *keyexpr) { + z_result_t ret; + + uint32_t id = _z_get_entity_id(_Z_RC_IN_VAL(zn)); + + _z_declaration_t declaration = _z_make_decl_token(keyexpr, id); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, false, 0); + ret = _z_send_n_msg(_Z_RC_IN_VAL(zn), &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK); + _z_n_msg_clear(&n_msg); + + _z_liveliness_register_token(_Z_RC_IN_VAL(zn), id, keyexpr); + + ret_token->_id = id; + _z_keyexpr_move(&ret_token->_key, keyexpr); + ret_token->_zn = _z_session_rc_clone_as_weak(zn); + return ret; +} + +z_result_t _z_undeclare_liveliness_token(_z_liveliness_token_t *token) { + if (token == NULL || _Z_RC_IS_NULL(&token->_zn)) { + return _Z_ERR_ENTITY_UNKNOWN; + } + + z_result_t ret; + + _z_liveliness_unregister_token(_Z_RC_IN_VAL(&token->_zn), token->_id); + + _z_declaration_t declaration = _z_make_undecl_token(token->_id, &token->_key); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, false, 0); + ret = _z_send_n_msg(_Z_RC_IN_VAL(&token->_zn), &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK); + _z_n_msg_clear(&n_msg); + + return ret; +} + +/**************** Liveliness Subscriber ****************/ + +#if Z_FEATURE_SUBSCRIPTION == 1 +_z_subscriber_t _z_declare_liveliness_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t *keyexpr, + _z_closure_sample_callback_t callback, _z_drop_handler_t dropper, + bool history, void *arg) { + _z_subscription_t s; + s._id = _z_get_entity_id(_Z_RC_IN_VAL(zn)); + s._key_id = keyexpr->_id; + s._key = _z_get_expanded_key_from_key(_Z_RC_IN_VAL(zn), keyexpr); + s._callback = callback; + s._dropper = dropper; + s._arg = arg; + + _z_subscriber_t ret = _z_subscriber_null(); + // Register subscription, stored at session-level, do not drop it by the end of this function. + _z_subscription_rc_t *sp_s = + _z_register_subscription(_Z_RC_IN_VAL(zn), _Z_SUBSCRIBER_KIND_LIVELINESS_SUBSCRIBER, &s); + if (sp_s == NULL) { + _z_subscriber_clear(&ret); + return ret; + } + // Build the declare message to send on the wire + uint8_t mode = history ? (_Z_INTEREST_FLAG_CURRENT | _Z_INTEREST_FLAG_FUTURE) : _Z_INTEREST_FLAG_FUTURE; + _z_interest_t interest = _z_make_interest( + keyexpr, s._id, _Z_INTEREST_FLAG_KEYEXPRS | _Z_INTEREST_FLAG_TOKENS | _Z_INTEREST_FLAG_RESTRICTED | mode); + + _z_network_message_t n_msg = _z_n_msg_make_interest(interest); + if (_z_send_n_msg(_Z_RC_IN_VAL(zn), &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _z_unregister_subscription(_Z_RC_IN_VAL(zn), _Z_SUBSCRIBER_KIND_LIVELINESS_SUBSCRIBER, sp_s); + _z_subscriber_clear(&ret); + return ret; + } + _z_n_msg_clear(&n_msg); + + ret._entity_id = s._id; + ret._zn = _z_session_rc_clone_as_weak(zn); + return ret; +} + +z_result_t _z_undeclare_liveliness_subscriber(_z_subscriber_t *sub) { + if (sub == NULL || _Z_RC_IS_NULL(&sub->_zn)) { + return _Z_ERR_ENTITY_UNKNOWN; + } + + _z_subscription_rc_t *s = + _z_get_subscription_by_id(_Z_RC_IN_VAL(&sub->_zn), _Z_SUBSCRIBER_KIND_LIVELINESS_SUBSCRIBER, sub->_entity_id); + if (s == NULL) { + return _Z_ERR_ENTITY_UNKNOWN; + } + + _z_interest_t interest = _z_make_interest_final(s->_val->_id); + _z_network_message_t n_msg = _z_n_msg_make_interest(interest); + if (_z_send_n_msg(_Z_RC_IN_VAL(&sub->_zn), &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != + _Z_RES_OK) { + return _Z_ERR_TRANSPORT_TX_FAILED; + } + _z_n_msg_clear(&n_msg); + + _z_undeclare_resource(_Z_RC_IN_VAL(&sub->_zn), _Z_RC_IN_VAL(s)->_key_id); + _z_unregister_subscription(_Z_RC_IN_VAL(&sub->_zn), _Z_SUBSCRIBER_KIND_LIVELINESS_SUBSCRIBER, s); + return _Z_RES_OK; +} +#endif // Z_FEATURE_SUBSCRIPTION == 1 + +/**************** Liveliness Query ****************/ + +#if Z_FEATURE_QUERY == 1 +z_result_t _z_liveliness_query(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_closure_reply_callback_t callback, + _z_drop_handler_t dropper, void *arg, uint64_t timeout_ms) { + z_result_t ret = _Z_RES_OK; + + // Create the pending liveliness query object + _z_liveliness_pending_query_t *pq = + (_z_liveliness_pending_query_t *)z_malloc(sizeof(_z_liveliness_pending_query_t)); + if (pq != NULL) { + uint32_t id = _z_liveliness_get_query_id(zn); + pq->_key = _z_get_expanded_key_from_key(zn, keyexpr); + pq->_callback = callback; + pq->_dropper = dropper; + pq->_arg = arg; + + ret = _z_liveliness_register_pending_query(zn, id, pq); + if (ret == _Z_RES_OK) { + _ZP_UNUSED(timeout_ms); // Current interest in pico don't support timeout + _z_keyexpr_t key = _z_keyexpr_alias(*keyexpr); + _z_interest_t interest = _z_make_interest(&key, id, + _Z_INTEREST_FLAG_KEYEXPRS | _Z_INTEREST_FLAG_TOKENS | + _Z_INTEREST_FLAG_RESTRICTED | _Z_INTEREST_FLAG_CURRENT); + + _z_network_message_t n_msg = _z_n_msg_make_interest(interest); + if (_z_send_n_msg(zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _z_liveliness_unregister_pending_query(zn, id); + ret = _Z_ERR_TRANSPORT_TX_FAILED; + } + + _z_n_msg_clear(&n_msg); + + } else { + _z_liveliness_pending_query_clear(pq); + } + } + + return ret; +} +#endif // Z_FEATURE_QUERY == 1 + +#endif // Z_FEATURE_LIVELINESS == 1 diff --git a/src/net/primitives.c b/src/net/primitives.c index baf24fa50..d1909188f 100644 --- a/src/net/primitives.c +++ b/src/net/primitives.c @@ -21,16 +21,17 @@ #include "zenoh-pico/collections/slice.h" #include "zenoh-pico/config.h" #include "zenoh-pico/net/filtering.h" -#include "zenoh-pico/net/logger.h" -#include "zenoh-pico/net/sample.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/declarations.h" +#include "zenoh-pico/protocol/definitions/interest.h" #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/keyexpr.h" #include "zenoh-pico/session/interest.h" +#include "zenoh-pico/session/liveliness.h" #include "zenoh-pico/session/query.h" #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/resource.h" +#include "zenoh-pico/session/session.h" #include "zenoh-pico/session/subscription.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/common/tx.h" @@ -101,6 +102,27 @@ z_result_t _z_undeclare_resource(_z_session_t *zn, uint16_t rid) { return ret; } +// TODO(sashacmc): currently used only for liveliness, because it have little bit different behavior from others +// It seems also correct for z_declare_queryable and z_declare_publisher, but it need to be verified +_z_keyexpr_t _z_update_keyexpr_to_declared(_z_session_t *zs, _z_keyexpr_t keyexpr) { + _z_keyexpr_t keyexpr_aliased = _z_keyexpr_alias_from_user_defined(keyexpr, true); + _z_keyexpr_t key = keyexpr_aliased; + + // TODO: Currently, if resource declarations are done over multicast transports, the current protocol definition + // lacks a way to convey them to later-joining nodes. Thus, in the current version automatic + // resource declarations are only performed on unicast transports. + if (zs->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { + _z_resource_t *r = _z_get_resource_by_key(zs, &keyexpr_aliased); + if (r != NULL) { + key = _z_rid_with_suffix(r->_id, NULL); + } else { + uint16_t id = _z_declare_resource(zs, keyexpr_aliased); + key = _z_rid_with_suffix(id, NULL); + } + } + return key; +} + #if Z_FEATURE_PUBLICATION == 1 /*------------------ Publisher Declaration ------------------*/ _z_publisher_t _z_declare_publisher(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, _z_encoding_t *encoding, @@ -205,7 +227,7 @@ _z_subscriber_t _z_declare_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t ke _z_subscriber_t ret = _z_subscriber_null(); // Register subscription, stored at session-level, do not drop it by the end of this function. - _z_subscription_rc_t *sp_s = _z_register_subscription(_Z_RC_IN_VAL(zn), _Z_RESOURCE_IS_LOCAL, &s); + _z_subscription_rc_t *sp_s = _z_register_subscription(_Z_RC_IN_VAL(zn), _Z_SUBSCRIBER_KIND_SUBSCRIBER, &s); if (sp_s == NULL) { _z_subscriber_clear(&ret); return ret; @@ -214,7 +236,7 @@ _z_subscriber_t _z_declare_subscriber(const _z_session_rc_t *zn, _z_keyexpr_t ke _z_declaration_t declaration = _z_make_decl_subscriber(&keyexpr, s._id); _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, false, 0); if (_z_send_n_msg(_Z_RC_IN_VAL(zn), &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { - _z_unregister_subscription(_Z_RC_IN_VAL(zn), _Z_RESOURCE_IS_LOCAL, sp_s); + _z_unregister_subscription(_Z_RC_IN_VAL(zn), _Z_SUBSCRIBER_KIND_SUBSCRIBER, sp_s); _z_subscriber_clear(&ret); return ret; } @@ -230,7 +252,8 @@ z_result_t _z_undeclare_subscriber(_z_subscriber_t *sub) { return _Z_ERR_ENTITY_UNKNOWN; } // Find subscription entry - _z_subscription_rc_t *s = _z_get_subscription_by_id(_Z_RC_IN_VAL(&sub->_zn), _Z_RESOURCE_IS_LOCAL, sub->_entity_id); + _z_subscription_rc_t *s = + _z_get_subscription_by_id(_Z_RC_IN_VAL(&sub->_zn), _Z_SUBSCRIBER_KIND_SUBSCRIBER, sub->_entity_id); if (s == NULL) { return _Z_ERR_ENTITY_UNKNOWN; } @@ -249,7 +272,7 @@ z_result_t _z_undeclare_subscriber(_z_subscriber_t *sub) { _z_n_msg_clear(&n_msg); // Only if message is successfully send, local subscription state can be removed _z_undeclare_resource(_Z_RC_IN_VAL(&sub->_zn), _Z_RC_IN_VAL(s)->_key_id); - _z_unregister_subscription(_Z_RC_IN_VAL(&sub->_zn), _Z_RESOURCE_IS_LOCAL, s); + _z_unregister_subscription(_Z_RC_IN_VAL(&sub->_zn), _Z_SUBSCRIBER_KIND_SUBSCRIBER, s); return _Z_RES_OK; } #endif diff --git a/src/net/query.c b/src/net/query.c index dcf5b647a..e1748e8c8 100644 --- a/src/net/query.c +++ b/src/net/query.c @@ -17,7 +17,7 @@ #include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/utils/logging.h" -void _z_query_clear_inner(_z_query_t *q) { +static void _z_query_clear_inner(_z_query_t *q) { _z_keyexpr_clear(&q->_key); _z_value_clear(&q->_value); _z_bytes_drop(&q->_attachment); @@ -25,15 +25,20 @@ void _z_query_clear_inner(_z_query_t *q) { _z_session_rc_drop(&q->_zn); } +z_result_t _z_query_send_reply_final(_z_query_t *q) { + if (_Z_RC_IS_NULL(&q->_zn)) { + return _Z_ERR_TRANSPORT_TX_FAILED; + } + _z_zenoh_message_t z_msg = _z_n_msg_make_response_final(q->_request_id); + z_result_t ret = _z_send_n_msg(_Z_RC_IN_VAL(&q->_zn), &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK); + _z_msg_clear(&z_msg); + return ret; +} + void _z_query_clear(_z_query_t *q) { - if (!_Z_RC_IS_NULL(&q->_zn)) { - // Send REPLY_FINAL message - _z_zenoh_message_t z_msg = _z_n_msg_make_response_final(q->_request_id); - if (_z_send_n_msg(_Z_RC_IN_VAL(&q->_zn), &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != - _Z_RES_OK) { - _Z_ERROR("Query send REPLY_FINAL transport failure !"); - } - _z_msg_clear(&z_msg); + // Send REPLY_FINAL message + if (_z_query_send_reply_final(q) != _Z_RES_OK) { + _Z_ERROR("Query send REPLY_FINAL transport failure !"); } // Clean up memory _z_query_clear_inner(q); diff --git a/src/protocol/iobuf.c b/src/protocol/iobuf.c index 8c6f6d39d..fc025c70a 100644 --- a/src/protocol/iobuf.c +++ b/src/protocol/iobuf.c @@ -84,7 +84,7 @@ void _z_iosli_read_bytes(_z_iosli_t *ios, uint8_t *dst, size_t offset, size_t le void _z_iosli_copy_bytes(_z_iosli_t *dst, const _z_iosli_t *src) { size_t length = _z_iosli_readable(src); - assert(_z_iosli_readable(dst) >= length); + assert(dst->_capacity >= length); (void)memcpy(dst->_buf + dst->_w_pos, src->_buf + src->_r_pos, length); dst->_w_pos += length; } diff --git a/src/protocol/keyexpr.c b/src/protocol/keyexpr.c index 15e1beee0..4ce2ab919 100644 --- a/src/protocol/keyexpr.c +++ b/src/protocol/keyexpr.c @@ -48,6 +48,11 @@ _z_keyexpr_t _z_keyexpr_from_substr(uint16_t rid, const char *str, size_t len) { }; } +size_t _z_keyexpr_size(_z_keyexpr_t *p) { + _ZP_UNUSED(p); + return sizeof(_z_keyexpr_t); +} + z_result_t _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src) { *dst = _z_keyexpr_null(); dst->_id = src->_id; @@ -65,17 +70,21 @@ _z_keyexpr_t _z_keyexpr_duplicate(const _z_keyexpr_t *src) { return dst; } +_z_keyexpr_t *_z_keyexpr_clone(const _z_keyexpr_t *src) { + _z_keyexpr_t *dst = z_malloc(sizeof(_z_keyexpr_t)); + if (dst != NULL) { + _z_keyexpr_copy(dst, src); + } + return dst; +} + _z_keyexpr_t _z_keyexpr_steal(_Z_MOVE(_z_keyexpr_t) src) { _z_keyexpr_t stolen = *src; *src = _z_keyexpr_null(); return stolen; } -void _z_keyexpr_move(_z_keyexpr_t *dst, _z_keyexpr_t *src) { - dst->_id = src->_id; - dst->_mapping = src->_mapping; - _z_string_move(&dst->_suffix, &src->_suffix); -} +void _z_keyexpr_move(_z_keyexpr_t *dst, _z_keyexpr_t *src) { *dst = _z_keyexpr_steal(src); } void _z_keyexpr_clear(_z_keyexpr_t *rk) { rk->_id = 0; diff --git a/src/session/interest.c b/src/session/interest.c index 8faa6cc2f..88a0626bd 100644 --- a/src/session/interest.c +++ b/src/session/interest.c @@ -21,10 +21,12 @@ #include "zenoh-pico/net/query.h" #include "zenoh-pico/protocol/codec/core.h" #include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/definitions/declarations.h" #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/keyexpr.h" #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/resource.h" +#include "zenoh-pico/session/session.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/common/tx.h" #include "zenoh-pico/utils/logging.h" @@ -118,7 +120,7 @@ static z_result_t _z_interest_send_decl_resource(_z_session_t *zn, uint32_t inte #if Z_FEATURE_SUBSCRIPTION == 1 static z_result_t _z_interest_send_decl_subscriber(_z_session_t *zn, uint32_t interest_id) { _z_session_mutex_lock(zn); - _z_subscription_rc_list_t *sub_list = _z_subscription_rc_list_clone(zn->_local_subscriptions); + _z_subscription_rc_list_t *sub_list = _z_subscription_rc_list_clone(zn->_subscriptions); _z_session_mutex_unlock(zn); _z_subscription_rc_list_t *xs = sub_list; while (xs != NULL) { @@ -174,6 +176,35 @@ static z_result_t _z_interest_send_decl_queryable(_z_session_t *zn, uint32_t int } #endif +#if Z_FEATURE_LIVELINESS == 1 +static z_result_t _z_interest_send_decl_token(_z_session_t *zn, uint32_t interest_id) { + _z_session_mutex_lock(zn); + _z_keyexpr_intmap_t token_list = _z_keyexpr_intmap_clone(&zn->_local_tokens); + _z_session_mutex_unlock(zn); + _z_keyexpr_intmap_iterator_t iter = _z_keyexpr_intmap_iterator_make(&token_list); + while (_z_keyexpr_intmap_iterator_next(&iter)) { + // Build the declare message to send on the wire + uint32_t id = (uint32_t)_z_keyexpr_intmap_iterator_key(&iter); + _z_keyexpr_t key = *_z_keyexpr_intmap_iterator_value(&iter); + _z_declaration_t declaration = _z_make_decl_token(&key, id); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, true, interest_id); + if (_z_send_n_msg(zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + return _Z_ERR_TRANSPORT_TX_FAILED; + } + _z_n_msg_clear(&n_msg); + } + _z_keyexpr_intmap_clear(&token_list); + + return _Z_RES_OK; +} +#else +static z_result_t _z_interest_send_decl_token(_z_session_t *zn, uint32_t interest_id) { + _ZP_UNUSED(zn); + _ZP_UNUSED(interest_id); + return _Z_RES_OK; +} +#endif + static z_result_t _z_interest_send_declare_final(_z_session_t *zn, uint32_t interest_id) { _z_declaration_t decl = _z_make_decl_final(); _z_network_message_t n_msg = _z_n_msg_make_declare(decl, true, interest_id); @@ -266,6 +297,13 @@ z_result_t _z_interest_process_declares(_z_session_t *zn, const _z_declaration_t decl_type = _Z_DECLARE_TYPE_QUERYABLE; flags = _Z_INTEREST_FLAG_QUERYABLES; break; + case _Z_DECL_TOKEN: + msg.type = _Z_INTEREST_MSG_TYPE_DECL_TOKEN; + msg.id = decl->_body._decl_token._id; + decl_key = &decl->_body._decl_token._keyexpr; + decl_type = _Z_DECLARE_TYPE_TOKEN; + flags = _Z_INTEREST_FLAG_TOKENS; + break; default: return _Z_ERR_MESSAGE_ZENOH_DECLARATION_UNKNOWN; } @@ -313,6 +351,12 @@ z_result_t _z_interest_process_undeclares(_z_session_t *zn, const _z_declaration decl_type = _Z_DECLARE_TYPE_QUERYABLE; flags = _Z_INTEREST_FLAG_QUERYABLES; break; + case _Z_UNDECL_TOKEN: + msg.type = _Z_INTEREST_MSG_TYPE_UNDECL_TOKEN; + msg.id = decl->_body._undecl_token._id; + decl_type = _Z_DECLARE_TYPE_TOKEN; + flags = _Z_INTEREST_FLAG_TOKENS; + break; default: return _Z_ERR_MESSAGE_ZENOH_DECLARATION_UNKNOWN; } @@ -403,7 +447,8 @@ z_result_t _z_interest_process_interest(_z_session_t *zn, _z_keyexpr_t key, uint _Z_RETURN_IF_ERR(_z_interest_send_decl_queryable(zn, id)); } if (_Z_HAS_FLAG(flags, _Z_INTEREST_FLAG_TOKENS)) { - // Zenoh pico doesn't support liveliness token for now + _Z_DEBUG("Sending declare tokens"); + _Z_RETURN_IF_ERR(_z_interest_send_decl_token(zn, id)); } // Send final declare _Z_RETURN_IF_ERR(_z_interest_send_declare_final(zn, id)); diff --git a/src/session/liveliness.c b/src/session/liveliness.c new file mode 100644 index 000000000..cdbbcf766 --- /dev/null +++ b/src/session/liveliness.c @@ -0,0 +1,339 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +#include "zenoh-pico/api/liveliness.h" + +#include +#include + +#include "zenoh-pico/api/primitives.h" +#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/config.h" +#include "zenoh-pico/net/reply.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/keyexpr.h" +#include "zenoh-pico/session/resource.h" +#include "zenoh-pico/session/session.h" +#include "zenoh-pico/session/subscription.h" +#include "zenoh-pico/session/utils.h" +#include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/result.h" + +#if Z_FEATURE_LIVELINESS == 1 + +/**************** Liveliness Token ****************/ + +z_result_t _z_liveliness_register_token(_z_session_t *zn, uint32_t id, const _z_keyexpr_t *keyexpr) { + z_result_t ret = _Z_RES_OK; + + _Z_DEBUG("Register liveliness token (%i:%.*s)", (int)id, (int)_z_string_len(&keyexpr->_suffix), + _z_string_data(&keyexpr->_suffix)); + + _z_session_mutex_lock(zn); + + const _z_keyexpr_t *pkeyexpr = _z_keyexpr_intmap_get(&zn->_local_tokens, id); + if (pkeyexpr != NULL) { + _Z_ERROR("Duplicate token id %i", (int)id); + ret = _Z_ERR_ENTITY_DECLARATION_FAILED; + } else { + _z_keyexpr_intmap_insert(&zn->_local_tokens, id, _z_keyexpr_clone(keyexpr)); + } + + _z_session_mutex_unlock(zn); + + return ret; +} + +void _z_liveliness_unregister_token(_z_session_t *zn, uint32_t id) { + _z_session_mutex_lock(zn); + + _Z_DEBUG("Unregister liveliness token (%i)", (int)id); + + _z_keyexpr_intmap_remove(&zn->_local_tokens, id); + + _z_session_mutex_unlock(zn); +} + +/**************** Liveliness Subscriber ****************/ + +#if Z_FEATURE_SUBSCRIPTION == 1 +z_result_t _z_liveliness_subscription_declare(_z_session_t *zn, uint32_t id, const _z_keyexpr_t *keyexpr, + const _z_timestamp_t *timestamp) { + z_result_t ret = _Z_RES_OK; + + _z_session_mutex_lock(zn); + + const _z_keyexpr_t *pkeyexpr = _z_keyexpr_intmap_get(&zn->_remote_tokens, id); + if (pkeyexpr != NULL) { + _Z_ERROR("Duplicate token id %i", (int)id); + ret = _Z_ERR_ENTITY_DECLARATION_FAILED; + } else { + _z_keyexpr_intmap_insert(&zn->_remote_tokens, id, _z_keyexpr_clone(keyexpr)); + } + + _z_session_mutex_unlock(zn); + + if (ret == _Z_RES_OK) { + _z_keyexpr_t key = _z_keyexpr_alias(*keyexpr); + ret = _z_trigger_liveliness_subscriptions_declare(zn, &key, timestamp); + } + + return ret; +} + +z_result_t _z_liveliness_subscription_undeclare(_z_session_t *zn, uint32_t id, const _z_timestamp_t *timestamp) { + z_result_t ret = _Z_RES_OK; + + _z_keyexpr_t *key = NULL; + _z_session_mutex_lock(zn); + const _z_keyexpr_t *keyexpr = _z_keyexpr_intmap_get(&zn->_remote_tokens, id); + if (keyexpr != NULL) { + key = _z_keyexpr_clone(keyexpr); + _z_keyexpr_intmap_remove(&zn->_remote_tokens, id); + } else { + ret = _Z_ERR_ENTITY_UNKNOWN; + } + _z_session_mutex_unlock(zn); + + if (key != NULL) { + ret = _z_trigger_liveliness_subscriptions_undeclare(zn, key, timestamp); + _z_keyexpr_clear(key); + } + + return ret; +} + +z_result_t _z_liveliness_subscription_trigger_history(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { + z_result_t ret = _Z_RES_OK; + + _Z_DEBUG("Retrieve liveliness history for %.*s", (int)_z_string_len(&keyexpr->_suffix), + _z_string_data(&keyexpr->_suffix)); + + _z_session_mutex_lock(zn); + _z_keyexpr_intmap_t token_list = _z_keyexpr_intmap_clone(&zn->_remote_tokens); + _z_session_mutex_unlock(zn); + + _z_keyexpr_intmap_iterator_t iter = _z_keyexpr_intmap_iterator_make(&token_list); + _z_timestamp_t tm = _z_timestamp_null(); + while (_z_keyexpr_intmap_iterator_next(&iter)) { + _z_keyexpr_t key = *_z_keyexpr_intmap_iterator_value(&iter); + if (_z_keyexpr_suffix_intersects(&key, keyexpr)) { + ret = _z_trigger_liveliness_subscriptions_declare(zn, &key, &tm); + if (ret != _Z_RES_OK) { + break; + } + } + } + _z_keyexpr_intmap_clear(&token_list); + + return ret; +} +#endif // Z_FEATURE_SUBSCRIPTION == 1 + +/**************** Liveliness Query ****************/ + +#if Z_FEATURE_QUERY == 1 + +void _z_liveliness_pending_query_clear(_z_liveliness_pending_query_t *pen_qry) { + if (pen_qry->_dropper != NULL) { + pen_qry->_dropper(pen_qry->_arg); + } + _z_keyexpr_clear(&pen_qry->_key); +} + +void _z_liveliness_pending_query_copy(_z_liveliness_pending_query_t *dst, const _z_liveliness_pending_query_t *src) { + dst->_arg = src->_arg; + dst->_callback = src->_callback; + dst->_dropper = src->_dropper; + _z_keyexpr_copy(&dst->_key, &src->_key); +} + +_z_liveliness_pending_query_t *_z_liveliness_pending_query_clone(const _z_liveliness_pending_query_t *src) { + _z_liveliness_pending_query_t *dst = z_malloc(sizeof(_z_liveliness_pending_query_t)); + if (dst != NULL) { + _z_liveliness_pending_query_copy(dst, src); + } + return dst; +} + +uint32_t _z_liveliness_get_query_id(_z_session_t *zn) { return zn->_liveliness_query_id++; } + +z_result_t _z_liveliness_register_pending_query(_z_session_t *zn, uint32_t id, _z_liveliness_pending_query_t *pen_qry) { + z_result_t ret = _Z_RES_OK; + + _Z_DEBUG("Register liveliness query for (%ju:%.*s)", (uintmax_t)pen_qry->_key._id, + (int)_z_string_len(&pen_qry->_key._suffix), _z_string_data(&pen_qry->_key._suffix)); + + _z_session_mutex_lock(zn); + + const _z_liveliness_pending_query_t *pq = + _z_liveliness_pending_query_intmap_get(&zn->_liveliness_pending_queries, id); + if (pq != NULL) { + _Z_ERROR("Duplicate liveliness query id %i", (int)id); + ret = _Z_ERR_ENTITY_DECLARATION_FAILED; + } else { + _z_liveliness_pending_query_intmap_insert(&zn->_liveliness_pending_queries, id, + _z_liveliness_pending_query_clone(pen_qry)); + } + + _z_session_mutex_unlock(zn); + + return ret; +} + +z_result_t _z_liveliness_pending_query_reply(_z_session_t *zn, uint32_t interest_id, const _z_keyexpr_t *keyexpr, + const _z_timestamp_t *timestamp) { + z_result_t ret = _Z_RES_OK; + + _z_session_mutex_lock(zn); + + const _z_liveliness_pending_query_t *pq = + _z_liveliness_pending_query_intmap_get(&zn->_liveliness_pending_queries, interest_id); + if (pq == NULL) { + ret = _Z_ERR_ENTITY_UNKNOWN; + } + + _Z_DEBUG("Liveliness pending query reply %i resolve result %i", (int)interest_id, ret); + + if (ret == _Z_RES_OK) { + _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr->_id, (int)_z_string_len(&keyexpr->_suffix), + _z_string_data(&keyexpr->_suffix), _z_keyexpr_mapping_id(keyexpr)); + _z_keyexpr_t expanded_ke = __unsafe_z_get_expanded_key_from_key(zn, keyexpr, true); + _Z_DEBUG("Reply liveliness query for %d - %.*s", expanded_ke._id, (int)_z_string_len(&expanded_ke._suffix), + _z_string_data(&expanded_ke._suffix)); + + if (!_z_keyexpr_suffix_intersects(&pq->_key, &expanded_ke)) { + ret = _Z_ERR_QUERY_NOT_MATCH; + } + + if (ret == _Z_RES_OK) { + _z_encoding_t encoding = _z_encoding_null(); + _z_bytes_t payload = _z_bytes_null(); + _z_bytes_t attachment = _z_bytes_null(); + _z_reply_t reply = _z_reply_alias(&expanded_ke, zn->_local_zid, &payload, timestamp, &encoding, + Z_SAMPLE_KIND_PUT, &attachment); + + pq->_callback(&reply, pq->_arg); + _z_reply_clear(&reply); + } + } + + _z_session_mutex_unlock(zn); + + return ret; +} + +z_result_t _z_liveliness_pending_query_drop(_z_session_t *zn, uint32_t interest_id) { + z_result_t ret = _Z_RES_OK; + + _z_session_mutex_lock(zn); + + const _z_liveliness_pending_query_t *pq = + _z_liveliness_pending_query_intmap_get(&zn->_liveliness_pending_queries, interest_id); + if (pq == NULL) { + ret = _Z_ERR_ENTITY_UNKNOWN; + } + + _Z_DEBUG("Liveliness pending query drop %i resolve result %i", (int)interest_id, ret); + + if (ret == _Z_RES_OK) { + _z_liveliness_pending_query_intmap_remove(&zn->_liveliness_pending_queries, interest_id); + } + + _z_session_mutex_unlock(zn); + + return ret; +} + +void _z_liveliness_unregister_pending_query(_z_session_t *zn, uint32_t id) { + _z_session_mutex_lock(zn); + + _z_liveliness_pending_query_intmap_remove(&zn->_liveliness_pending_queries, id); + + _z_session_mutex_unlock(zn); +} + +#endif // Z_FEATURE_QUERY == 1 + +/**************** Interest processing ****************/ + +z_result_t _z_liveliness_process_token_declare(_z_session_t *zn, const _z_n_msg_declare_t *decl) { +#if Z_FEATURE_QUERY == 1 + if (decl->has_interest_id) { + _z_liveliness_pending_query_reply(zn, decl->_interest_id, &decl->_decl._body._decl_token._keyexpr, + &decl->_ext_timestamp); + } +#endif + +#if Z_FEATURE_SUBSCRIPTION == 1 + return _z_liveliness_subscription_declare(zn, decl->_decl._body._decl_token._id, + &decl->_decl._body._decl_token._keyexpr, &decl->_ext_timestamp); +#else + _ZP_UNUSED(zn); + _ZP_UNUSED(decl); + return _Z_RES_OK; +#endif +} + +z_result_t _z_liveliness_process_token_undeclare(_z_session_t *zn, const _z_n_msg_declare_t *decl) { +#if Z_FEATURE_SUBSCRIPTION == 1 + return _z_liveliness_subscription_undeclare(zn, decl->_decl._body._undecl_token._id, &decl->_ext_timestamp); +#else + _ZP_UNUSED(zn); + _ZP_UNUSED(decl); + return _Z_RES_OK; +#endif +} + +z_result_t _z_liveliness_process_declare_final(_z_session_t *zn, const _z_n_msg_declare_t *decl) { +#if Z_FEATURE_QUERY == 1 + if (decl->has_interest_id) { + _z_liveliness_pending_query_drop(zn, decl->_interest_id); + } + return _Z_RES_OK; +#else + _ZP_UNUSED(zn); + _ZP_UNUSED(decl); + return _Z_RES_OK; +#endif +} + +/**************** Init/Clear ****************/ + +void _z_liveliness_init(_z_session_t *zn) { + _z_session_mutex_lock(zn); + + zn->_remote_tokens = _z_keyexpr_intmap_make(); + zn->_local_tokens = _z_keyexpr_intmap_make(); +#if Z_FEATURE_QUERY == 1 + zn->_liveliness_query_id = 1; + zn->_liveliness_pending_queries = _z_liveliness_pending_query_intmap_make(); +#endif + + _z_session_mutex_unlock(zn); +} + +void _z_liveliness_clear(_z_session_t *zn) { + _z_session_mutex_lock(zn); + +#if Z_FEATURE_QUERY == 1 + _z_liveliness_pending_query_intmap_clear(&zn->_liveliness_pending_queries); +#endif + _z_keyexpr_intmap_clear(&zn->_local_tokens); + _z_keyexpr_intmap_clear(&zn->_remote_tokens); + + _z_session_mutex_unlock(zn); +} + +#endif // Z_FEATURE_LIVELINESS == 1 diff --git a/src/session/push.c b/src/session/push.c index a9537be38..098a1ec24 100644 --- a/src/session/push.c +++ b/src/session/push.c @@ -27,17 +27,14 @@ z_result_t _z_trigger_push(_z_session_t *zn, _z_n_msg_push_t *push, z_reliabilit // TODO check body to know where to dispatch - size_t kind = push->_body._is_put ? Z_SAMPLE_KIND_PUT : Z_SAMPLE_KIND_DELETE; if (push->_body._is_put) { _z_msg_put_t *put = &push->_body._body._put; - ret = _z_trigger_subscriptions(zn, &push->_key, &put->_payload, &put->_encoding, kind, - &put->_commons._timestamp, push->_qos, &put->_attachment, reliability); + ret = _z_trigger_subscriptions_put(zn, &push->_key, &put->_payload, &put->_encoding, &put->_commons._timestamp, + push->_qos, &put->_attachment, reliability); } else { - _z_encoding_t encoding = _z_encoding_null(); - _z_bytes_t payload = _z_bytes_null(); _z_msg_del_t *del = &push->_body._body._del; - ret = _z_trigger_subscriptions(zn, &push->_key, &payload, &encoding, kind, &del->_commons._timestamp, - push->_qos, &del->_attachment, reliability); + ret = _z_trigger_subscriptions_del(zn, &push->_key, &del->_commons._timestamp, push->_qos, &del->_attachment, + reliability); } return ret; } diff --git a/src/session/queryable.c b/src/session/queryable.c index d3b120751..06d81c647 100644 --- a/src/session/queryable.c +++ b/src/session/queryable.c @@ -231,6 +231,8 @@ static z_result_t _z_trigger_queryables_inner(_z_session_rc_t *zsrc, _z_msg_quer _z_queryable_infos_t *qle_info = _z_queryable_infos_svec_get(&qles, i); qle_info->callback(&query, qle_info->arg); } + // Send reply final message + _z_query_send_reply_final(&query); // Clean up _z_keyexpr_clear(&key); #if Z_FEATURE_RX_CACHE != 1 diff --git a/src/session/resource.c b/src/session/resource.c index 2413a1d21..b95b4c850 100644 --- a/src/session/resource.c +++ b/src/session/resource.c @@ -31,6 +31,11 @@ bool _z_resource_eq(const _z_resource_t *other, const _z_resource_t *this_) { re void _z_resource_clear(_z_resource_t *res) { _z_keyexpr_clear(&res->_key); } +size_t _z_resource_size(_z_resource_t *p) { + _ZP_UNUSED(p); + return sizeof(_z_resource_t); +} + void _z_resource_copy(_z_resource_t *dst, const _z_resource_t *src) { _z_keyexpr_copy(&dst->_key, &src->_key); dst->_id = src->_id; diff --git a/src/session/rx.c b/src/session/rx.c index c15e53810..d94621b70 100644 --- a/src/session/rx.c +++ b/src/session/rx.c @@ -25,11 +25,11 @@ #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/keyexpr.h" #include "zenoh-pico/session/interest.h" +#include "zenoh-pico/session/liveliness.h" #include "zenoh-pico/session/push.h" #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/reply.h" #include "zenoh-pico/session/resource.h" -#include "zenoh-pico/session/session.h" #include "zenoh-pico/session/subscription.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/common/tx.h" @@ -42,8 +42,8 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * switch (msg->_tag) { case _Z_N_DECLARE: { - _Z_DEBUG("Handling _Z_N_DECLARE"); _z_n_msg_declare_t *decl = &msg->_body._declare; + _Z_DEBUG("Handling _Z_N_DECLARE: %i", decl->_decl._tag); switch (decl->_decl._tag) { case _Z_DECL_KEXPR: { if (_z_register_resource(zn, decl->_decl._body._decl_kexpr._keyexpr, @@ -60,19 +60,28 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * case _Z_DECL_QUERYABLE: { _z_interest_process_declares(zn, &decl->_decl); } break; + case _Z_DECL_TOKEN: { +#if Z_FEATURE_LIVELINESS == 1 + _z_liveliness_process_token_declare(zn, decl); +#endif + _z_interest_process_declares(zn, &decl->_decl); + } break; case _Z_UNDECL_SUBSCRIBER: { _z_interest_process_undeclares(zn, &decl->_decl); } break; case _Z_UNDECL_QUERYABLE: { _z_interest_process_undeclares(zn, &decl->_decl); } break; - case _Z_DECL_TOKEN: { - // TODO: add support or explicitly discard - } break; case _Z_UNDECL_TOKEN: { - // TODO: add support or explicitly discard +#if Z_FEATURE_LIVELINESS == 1 + _z_liveliness_process_token_undeclare(zn, decl); +#endif + _z_interest_process_undeclares(zn, &decl->_decl); } break; case _Z_DECL_FINAL: { +#if Z_FEATURE_LIVELINESS == 1 + _z_liveliness_process_declare_final(zn, decl); +#endif // Check that interest id is valid if (!decl->has_interest_id) { return _Z_ERR_MESSAGE_ZENOH_DECLARATION_UNKNOWN; @@ -101,9 +110,9 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * case _Z_REQUEST_PUT: { #if Z_FEATURE_SUBSCRIPTION == 1 _z_msg_put_t put = req->_body._put; - ret = _z_trigger_subscriptions(zn, &req->_key, &put._payload, &put._encoding, Z_SAMPLE_KIND_PUT, - &put._commons._timestamp, req->_ext_qos, &put._attachment, - msg->_reliability); + ret = _z_trigger_subscriptions_put(zn, &req->_key, &put._payload, &put._encoding, + &put._commons._timestamp, req->_ext_qos, &put._attachment, + msg->_reliability); #endif if (ret == _Z_RES_OK) { _z_network_message_t final = _z_n_msg_make_response_final(req->_rid); @@ -113,11 +122,8 @@ z_result_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t * case _Z_REQUEST_DEL: { #if Z_FEATURE_SUBSCRIPTION == 1 _z_msg_del_t del = req->_body._del; - _z_encoding_t encoding = _z_encoding_null(); - _z_bytes_t empty_payload = _z_bytes_null(); - ret = _z_trigger_subscriptions(zn, &req->_key, &empty_payload, &encoding, Z_SAMPLE_KIND_DELETE, - &del._commons._timestamp, req->_ext_qos, &del._attachment, - msg->_reliability); + ret = _z_trigger_subscriptions_del(zn, &req->_key, &del._commons._timestamp, req->_ext_qos, + &del._attachment, msg->_reliability); #endif if (ret == _Z_RES_OK) { _z_network_message_t final = _z_n_msg_make_response_final(req->_rid); diff --git a/src/session/subscription.c b/src/session/subscription.c index cad4821a5..99c53672d 100644 --- a/src/session/subscription.c +++ b/src/session/subscription.c @@ -17,6 +17,7 @@ #include #include +#include "zenoh-pico/api/constants.h" #include "zenoh-pico/api/types.h" #include "zenoh-pico/config.h" #include "zenoh-pico/net/sample.h" @@ -116,9 +117,10 @@ _z_subscription_rc_t *__z_get_subscription_by_id(_z_subscription_rc_list_t *subs * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_subscription_rc_t *__unsafe_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id) { +_z_subscription_rc_t *__unsafe_z_get_subscription_by_id(_z_session_t *zn, _z_subscriber_kind_t kind, + const _z_zint_t id) { _z_subscription_rc_list_t *subs = - (is_local == _Z_RESOURCE_IS_LOCAL) ? zn->_local_subscriptions : zn->_remote_subscriptions; + (kind == _Z_SUBSCRIBER_KIND_SUBSCRIBER) ? zn->_subscriptions : zn->_liveliness_subscriptions; return __z_get_subscription_by_id(subs, id); } @@ -127,10 +129,11 @@ _z_subscription_rc_t *__unsafe_z_get_subscription_by_id(_z_session_t *zn, uint8_ * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -static z_result_t __unsafe_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *key, +static z_result_t __unsafe_z_get_subscriptions_by_key(_z_session_t *zn, _z_subscriber_kind_t kind, + const _z_keyexpr_t *key, _z_subscription_infos_svec_t *sub_infos) { _z_subscription_rc_list_t *subs = - (is_local == _Z_RESOURCE_IS_LOCAL) ? zn->_local_subscriptions : zn->_remote_subscriptions; + (kind == _Z_SUBSCRIBER_KIND_SUBSCRIBER) ? zn->_subscriptions : zn->_liveliness_subscriptions; *sub_infos = _z_subscription_infos_svec_make(_Z_SUBINFOS_VEC_SIZE); _z_subscription_rc_list_t *xs = subs; @@ -147,17 +150,17 @@ static z_result_t __unsafe_z_get_subscriptions_by_key(_z_session_t *zn, uint8_t return _Z_RES_OK; } -_z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id) { +_z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, _z_subscriber_kind_t kind, const _z_zint_t id) { _z_session_mutex_lock(zn); - _z_subscription_rc_t *sub = __unsafe_z_get_subscription_by_id(zn, is_local, id); + _z_subscription_rc_t *sub = __unsafe_z_get_subscription_by_id(zn, kind, id); _z_session_mutex_unlock(zn); return sub; } -_z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_t *s) { +_z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, _z_subscriber_kind_t kind, _z_subscription_t *s) { _Z_DEBUG(">>> Allocating sub decl for (%ju:%.*s)", (uintmax_t)s->_key._id, (int)_z_string_len(&s->_key._suffix), _z_string_data(&s->_key._suffix)); _z_subscription_rc_t *ret = NULL; @@ -167,10 +170,10 @@ _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_loca ret = (_z_subscription_rc_t *)z_malloc(sizeof(_z_subscription_rc_t)); if (ret != NULL) { *ret = _z_subscription_rc_new_from_val(s); - if (is_local == _Z_RESOURCE_IS_LOCAL) { - zn->_local_subscriptions = _z_subscription_rc_list_push(zn->_local_subscriptions, ret); + if (kind == _Z_SUBSCRIBER_KIND_SUBSCRIBER) { + zn->_subscriptions = _z_subscription_rc_list_push(zn->_subscriptions, ret); } else { - zn->_remote_subscriptions = _z_subscription_rc_list_push(zn->_remote_subscriptions, ret); + zn->_liveliness_subscriptions = _z_subscription_rc_list_push(zn->_liveliness_subscriptions, ret); } } @@ -179,16 +182,45 @@ _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_loca return ret; } -void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, - _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - _z_bytes_t *attachment, z_reliability_t reliability) { - z_result_t ret = _z_trigger_subscriptions(zn, keyexpr, payload, encoding, Z_SAMPLE_KIND_PUT, timestamp, qos, - attachment, reliability); - (void)ret; +z_result_t _z_trigger_subscriptions_put(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, + _z_encoding_t *encoding, const _z_timestamp_t *timestamp, const _z_n_qos_t qos, + _z_bytes_t *attachment, z_reliability_t reliability) { + return _z_trigger_subscriptions_impl(zn, _Z_SUBSCRIBER_KIND_SUBSCRIBER, keyexpr, payload, encoding, + Z_SAMPLE_KIND_PUT, timestamp, qos, attachment, reliability); } -static z_result_t _z_subscription_get_infos(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_keyexpr_t *key, - _z_subscription_infos_svec_t *subs, size_t *sub_nb) { +z_result_t _z_trigger_subscriptions_del(_z_session_t *zn, _z_keyexpr_t *keyexpr, const _z_timestamp_t *timestamp, + const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability) { + _z_encoding_t encoding = _z_encoding_null(); + _z_bytes_t payload = _z_bytes_null(); + return _z_trigger_subscriptions_impl(zn, _Z_SUBSCRIBER_KIND_SUBSCRIBER, keyexpr, &payload, &encoding, + Z_SAMPLE_KIND_DELETE, timestamp, qos, attachment, reliability); +} + +z_result_t _z_trigger_liveliness_subscriptions_declare(_z_session_t *zn, _z_keyexpr_t *keyexpr, + const _z_timestamp_t *timestamp) { + _z_encoding_t encoding = _z_encoding_null(); + _z_bytes_t payload = _z_bytes_null(); + _z_bytes_t attachment = _z_bytes_null(); + _z_keyexpr_t key = _z_keyexpr_alias(*keyexpr); + return _z_trigger_subscriptions_impl(zn, _Z_SUBSCRIBER_KIND_LIVELINESS_SUBSCRIBER, &key, &payload, &encoding, + Z_SAMPLE_KIND_PUT, timestamp, _Z_N_QOS_DEFAULT, &attachment, + Z_RELIABILITY_RELIABLE); +} + +z_result_t _z_trigger_liveliness_subscriptions_undeclare(_z_session_t *zn, _z_keyexpr_t *keyexpr, + const _z_timestamp_t *timestamp) { + _z_encoding_t encoding = _z_encoding_null(); + _z_bytes_t payload = _z_bytes_null(); + _z_bytes_t attachment = _z_bytes_null(); + _z_keyexpr_t key = _z_keyexpr_alias(*keyexpr); + return _z_trigger_subscriptions_impl(zn, _Z_SUBSCRIBER_KIND_LIVELINESS_SUBSCRIBER, &key, &payload, &encoding, + Z_SAMPLE_KIND_DELETE, timestamp, _Z_N_QOS_DEFAULT, &attachment, + Z_RELIABILITY_RELIABLE); +} + +static z_result_t _z_subscription_get_infos(_z_session_t *zn, _z_subscriber_kind_t kind, const _z_keyexpr_t *keyexpr, + _z_keyexpr_t *key, _z_subscription_infos_svec_t *subs, size_t *sub_nb) { // Check cache if (!_z_subscription_get_from_cache(zn, keyexpr, key, subs, sub_nb)) { _Z_DEBUG("Resolving %d - %.*s on mapping 0x%x", keyexpr->_id, (int)_z_string_len(&keyexpr->_suffix), @@ -201,7 +233,7 @@ static z_result_t _z_subscription_get_infos(_z_session_t *zn, const _z_keyexpr_t return _Z_ERR_KEYEXPR_UNKNOWN; } // Get subscription list - z_result_t ret = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, key, subs); + z_result_t ret = __unsafe_z_get_subscriptions_by_key(zn, kind, key, subs); _z_session_mutex_unlock(zn); if (ret != _Z_RES_OK) { return ret; @@ -213,15 +245,16 @@ static z_result_t _z_subscription_get_infos(_z_session_t *zn, const _z_keyexpr_t return _Z_RES_OK; } -static z_result_t _z_trigger_subscriptions_inner(_z_session_t *zn, const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, - _z_encoding_t *encoding, const _z_zint_t kind, +static z_result_t _z_trigger_subscriptions_inner(_z_session_t *zn, _z_subscriber_kind_t sub_kind, + const _z_keyexpr_t *keyexpr, _z_bytes_t *payload, + _z_encoding_t *encoding, const _z_zint_t sample_kind, const _z_timestamp_t *timestamp, const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability) { _z_keyexpr_t key; _z_subscription_infos_svec_t subs; size_t sub_nb; // Retrieve sub infos - _Z_RETURN_IF_ERR(_z_subscription_get_infos(zn, keyexpr, &key, &subs, &sub_nb)); + _Z_RETURN_IF_ERR(_z_subscription_get_infos(zn, sub_kind, keyexpr, &key, &subs, &sub_nb)); // Check if there are subs _Z_DEBUG("Triggering %ju subs for key %d - %.*s", (uintmax_t)sub_nb, key._id, (int)_z_string_len(&key._suffix), _z_string_data(&key._suffix)); @@ -230,7 +263,7 @@ static z_result_t _z_trigger_subscriptions_inner(_z_session_t *zn, const _z_keye return _Z_RES_OK; } // Create sample - _z_sample_t sample = _z_sample_alias(&key, payload, timestamp, encoding, kind, qos, attachment, reliability); + _z_sample_t sample = _z_sample_alias(&key, payload, timestamp, encoding, sample_kind, qos, attachment, reliability); // Parse subscription infos svec for (size_t i = 0; i < sub_nb; i++) { _z_subscription_infos_t *sub_info = _z_subscription_infos_svec_get(&subs, i); @@ -244,11 +277,12 @@ static z_result_t _z_trigger_subscriptions_inner(_z_session_t *zn, const _z_keye return _Z_RES_OK; } -z_result_t _z_trigger_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, - _z_encoding_t *encoding, const _z_zint_t kind, const _z_timestamp_t *timestamp, - const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability) { - z_result_t ret = - _z_trigger_subscriptions_inner(zn, keyexpr, payload, encoding, kind, timestamp, qos, attachment, reliability); +z_result_t _z_trigger_subscriptions_impl(_z_session_t *zn, _z_subscriber_kind_t sub_kind, _z_keyexpr_t *keyexpr, + _z_bytes_t *payload, _z_encoding_t *encoding, const _z_zint_t sample_kind, + const _z_timestamp_t *timestamp, const _z_n_qos_t qos, _z_bytes_t *attachment, + z_reliability_t reliability) { + z_result_t ret = _z_trigger_subscriptions_inner(zn, sub_kind, keyexpr, payload, encoding, sample_kind, timestamp, + qos, attachment, reliability); // Clean up _z_keyexpr_clear(keyexpr); _z_encoding_clear(encoding); @@ -257,15 +291,14 @@ z_result_t _z_trigger_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_ return ret; } -void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub) { +void _z_unregister_subscription(_z_session_t *zn, _z_subscriber_kind_t kind, _z_subscription_rc_t *sub) { _z_session_mutex_lock(zn); - if (is_local == _Z_RESOURCE_IS_LOCAL) { - zn->_local_subscriptions = - _z_subscription_rc_list_drop_filter(zn->_local_subscriptions, _z_subscription_rc_eq, sub); + if (kind == _Z_SUBSCRIBER_KIND_SUBSCRIBER) { + zn->_subscriptions = _z_subscription_rc_list_drop_filter(zn->_subscriptions, _z_subscription_rc_eq, sub); } else { - zn->_remote_subscriptions = - _z_subscription_rc_list_drop_filter(zn->_remote_subscriptions, _z_subscription_rc_eq, sub); + zn->_liveliness_subscriptions = + _z_subscription_rc_list_drop_filter(zn->_liveliness_subscriptions, _z_subscription_rc_eq, sub); } _z_session_mutex_unlock(zn); @@ -274,16 +307,16 @@ void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscript void _z_flush_subscriptions(_z_session_t *zn) { _z_session_mutex_lock(zn); - _z_subscription_rc_list_free(&zn->_local_subscriptions); - _z_subscription_rc_list_free(&zn->_remote_subscriptions); + _z_subscription_rc_list_free(&zn->_subscriptions); + _z_subscription_rc_list_free(&zn->_liveliness_subscriptions); _z_session_mutex_unlock(zn); } #else // Z_FEATURE_SUBSCRIPTION == 0 -void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, - _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, - _z_bytes_t *attachment, z_reliability_t reliability) { +z_result_t _z_trigger_subscriptions_put(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_bytes_t *payload, + _z_encoding_t *encoding, const _z_timestamp_t *timestamp, const _z_n_qos_t qos, + _z_bytes_t *attachment, z_reliability_t reliability) { _ZP_UNUSED(zn); _ZP_UNUSED(keyexpr); _ZP_UNUSED(payload); @@ -292,6 +325,38 @@ void _z_trigger_local_subscriptions(_z_session_t *zn, _z_keyexpr_t *keyexpr, _z_ _ZP_UNUSED(timestamp); _ZP_UNUSED(attachment); _ZP_UNUSED(reliability); + + return _Z_RES_OK; +} + +z_result_t _z_trigger_subscriptions_del(_z_session_t *zn, _z_keyexpr_t *keyexpr, const _z_timestamp_t *timestamp, + const _z_n_qos_t qos, _z_bytes_t *attachment, z_reliability_t reliability) { + _ZP_UNUSED(zn); + _ZP_UNUSED(keyexpr); + _ZP_UNUSED(qos); + _ZP_UNUSED(timestamp); + _ZP_UNUSED(attachment); + _ZP_UNUSED(reliability); + + return _Z_RES_OK; +} + +z_result_t _z_trigger_liveliness_subscriptions_declare(_z_session_t *zn, _z_keyexpr_t *keyexpr, + const _z_timestamp_t *timestamp) { + _ZP_UNUSED(zn); + _ZP_UNUSED(keyexpr); + _ZP_UNUSED(timestamp); + + return _Z_RES_OK; +} + +z_result_t _z_trigger_liveliness_subscriptions_undeclare(_z_session_t *zn, _z_keyexpr_t *keyexpr, + const _z_timestamp_t *timestamp) { + _ZP_UNUSED(zn); + _ZP_UNUSED(keyexpr); + _ZP_UNUSED(timestamp); + + return _Z_RES_OK; } #endif // Z_FEATURE_SUBSCRIPTION == 1 diff --git a/src/session/utils.c b/src/session/utils.c index 84ad8793e..90ec97912 100644 --- a/src/session/utils.c +++ b/src/session/utils.c @@ -19,11 +19,11 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/session/interest.h" +#include "zenoh-pico/session/liveliness.h" #include "zenoh-pico/session/query.h" #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/resource.h" #include "zenoh-pico/session/subscription.h" -#include "zenoh-pico/utils/logging.h" /*------------------ clone helpers ------------------*/ void _z_timestamp_copy(_z_timestamp_t *dst, const _z_timestamp_t *src) { *dst = *src; } @@ -60,8 +60,8 @@ z_result_t _z_session_init(_z_session_rc_t *zsrc, _z_id_t *zid) { zn->_local_resources = NULL; zn->_remote_resources = NULL; #if Z_FEATURE_SUBSCRIPTION == 1 - zn->_local_subscriptions = NULL; - zn->_remote_subscriptions = NULL; + zn->_subscriptions = NULL; + zn->_liveliness_subscriptions = NULL; #if Z_FEATURE_RX_CACHE == 1 memset(&zn->_subscription_cache, 0, sizeof(zn->_subscription_cache)); #endif @@ -84,6 +84,10 @@ z_result_t _z_session_init(_z_session_rc_t *zsrc, _z_id_t *zid) { } #endif // Z_FEATURE_MULTI_THREAD == 1 +#if Z_FEATURE_LIVELINESS == 1 + _z_liveliness_init(zn); +#endif + zn->_local_zid = *zid; // Note session in transport switch (zn->_tp._type) { @@ -131,6 +135,9 @@ void _z_session_clear(_z_session_t *zn) { #endif #if Z_FEATURE_QUERY == 1 _z_flush_pending_queries(zn); +#endif +#if Z_FEATURE_LIVELINESS == 1 + _z_liveliness_clear(zn); #endif _z_flush_interest(zn); diff --git a/tests/z_api_liveliness_test.c b/tests/z_api_liveliness_test.c new file mode 100644 index 000000000..2cf4c350e --- /dev/null +++ b/tests/z_api_liveliness_test.c @@ -0,0 +1,229 @@ +// +// Copyright (c) 2024 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, + +#include +#include +#include +#include +#include +#include + +#include "zenoh-pico.h" +#include "zenoh-pico/api/handlers.h" +#include "zenoh-pico/api/liveliness.h" +#include "zenoh-pico/api/primitives.h" +#include "zenoh-pico/api/types.h" + +#if Z_FEATURE_LIVELINESS == 1 && Z_FEATURE_SUBSCRIPTION == 1 && Z_FEATURE_QUERY == 1 + +#undef NDEBUG +#include +typedef struct context_t { + bool token1_put; + bool token2_put; + bool token1_drop; + bool token2_drop; +} context_t; + +#define assert_ok(x) \ + { \ + int ret = (int)x; \ + if (ret != Z_OK) { \ + printf("%s failed: %d\n", #x, ret); \ + assert(false); \ + } \ + } + +const char* token1_expr = "zenoh-pico/liveliness/test/1"; +const char* token2_expr = "zenoh-pico/liveliness/test/2"; + +void on_receive(z_loaned_sample_t* s, void* context) { + context_t* c = (context_t*)context; + const z_loaned_keyexpr_t* k = z_sample_keyexpr(s); + z_view_string_t ks; + z_keyexpr_as_view_string(k, &ks); + + if (z_sample_kind(s) == Z_SAMPLE_KIND_PUT) { + if (strncmp(token1_expr, z_string_data(z_view_string_loan(&ks)), z_string_len(z_view_string_loan(&ks))) == 0) { + c->token1_put = true; + } else if (strncmp(token2_expr, z_string_data(z_view_string_loan(&ks)), + z_string_len(z_view_string_loan(&ks))) == 0) { + c->token2_put = true; + } + } else if (z_sample_kind(s) == Z_SAMPLE_KIND_DELETE) { + if (strncmp(token1_expr, z_string_data(z_view_string_loan(&ks)), z_string_len(z_view_string_loan(&ks))) == 0) { + c->token1_drop = true; + } else if (strncmp(token2_expr, z_string_data(z_view_string_loan(&ks)), + z_string_len(z_view_string_loan(&ks))) == 0) { + c->token2_drop = true; + } + } +} + +void test_liveliness_sub(bool multicast, bool history) { + printf("test_liveliness_sub: multicast=%d, history=%d\n", multicast, history); + const char* expr = "zenoh-pico/liveliness/test/*"; + + z_owned_session_t s1, s2; + z_owned_config_t c1, c2; + z_config_default(&c1); + z_config_default(&c2); + z_view_keyexpr_t k, k1, k2; + z_view_keyexpr_from_str(&k, expr); + z_view_keyexpr_from_str(&k1, token1_expr); + z_view_keyexpr_from_str(&k2, token2_expr); + + if (multicast) { + zp_config_insert(z_loan_mut(c1), Z_CONFIG_MODE_KEY, "peer"); + zp_config_insert(z_loan_mut(c1), Z_CONFIG_LISTEN_KEY, "udp/224.0.0.224:7447#iface=lo"); + + zp_config_insert(z_loan_mut(c2), Z_CONFIG_MODE_KEY, "client"); + zp_config_insert(z_loan_mut(c2), Z_CONFIG_LISTEN_KEY, "udp/224.0.0.224:7447#iface=lo"); + } + + assert_ok(z_open(&s1, z_config_move(&c1), NULL)); + assert_ok(z_open(&s2, z_config_move(&c2), NULL)); + + assert_ok(zp_start_read_task(z_loan_mut(s1), NULL)); + assert_ok(zp_start_read_task(z_loan_mut(s2), NULL)); + assert_ok(zp_start_lease_task(z_loan_mut(s1), NULL)); + assert_ok(zp_start_lease_task(z_loan_mut(s2), NULL)); + + z_owned_liveliness_token_t t1, t2; + // In history mode we can declare token before subsribing + if (history) { + assert_ok(z_liveliness_declare_token(z_session_loan(&s2), &t1, z_view_keyexpr_loan(&k1), NULL)); + assert_ok(z_liveliness_declare_token(z_session_loan(&s2), &t2, z_view_keyexpr_loan(&k2), NULL)); + } + + z_sleep_s(1); + z_owned_closure_sample_t closure; + context_t context = {false, false, false, false}; + z_closure_sample(&closure, on_receive, NULL, (void*)(&context)); + + z_owned_subscriber_t sub; + z_liveliness_subscriber_options_t sub_opt; + z_liveliness_subscriber_options_default(&sub_opt); + sub_opt.history = history; + assert_ok(z_liveliness_declare_subscriber(z_session_loan(&s1), &sub, z_view_keyexpr_loan(&k), + z_closure_sample_move(&closure), &sub_opt)); + + z_sleep_s(1); + if (!history) { + assert_ok(z_liveliness_declare_token(z_session_loan(&s2), &t1, z_view_keyexpr_loan(&k1), NULL)); + assert_ok(z_liveliness_declare_token(z_session_loan(&s2), &t2, z_view_keyexpr_loan(&k2), NULL)); + } + + z_sleep_s(1); + + assert(context.token1_put); + assert(context.token2_put); + + assert_ok(z_liveliness_undeclare_token(z_liveliness_token_move(&t1))); + z_sleep_s(1); + + assert(context.token1_drop); + assert(!context.token2_drop); + + assert_ok(z_liveliness_undeclare_token(z_liveliness_token_move(&t2))); + z_sleep_s(1); + assert(context.token2_drop); + + assert_ok(zp_stop_read_task(z_loan_mut(s1))); + assert_ok(zp_stop_read_task(z_loan_mut(s2))); + assert_ok(zp_stop_lease_task(z_loan_mut(s1))); + assert_ok(zp_stop_lease_task(z_loan_mut(s2))); + + z_session_drop(z_session_move(&s1)); + z_session_drop(z_session_move(&s2)); +} + +void test_liveliness_get(void) { + const char* expr = "zenoh-pico/liveliness/test/*"; + + z_owned_session_t s1, s2; + z_owned_config_t c1, c2; + z_config_default(&c1); + z_config_default(&c2); + z_view_keyexpr_t k, k1; + z_view_keyexpr_from_str(&k, expr); + z_view_keyexpr_from_str(&k1, token1_expr); + + assert_ok(z_open(&s1, z_config_move(&c1), NULL)); + assert_ok(z_open(&s2, z_config_move(&c2), NULL)); + + assert_ok(zp_start_read_task(z_loan_mut(s1), NULL)); + assert_ok(zp_start_read_task(z_loan_mut(s2), NULL)); + assert_ok(zp_start_lease_task(z_loan_mut(s1), NULL)); + assert_ok(zp_start_lease_task(z_loan_mut(s2), NULL)); + + z_sleep_s(1); + z_owned_liveliness_token_t t1; + assert_ok(z_liveliness_declare_token(z_session_loan(&s1), &t1, z_view_keyexpr_loan(&k1), NULL)); + z_sleep_s(1); + + z_owned_fifo_handler_reply_t handler; + z_owned_closure_reply_t cb; + assert_ok(z_fifo_channel_reply_new(&cb, &handler, 3)); + + assert_ok(z_liveliness_get(z_session_loan(&s2), z_view_keyexpr_loan(&k), z_closure_reply_move(&cb), NULL)); + z_owned_reply_t reply; + assert_ok(z_fifo_handler_reply_recv(z_fifo_handler_reply_loan(&handler), &reply)); + assert(z_reply_is_ok(z_reply_loan(&reply))); + const z_loaned_keyexpr_t* reply_keyexpr = z_sample_keyexpr(z_reply_ok(z_reply_loan(&reply))); + z_view_string_t reply_keyexpr_s; + z_keyexpr_as_view_string(reply_keyexpr, &reply_keyexpr_s); + assert(strlen(token1_expr) == z_string_len(z_view_string_loan(&reply_keyexpr_s))); + assert(strncmp(token1_expr, z_string_data(z_view_string_loan(&reply_keyexpr_s)), + z_string_len(z_view_string_loan(&reply_keyexpr_s))) == 0); + + z_reply_drop(z_reply_move(&reply)); + assert(z_fifo_handler_reply_recv(z_fifo_handler_reply_loan(&handler), &reply) == Z_CHANNEL_DISCONNECTED); + + z_liveliness_token_drop(z_liveliness_token_move(&t1)); + z_fifo_handler_reply_drop(z_fifo_handler_reply_move(&handler)); + z_sleep_s(1); + assert_ok(z_fifo_channel_reply_new(&cb, &handler, 3)); + + z_liveliness_get(z_session_loan(&s2), z_view_keyexpr_loan(&k), z_closure_reply_move(&cb), NULL); + assert(z_fifo_handler_reply_recv(z_fifo_handler_reply_loan(&handler), &reply) == Z_CHANNEL_DISCONNECTED); + + z_fifo_handler_reply_drop(z_fifo_handler_reply_move(&handler)); + + assert_ok(zp_stop_read_task(z_loan_mut(s1))); + assert_ok(zp_stop_read_task(z_loan_mut(s2))); + assert_ok(zp_stop_lease_task(z_loan_mut(s1))); + assert_ok(zp_stop_lease_task(z_loan_mut(s2))); + + z_session_drop(z_session_move(&s1)); + z_session_drop(z_session_move(&s2)); +} + +int main(int argc, char** argv) { + (void)argc; + (void)argv; +#if defined(ZENOH_LINUX) + test_liveliness_sub(true, false); + test_liveliness_sub(true, true); +#endif + test_liveliness_sub(false, false); + test_liveliness_sub(false, true); + test_liveliness_get(); +} + +#else +int main(int argc, char** argv) { + (void)argc; + (void)argv; +} +#endif diff --git a/tests/z_client_test.c b/tests/z_client_test.c index ca230002c..559505de5 100644 --- a/tests/z_client_test.c +++ b/tests/z_client_test.c @@ -134,7 +134,7 @@ int main(int argc, char **argv) { z_owned_session_t s1; assert(z_open(&s1, z_move(config), NULL) == Z_OK); _z_string_t zid1 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); - printf("Session 1 with PID: %*.s\n", (int)_z_string_len(&zid1), _z_string_data(&zid1)); + printf("Session 1 with PID: %.*s\n", (int)_z_string_len(&zid1), _z_string_data(&zid1)); _z_string_clear(&zid1); // Start the read session session lease loops @@ -150,7 +150,7 @@ int main(int argc, char **argv) { assert(z_open(&s2, z_move(config), NULL) == Z_OK); assert(z_internal_check(s2)); _z_string_t zid2 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); - printf("Session 2 with PID: %*.s\n", (int)_z_string_len(&zid2), _z_string_data(&zid2)); + printf("Session 2 with PID: %.*s\n", (int)_z_string_len(&zid2), _z_string_data(&zid2)); _z_string_clear(&zid2); // Start the read session session lease loops diff --git a/tests/z_collections_test.c b/tests/z_collections_test.c index ec103b444..8bb54007f 100644 --- a/tests/z_collections_test.c +++ b/tests/z_collections_test.c @@ -18,6 +18,7 @@ #include "zenoh-pico/collections/fifo.h" #include "zenoh-pico/collections/lifo.h" +#include "zenoh-pico/collections/list.h" #include "zenoh-pico/collections/ring.h" #include "zenoh-pico/collections/string.h" @@ -308,6 +309,46 @@ void fifo_test_init_free(void) { assert(r == NULL); } +void int_map_iterator_test(void) { + _z_str_intmap_t map; + + map = _z_str_intmap_make(); + _z_str_intmap_insert(&map, 10, "A"); + _z_str_intmap_insert(&map, 20, "B"); + _z_str_intmap_insert(&map, 30, "C"); + _z_str_intmap_insert(&map, 40, "D"); + +#define TEST_MAP(map) \ + { \ + _z_str_intmap_iterator_t iter = _z_str_intmap_iterator_make(&map); \ + assert(_z_str_intmap_iterator_next(&iter)); \ + assert(_z_str_intmap_iterator_key(&iter) == 20); \ + assert(strcmp(_z_str_intmap_iterator_value(&iter), "B") == 0); \ + \ + assert(_z_str_intmap_iterator_next(&iter)); \ + assert(_z_str_intmap_iterator_key(&iter) == 40); \ + assert(strcmp(_z_str_intmap_iterator_value(&iter), "D") == 0); \ + \ + assert(_z_str_intmap_iterator_next(&iter)); \ + assert(_z_str_intmap_iterator_key(&iter) == 10); \ + assert(strcmp(_z_str_intmap_iterator_value(&iter), "A") == 0); \ + \ + assert(_z_str_intmap_iterator_next(&iter)); \ + assert(_z_str_intmap_iterator_key(&iter) == 30); \ + assert(strcmp(_z_str_intmap_iterator_value(&iter), "C") == 0); \ + \ + assert(!_z_str_intmap_iterator_next(&iter)); \ + } + + TEST_MAP(map); + + _z_str_intmap_t map2 = _z_str_intmap_clone(&map); + + TEST_MAP(map2); + +#undef TEST_MAP +} + int main(void) { ring_test(); ring_test_init_free(); @@ -315,4 +356,6 @@ int main(void) { lifo_test_init_free(); fifo_test(); fifo_test_init_free(); + + int_map_iterator_test(); } diff --git a/tests/z_msgcodec_test.c b/tests/z_msgcodec_test.c index 1b0b134c5..97ef0172f 100644 --- a/tests/z_msgcodec_test.c +++ b/tests/z_msgcodec_test.c @@ -844,6 +844,49 @@ void queryable_declaration(void) { _z_wbuf_clear(&wbf); } +/*------------------ Token declaration ------------------*/ +_z_decl_token_t gen_token_declaration(void) { + _z_decl_token_t e_qd = {._keyexpr = gen_keyexpr(), ._id = (uint32_t)gen_uint64()}; + + return e_qd; +} + +void assert_eq_token_declaration(const _z_decl_token_t *left, const _z_decl_token_t *right) { + assert_eq_keyexpr(&left->_keyexpr, &right->_keyexpr); + assert(left->_id == right->_id); +} + +void token_declaration(void) { + printf("\n>> Queryable declaration\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + + // Initialize + _z_decl_token_t e_qd = gen_token_declaration(); + + // Encode + int8_t res = _z_decl_token_encode(&wbf, &e_qd); + assert(res == _Z_RES_OK); + (void)(res); + + // Decode + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + _z_decl_token_t d_qd; + uint8_t e_hdr = 0; + _z_uint8_decode(&e_hdr, &zbf); + res = _z_decl_token_decode(&d_qd, &zbf, e_hdr); + assert(res == _Z_RES_OK); + + printf(" "); + assert_eq_token_declaration(&e_qd, &d_qd); + printf("\n"); + + // Free + _z_keyexpr_clear(&e_qd._keyexpr); + _z_keyexpr_clear(&d_qd._keyexpr); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} + /*------------------ Forget Resource declaration ------------------*/ _z_undecl_kexpr_t gen_forget_resource_declaration(void) { _z_undecl_kexpr_t e_frd; @@ -971,12 +1014,52 @@ void forget_queryable_declaration(void) { _z_wbuf_clear(&wbf); } +/*------------------ Forget Token declaration ------------------*/ +_z_undecl_token_t gen_forget_token_declaration(void) { + _z_undecl_token_t e_fqd = {._ext_keyexpr = gen_keyexpr(), ._id = (uint32_t)gen_zint()}; + return e_fqd; +} + +void assert_eq_forget_token_declaration(const _z_undecl_token_t *left, const _z_undecl_token_t *right) { + assert_eq_keyexpr(&left->_ext_keyexpr, &right->_ext_keyexpr); + assert(left->_id == right->_id); +} + +void forget_token_declaration(void) { + printf("\n>> Forget token declaration\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + + // Initialize + _z_undecl_token_t e_fqd = gen_forget_token_declaration(); + + // Encode + int8_t res = _z_undecl_token_encode(&wbf, &e_fqd); + assert(res == _Z_RES_OK); + (void)(res); + + // Decode + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + uint8_t e_hdr = 0; + _z_uint8_decode(&e_hdr, &zbf); + _z_undecl_token_t d_fqd = {._ext_keyexpr = _z_keyexpr_null()}; + res = _z_undecl_token_decode(&d_fqd, &zbf, e_hdr); + assert(res == _Z_RES_OK); + + printf(" "); + assert_eq_forget_token_declaration(&e_fqd, &d_fqd); + printf("\n"); + + // Free + _z_keyexpr_clear(&e_fqd._ext_keyexpr); + _z_keyexpr_clear(&d_fqd._ext_keyexpr); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} + /*------------------ Declaration ------------------*/ _z_declaration_t gen_declaration(void) { - uint8_t decl[] = { - _Z_DECL_KEXPR, _Z_UNDECL_KEXPR, _Z_DECL_SUBSCRIBER, - _Z_UNDECL_SUBSCRIBER, _Z_DECL_QUERYABLE, _Z_UNDECL_QUERYABLE, - }; + uint8_t decl[] = {_Z_DECL_KEXPR, _Z_UNDECL_KEXPR, _Z_DECL_SUBSCRIBER, _Z_UNDECL_SUBSCRIBER, + _Z_DECL_QUERYABLE, _Z_UNDECL_QUERYABLE, _Z_DECL_TOKEN, _Z_UNDECL_TOKEN}; _z_declaration_t d; d._tag = decl[gen_uint8() % (sizeof(decl) / sizeof(uint8_t))]; @@ -1000,6 +1083,12 @@ _z_declaration_t gen_declaration(void) { case _Z_UNDECL_QUERYABLE: { d._body._undecl_queryable = gen_forget_queryable_declaration(); } break; + case _Z_DECL_TOKEN: { + d._body._decl_token = gen_token_declaration(); + } break; + case _Z_UNDECL_TOKEN: { + d._body._undecl_token = gen_forget_token_declaration(); + } break; default: assert(false); } @@ -1022,6 +1111,9 @@ void assert_eq_declaration(const _z_declaration_t *left, const _z_declaration_t case _Z_DECL_QUERYABLE: assert_eq_queryable_declaration(&left->_body._decl_queryable, &right->_body._decl_queryable); break; + case _Z_DECL_TOKEN: + assert_eq_token_declaration(&left->_body._decl_token, &right->_body._decl_token); + break; case _Z_UNDECL_KEXPR: assert_eq_forget_resource_declaration(&left->_body._undecl_kexpr, &right->_body._undecl_kexpr); break; @@ -1031,6 +1123,9 @@ void assert_eq_declaration(const _z_declaration_t *left, const _z_declaration_t case _Z_UNDECL_QUERYABLE: assert_eq_forget_queryable_declaration(&left->_body._undecl_queryable, &right->_body._undecl_queryable); break; + case _Z_UNDECL_TOKEN: + assert_eq_forget_token_declaration(&left->_body._undecl_token, &right->_body._undecl_token); + break; default: assert(false); } diff --git a/tests/z_peer_multicast_test.c b/tests/z_peer_multicast_test.c index b0cf8e699..7d350eeb5 100644 --- a/tests/z_peer_multicast_test.c +++ b/tests/z_peer_multicast_test.c @@ -78,7 +78,7 @@ int main(int argc, char **argv) { z_owned_session_t s1; assert(z_open(&s1, z_move(config), NULL) == Z_OK); _z_string_t zid1 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s1))->_local_zid)); - printf("Session 1 with PID: %*.s\n", (int)_z_string_len(&zid1), _z_string_data(&zid1)); + printf("Session 1 with PID: %.*s\n", (int)_z_string_len(&zid1), _z_string_data(&zid1)); _z_string_clear(&zid1); // Start the read session session lease loops @@ -95,7 +95,7 @@ int main(int argc, char **argv) { assert(z_open(&s2, z_move(config), NULL) == Z_OK); _z_string_t zid2 = _z_id_to_string(&(_Z_RC_IN_VAL(z_loan(s2))->_local_zid)); - printf("Session 2 with PID: %*.s\n", (int)_z_string_len(&zid2), _z_string_data(&zid2)); + printf("Session 2 with PID: %.*s\n", (int)_z_string_len(&zid2), _z_string_data(&zid2)); _z_string_clear(&zid2); // Start the read session session lease loops diff --git a/zenohpico.pc b/zenohpico.pc index 0bfb73da3..3922083d4 100644 --- a/zenohpico.pc +++ b/zenohpico.pc @@ -3,6 +3,6 @@ prefix=/usr/local Name: zenohpico Description: URL: -Version: 1.0.20241113dev +Version: 1.0.20241115dev Cflags: -I${prefix}/include Libs: -L${prefix}/lib -lzenohpico From eb1e7cf5b5e90a4df5768a3661e60b527cde2f85 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Tue, 19 Nov 2024 16:42:11 +0100 Subject: [PATCH 14/17] Add corrections on 1.1 (#791) * Update closure handlers documentaion (#736) * Rename closure callback/dropper types (#739) * Remove legacy z_zint_t from public API (#741) * Add `export "C"` for all header files (#740) * Add `export "C"` for proper closures callbacks export * Add `export "C"` for all headers * add serialize from substr functions (#742) * Rename z_loaned_hello_handler_t to z_closure_hello_callback_t (#743) * Mark z_reply_replier_id as unstable (#745) * Add documentation about logging (#744) * Update README.md (#746) * hardcode clang-format runner to Ubuntu24.04 (#748) * fix build granularity (#747) * fix: badly named constant (#750) * fix packages * fix: update debian packaging - include libzenohpico.so in debian package - change the package name to libzenohpico in line with libzenohc - set correct debian version for pre releases - fix wrong version used in Release mode * fix: debian dev package name * fix: package version for releases (#753) * fix: debian_version for official releases otherwise they would be undefined * fix: align cpack version with zenoh-c * chore: review comments move cpack version closer to where it's used * build shared lib for packages instead of static one (#757) * Fix z_task cleanup for platforms with pthread support (#759) * Fix read/lease task cleanup (#760) * Align ID string representation with zenoh (lowercase) (#761) * Remove default parameters from z_closure (#755) * build both libraries:shared and static when packaging; (#766) add static library to dev package; * Publish debian packages (#769) * fix: add workflow to release debian packages * fix: align with zenoh-c - update package names - set version string in the same way - set DEBARCH/RPMARCH - set CPACK_PACKAGE_FILE_NAME - add -j to zip archive to not include parent folder * fix: use CPACK_PACKAGE_NAME * fix: pass package name to all build targets * fix: Don't tag release branch during dry-run * Replace exit with return in zephyr examples (#774) * Add platform_common.c to zephyr CMakeLists.txt file * Rework Zenoh ID conversion * chore: Update org secrets (#782) As per eclipse-zenoh/.eclipsefdn#18, secrets were updated to follow eclipse foundation naming convention. * Implement liveliness support (#632) * Mark liveliness API as unstable and disable by default * Fix typo (#787) * fix: correct 1.1 issues * feat: add zp_batch_flush * fix: switch to #if 0 to deactivate tcp function --------- Co-authored-by: Alexander Bushnev Co-authored-by: DenisBiryukov91 <155981813+DenisBiryukov91@users.noreply.github.com> Co-authored-by: Denis Biryukov Co-authored-by: Diogo Mendes Matsubara Co-authored-by: Luca Cominardi --- CMakeLists.txt | 8 +++++++- docs/api.rst | 2 +- include/zenoh-pico/api/liveliness.h | 2 +- include/zenoh-pico/api/primitives.h | 19 +++++++++++++++---- include/zenoh-pico/config.h | 6 +++--- include/zenoh-pico/net/primitives.h | 4 ---- src/api/api.c | 9 +++++++++ src/transport/multicast/rx.c | 2 -- src/transport/unicast/rx.c | 2 -- src/transport/unicast/transport.c | 12 ++++++++++++ 10 files changed, 48 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7920bdc68..ba8f552b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,7 +216,7 @@ set(Z_FEATURE_PUBLICATION 1 CACHE STRING "Toggle publication feature") set(Z_FEATURE_SUBSCRIPTION 1 CACHE STRING "Toggle subscription feature") set(Z_FEATURE_QUERY 1 CACHE STRING "Toggle query feature") set(Z_FEATURE_QUERYABLE 1 CACHE STRING "Toggle queryable feature") -set(Z_FEATURE_LIVELINESS 1 CACHE STRING "Toggle liveliness feature") +set(Z_FEATURE_LIVELINESS 0 CACHE STRING "Toggle liveliness feature") set(Z_FEATURE_INTEREST 1 CACHE STRING "Toggle interests") set(Z_FEATURE_FRAGMENTATION 1 CACHE STRING "Toggle fragmentation") set(Z_FEATURE_ENCODING_VALUES 1 CACHE STRING "Toggle encoding values") @@ -239,6 +239,12 @@ set(Z_FEATURE_PUBLISHER_SESSION_CHECK 1 CACHE STRING "Toggle publisher session c set(Z_FEATURE_BATCHING 1 CACHE STRING "Toggle batching") set(Z_FEATURE_RX_CACHE 0 CACHE STRING "Toggle RX_CACHE") +# Add a warning message if someone tries to enable Z_FEATURE_LIVELINESS directly +if(Z_FEATURE_LIVELINESS AND NOT Z_FEATURE_UNSTABLE_API) + message(WARNING "Z_FEATURE_LIVELINESS can only be enabled when Z_FEATURE_UNSTABLE_API is also enabled. Disabling Z_FEATURE_LIVELINESS.") + set(Z_FEATURE_LIVELINESS 0 CACHE STRING "Toggle liveliness feature" FORCE) +endif() + add_compile_definitions("Z_BUILD_DEBUG=$") message(STATUS "Building with feature confing:\n\ * UNSTABLE_API: ${Z_FEATURE_UNSTABLE_API}\n\ diff --git a/docs/api.rst b/docs/api.rst index 7271209eb..1a3893a0b 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1289,7 +1289,7 @@ See details at :ref:`owned_types_concept` Functions --------- -.. autocfunction:: liveliness.h::z_liveliness_token_options_t_default +.. autocfunction:: liveliness.h::z_liveliness_token_options_default .. autocfunction:: liveliness.h::z_liveliness_declare_token .. autocfunction:: liveliness.h::z_liveliness_undeclare_token .. autocfunction:: liveliness.h::z_liveliness_subscriber_options_default diff --git a/include/zenoh-pico/api/liveliness.h b/include/zenoh-pico/api/liveliness.h index 43e3012fc..d3751bc4f 100644 --- a/include/zenoh-pico/api/liveliness.h +++ b/include/zenoh-pico/api/liveliness.h @@ -48,7 +48,7 @@ typedef struct z_liveliness_token_options_t { /** * Constructs default value for :c:type:`z_liveliness_token_options_t`. */ -z_result_t z_liveliness_token_options_t_default(z_liveliness_token_options_t *options); +z_result_t z_liveliness_token_options_default(z_liveliness_token_options_t *options); /** * Constructs and declares a liveliness token on the network. diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index b28f3ec6c..3da9ab8f0 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -2063,9 +2063,9 @@ const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *subs #ifdef Z_FEATURE_UNSTABLE_API #if Z_FEATURE_BATCHING == 1 /** - * Activate the batching mechanism. - * Any message that would have been sent on the network by a subsequent api call (e.g z_put, z_get) - * will be instead stored until the batch is full or batching is stopped with :c:func:`zp_batch_stop`. + * Activate the batching mechanism, any message that would have been sent on the network by a subsequent api call (e.g + * z_put, z_get) will be instead stored until the batch is full, flushed with :c:func:`zp_batch_flush` or batching is + * stopped with :c:func:`zp_batch_stop`. * * Parameters: * zs: Pointer to a :c:type:`z_loaned_session_t` that will start batching messages. @@ -2076,7 +2076,18 @@ const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *subs z_result_t zp_batch_start(const z_loaned_session_t *zs); /** - * Deactivate the batching mechanism and flush the remaining messages. + * Send the currently batched messages on the network. + * + * Parameters: + * zs: Pointer to a :c:type:`z_loaned_session_t` that will send its batched messages. + * + * Return: + * ``0`` if batch successfully sent, ``negative value`` otherwise. + */ +z_result_t zp_batch_flush(const z_loaned_session_t *zs); + +/** + * Deactivate the batching mechanism and send the currently batched on the network. * * Parameters: * zs: Pointer to a :c:type:`z_loaned_session_t` that will stop batching messages. diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index 4e4ae9f99..840dff4ee 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -27,7 +27,7 @@ #define Z_FEATURE_SUBSCRIPTION 1 #define Z_FEATURE_QUERY 1 #define Z_FEATURE_QUERYABLE 1 -#define Z_FEATURE_LIVELINESS 1 +#define Z_FEATURE_LIVELINESS 0 #define Z_FEATURE_RAWETH_TRANSPORT 0 #define Z_FEATURE_INTEREST 1 #define Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION 0 @@ -44,9 +44,9 @@ #define Z_FEATURE_ENCODING_VALUES 1 #define Z_FEATURE_TCP_NODELAY 1 #define Z_FEATURE_LOCAL_SUBSCRIBER 0 -#define Z_FEATURE_PUBLISHER_SESSION_CHECK 0 +#define Z_FEATURE_PUBLISHER_SESSION_CHECK 1 #define Z_FEATURE_BATCHING 1 -#define Z_FEATURE_RX_CACHE 1 +#define Z_FEATURE_RX_CACHE 0 // End of CMake generation /*------------------ Runtime configuration properties ------------------*/ diff --git a/include/zenoh-pico/net/primitives.h b/include/zenoh-pico/net/primitives.h index 53db370e1..b53a8f4e4 100644 --- a/include/zenoh-pico/net/primitives.h +++ b/include/zenoh-pico/net/primitives.h @@ -29,10 +29,6 @@ extern "C" { #endif -#ifdef __cplusplus -extern "C" { -#endif - /*------------------ Discovery ------------------*/ /** diff --git a/src/api/api.c b/src/api/api.c index 40f3e5ed3..c4b827209 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -1432,6 +1432,15 @@ z_result_t zp_batch_start(const z_loaned_session_t *zs) { return _z_transport_start_batching(&session->_tp) ? _Z_RES_OK : _Z_ERR_GENERIC; } +z_result_t zp_batch_flush(const z_loaned_session_t *zs) { + _z_session_t *session = _Z_RC_IN_VAL(zs); + if (_Z_RC_IS_NULL(zs)) { + return _Z_ERR_SESSION_CLOSED; + } + // Send current batch + return _z_send_n_batch(session, Z_CONGESTION_CONTROL_DEFAULT); +} + z_result_t zp_batch_stop(const z_loaned_session_t *zs) { _z_session_t *session = _Z_RC_IN_VAL(zs); if (_Z_RC_IS_NULL(zs)) { diff --git a/src/transport/multicast/rx.c b/src/transport/multicast/rx.c index 1ab13f161..dc64460e4 100644 --- a/src/transport/multicast/rx.c +++ b/src/transport/multicast/rx.c @@ -252,8 +252,6 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _Z_INFO("Failed to decode defragmented message"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - // Fragmented messages must be cleared. Non-fragmented messages are released with their transport. - _z_msg_clear(&zm); // Free the decoding buffer _z_zbuf_clear(&zbf); *dbuf_state = _Z_DBUF_STATE_NULL; diff --git a/src/transport/unicast/rx.c b/src/transport/unicast/rx.c index 628f2815d..d90b59f38 100644 --- a/src/transport/unicast/rx.c +++ b/src/transport/unicast/rx.c @@ -204,8 +204,6 @@ z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_t _Z_INFO("Failed to decode defragmented message"); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - // Fragmented messages must be cleared. Non-fragmented messages are released with their transport. - _z_msg_clear(&zm); // Free the decoding buffer _z_zbuf_clear(&zbf); *dbuf_state = _Z_DBUF_STATE_NULL; diff --git a/src/transport/unicast/transport.c b/src/transport/unicast/transport.c index 9ae20a38c..64a1d6540 100644 --- a/src/transport/unicast/transport.c +++ b/src/transport/unicast/transport.c @@ -217,6 +217,8 @@ static z_result_t _z_unicast_handshake_client(_z_transport_unicast_establish_par return _Z_RES_OK; } +// TODO: Activate if we add peer unicast support +#if 0 static z_result_t _z_unicast_handshake_listener(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, const _z_id_t *local_zid, enum z_whatami_t whatami) { // Read t message from link @@ -293,6 +295,16 @@ static z_result_t _z_unicast_handshake_listener(_z_transport_unicast_establish_p // Handshake finished return _Z_RES_OK; } +#else +static z_result_t _z_unicast_handshake_listener(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, + const _z_id_t *local_zid, enum z_whatami_t whatami) { + _ZP_UNUSED(param); + _ZP_UNUSED(zl); + _ZP_UNUSED(local_zid); + _ZP_UNUSED(whatami); + return _Z_ERR_TRANSPORT_OPEN_FAILED; +} +#endif z_result_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, const _z_id_t *local_zid) { From 5071eda91f99d0b8b8b3443b093e86d4ce379a90 Mon Sep 17 00:00:00 2001 From: Jean-Roland Date: Tue, 19 Nov 2024 21:14:36 +0100 Subject: [PATCH 15/17] fix: prevent code duplication during merge --- CMakeLists.txt | 6 ------ include/zenoh-pico/collections/element.h | 4 ---- include/zenoh-pico/net/publish.h | 4 ---- include/zenoh-pico/net/query.h | 4 ---- include/zenoh-pico/net/subscribe.h | 4 ---- include/zenoh-pico/protocol/codec/network.h | 4 ---- include/zenoh-pico/protocol/definitions/network.h | 4 ---- include/zenoh-pico/session/utils.h | 4 ---- include/zenoh-pico/transport/common/tx.h | 4 ---- include/zenoh-pico/transport/multicast/rx.h | 4 ---- include/zenoh-pico/transport/raweth/rx.h | 4 ---- include/zenoh-pico/transport/raweth/tx.h | 4 ---- include/zenoh-pico/transport/unicast/rx.h | 4 ---- src/protocol/keyexpr.c | 8 -------- 14 files changed, 62 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba8f552b1..05c7a35ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -239,12 +239,6 @@ set(Z_FEATURE_PUBLISHER_SESSION_CHECK 1 CACHE STRING "Toggle publisher session c set(Z_FEATURE_BATCHING 1 CACHE STRING "Toggle batching") set(Z_FEATURE_RX_CACHE 0 CACHE STRING "Toggle RX_CACHE") -# Add a warning message if someone tries to enable Z_FEATURE_LIVELINESS directly -if(Z_FEATURE_LIVELINESS AND NOT Z_FEATURE_UNSTABLE_API) - message(WARNING "Z_FEATURE_LIVELINESS can only be enabled when Z_FEATURE_UNSTABLE_API is also enabled. Disabling Z_FEATURE_LIVELINESS.") - set(Z_FEATURE_LIVELINESS 0 CACHE STRING "Toggle liveliness feature" FORCE) -endif() - add_compile_definitions("Z_BUILD_DEBUG=$") message(STATUS "Building with feature confing:\n\ * UNSTABLE_API: ${Z_FEATURE_UNSTABLE_API}\n\ diff --git a/include/zenoh-pico/collections/element.h b/include/zenoh-pico/collections/element.h index 5657a63b9..e6a167498 100644 --- a/include/zenoh-pico/collections/element.h +++ b/include/zenoh-pico/collections/element.h @@ -79,8 +79,4 @@ static inline void _z_noop_move(void *dst, void *src) { _Z_ELEM_DEFINE(_z_noop, _z_noop_t, _z_noop_size, _z_noop_clear, _z_noop_copy, _z_noop_move) -#ifdef __cplusplus -} -#endif - #endif /* ZENOH_PICO_COLLECTIONS_ELEMENT_H */ diff --git a/include/zenoh-pico/net/publish.h b/include/zenoh-pico/net/publish.h index b270f4eb3..e54381de4 100644 --- a/include/zenoh-pico/net/publish.h +++ b/include/zenoh-pico/net/publish.h @@ -48,8 +48,4 @@ void _z_publisher_clear(_z_publisher_t *pub); void _z_publisher_free(_z_publisher_t **pub); #endif -#ifdef __cplusplus -} -#endif - #endif /* INCLUDE_ZENOH_PICO_NET_PUBLISH_H */ diff --git a/include/zenoh-pico/net/query.h b/include/zenoh-pico/net/query.h index 433fc1217..676a1c41b 100644 --- a/include/zenoh-pico/net/query.h +++ b/include/zenoh-pico/net/query.h @@ -79,8 +79,4 @@ void _z_queryable_free(_z_queryable_t **qbl); #endif -#ifdef __cplusplus -} -#endif - #endif /* ZENOH_PICO_QUERY_NETAPI_H */ diff --git a/include/zenoh-pico/net/subscribe.h b/include/zenoh-pico/net/subscribe.h index 2357a0c8a..b9d6d8da7 100644 --- a/include/zenoh-pico/net/subscribe.h +++ b/include/zenoh-pico/net/subscribe.h @@ -41,8 +41,4 @@ void _z_subscriber_free(_z_subscriber_t **sub); #endif -#ifdef __cplusplus -} -#endif - #endif /* ZENOH_PICO_SUBSCRIBE_NETAPI_H */ diff --git a/include/zenoh-pico/protocol/codec/network.h b/include/zenoh-pico/protocol/codec/network.h index 661ee9de2..4aca08740 100644 --- a/include/zenoh-pico/protocol/codec/network.h +++ b/include/zenoh-pico/protocol/codec/network.h @@ -40,8 +40,4 @@ z_result_t _z_n_interest_decode(_z_n_msg_interest_t *interest, _z_zbuf_t *zbf, u z_result_t _z_network_message_encode(_z_wbuf_t *wbf, const _z_network_message_t *msg); z_result_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf, _z_arc_slice_t *arcs); -#ifdef __cplusplus -} -#endif - #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_NETWORK_H */ diff --git a/include/zenoh-pico/protocol/definitions/network.h b/include/zenoh-pico/protocol/definitions/network.h index f828d48f1..610ba7fb3 100644 --- a/include/zenoh-pico/protocol/definitions/network.h +++ b/include/zenoh-pico/protocol/definitions/network.h @@ -309,8 +309,4 @@ _z_network_message_t _z_n_msg_make_push(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_pu _z_network_message_t _z_n_msg_make_interest(_z_interest_t interest); z_result_t _z_n_msg_copy(_z_network_message_t *dst, const _z_network_message_t *src); -#ifdef __cplusplus -} -#endif - #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_NETWORK_H */ diff --git a/include/zenoh-pico/session/utils.h b/include/zenoh-pico/session/utils.h index 44c48ff91..7b1d3d7af 100644 --- a/include/zenoh-pico/session/utils.h +++ b/include/zenoh-pico/session/utils.h @@ -44,8 +44,4 @@ static inline void _z_session_mutex_lock(_z_session_t *zn) { _ZP_UNUSED(zn); } static inline void _z_session_mutex_unlock(_z_session_t *zn) { _ZP_UNUSED(zn); } #endif -#ifdef __cplusplus -} -#endif - #endif /* INCLUDE_ZENOH_PICO_SESSION_UTILS_H */ diff --git a/include/zenoh-pico/transport/common/tx.h b/include/zenoh-pico/transport/common/tx.h index 6809f20f3..1b8d85d7f 100644 --- a/include/zenoh-pico/transport/common/tx.h +++ b/include/zenoh-pico/transport/common/tx.h @@ -37,8 +37,4 @@ z_result_t _z_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_ z_congestion_control_t cong_ctrl); z_result_t _z_send_n_batch(_z_session_t *zn, z_congestion_control_t cong_ctrl); -#ifdef __cplusplus -} -#endif - #endif /* ZENOH_PICO_TRANSPORT_TX_H */ diff --git a/include/zenoh-pico/transport/multicast/rx.h b/include/zenoh-pico/transport/multicast/rx.h index f7a81e00a..83bf77eaf 100644 --- a/include/zenoh-pico/transport/multicast/rx.h +++ b/include/zenoh-pico/transport/multicast/rx.h @@ -26,8 +26,4 @@ z_result_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_slice_t *addr); z_result_t _z_multicast_update_rx_buffer(_z_transport_multicast_t *ztm); -#ifdef __cplusplus -} -#endif - #endif /* ZENOH_PICO_TRANSPORT_LINK_RX_H */ diff --git a/include/zenoh-pico/transport/raweth/rx.h b/include/zenoh-pico/transport/raweth/rx.h index 19901b68f..de4f0558b 100644 --- a/include/zenoh-pico/transport/raweth/rx.h +++ b/include/zenoh-pico/transport/raweth/rx.h @@ -25,8 +25,4 @@ z_result_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_mess z_result_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); z_result_t _z_raweth_update_rx_buff(_z_transport_multicast_t *ztm); -#ifdef __cplusplus -} -#endif - #endif /* ZENOH_PICO_RAWETH_RX_H */ diff --git a/include/zenoh-pico/transport/raweth/tx.h b/include/zenoh-pico/transport/raweth/tx.h index a338c16f3..109367206 100644 --- a/include/zenoh-pico/transport/raweth/tx.h +++ b/include/zenoh-pico/transport/raweth/tx.h @@ -27,8 +27,4 @@ z_result_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_ z_congestion_control_t cong_ctrl); z_result_t _z_raweth_send_t_msg(_z_transport_common_t *ztc, const _z_transport_message_t *t_msg); -#ifdef __cplusplus -} -#endif - #endif /* ZENOH_PICO_RAWETH_TX_H */ diff --git a/include/zenoh-pico/transport/unicast/rx.h b/include/zenoh-pico/transport/unicast/rx.h index 8052ebd88..7f7e036f8 100644 --- a/include/zenoh-pico/transport/unicast/rx.h +++ b/include/zenoh-pico/transport/unicast/rx.h @@ -26,8 +26,4 @@ z_result_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_me z_result_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg); z_result_t _z_unicast_update_rx_buffer(_z_transport_unicast_t *ztu); -#ifdef __cplusplus -} -#endif - #endif /* ZENOH_PICO_UNICAST_RX_H */ diff --git a/src/protocol/keyexpr.c b/src/protocol/keyexpr.c index 4ce2ab919..b27655dd8 100644 --- a/src/protocol/keyexpr.c +++ b/src/protocol/keyexpr.c @@ -70,14 +70,6 @@ _z_keyexpr_t _z_keyexpr_duplicate(const _z_keyexpr_t *src) { return dst; } -_z_keyexpr_t *_z_keyexpr_clone(const _z_keyexpr_t *src) { - _z_keyexpr_t *dst = z_malloc(sizeof(_z_keyexpr_t)); - if (dst != NULL) { - _z_keyexpr_copy(dst, src); - } - return dst; -} - _z_keyexpr_t _z_keyexpr_steal(_Z_MOVE(_z_keyexpr_t) src) { _z_keyexpr_t stolen = *src; *src = _z_keyexpr_null(); From 11d2edf81b80ebe222305ad86259ef8d7a5a35c5 Mon Sep 17 00:00:00 2001 From: Jean-Roland Gosse Date: Wed, 20 Nov 2024 08:06:23 +0100 Subject: [PATCH 16/17] Merge main in 1.1 (#793) * Update closure handlers documentaion (#736) * Rename closure callback/dropper types (#739) * Remove legacy z_zint_t from public API (#741) * Add `export "C"` for all header files (#740) * Add `export "C"` for proper closures callbacks export * Add `export "C"` for all headers * add serialize from substr functions (#742) * Rename z_loaned_hello_handler_t to z_closure_hello_callback_t (#743) * Mark z_reply_replier_id as unstable (#745) * Add documentation about logging (#744) * Update README.md (#746) * hardcode clang-format runner to Ubuntu24.04 (#748) * fix build granularity (#747) * fix: badly named constant (#750) * fix packages * fix: update debian packaging - include libzenohpico.so in debian package - change the package name to libzenohpico in line with libzenohc - set correct debian version for pre releases - fix wrong version used in Release mode * fix: debian dev package name * fix: package version for releases (#753) * fix: debian_version for official releases otherwise they would be undefined * fix: align cpack version with zenoh-c * chore: review comments move cpack version closer to where it's used * build shared lib for packages instead of static one (#757) * Fix z_task cleanup for platforms with pthread support (#759) * Fix read/lease task cleanup (#760) * Align ID string representation with zenoh (lowercase) (#761) * Remove default parameters from z_closure (#755) * build both libraries:shared and static when packaging; (#766) add static library to dev package; * Publish debian packages (#769) * fix: add workflow to release debian packages * fix: align with zenoh-c - update package names - set version string in the same way - set DEBARCH/RPMARCH - set CPACK_PACKAGE_FILE_NAME - add -j to zip archive to not include parent folder * fix: use CPACK_PACKAGE_NAME * fix: pass package name to all build targets * fix: Don't tag release branch during dry-run * Replace exit with return in zephyr examples (#774) * Add platform_common.c to zephyr CMakeLists.txt file * Rework Zenoh ID conversion * chore: Update org secrets (#782) As per eclipse-zenoh/.eclipsefdn#18, secrets were updated to follow eclipse foundation naming convention. * Implement liveliness support (#632) * Mark liveliness API as unstable and disable by default * Fix typo (#787) * fix: prevent code duplication during merge --------- Co-authored-by: Alexander Bushnev Co-authored-by: DenisBiryukov91 <155981813+DenisBiryukov91@users.noreply.github.com> Co-authored-by: Denis Biryukov Co-authored-by: Diogo Mendes Matsubara Co-authored-by: Luca Cominardi --- zenohpico.pc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zenohpico.pc b/zenohpico.pc index 3922083d4..1e3b39ae2 100644 --- a/zenohpico.pc +++ b/zenohpico.pc @@ -3,6 +3,6 @@ prefix=/usr/local Name: zenohpico Description: URL: -Version: 1.0.20241115dev +Version: 1.0.20241018dev Cflags: -I${prefix}/include Libs: -L${prefix}/lib -lzenohpico From 9e35c5f6c764f953e7b59b70531a7bbdcb985300 Mon Sep 17 00:00:00 2001 From: Alexander Bushnev Date: Wed, 20 Nov 2024 14:28:56 +0100 Subject: [PATCH 17/17] Fix merge issue --- src/api/liveliness.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/liveliness.c b/src/api/liveliness.c index a9403361f..bcf477e9c 100644 --- a/src/api/liveliness.c +++ b/src/api/liveliness.c @@ -48,7 +48,7 @@ void _z_liveliness_token_clear(_z_liveliness_token_t *token) { _Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL(_z_liveliness_token_t, liveliness_token, _z_liveliness_token_check, _z_liveliness_token_null, _z_liveliness_token_clear) -z_result_t z_liveliness_token_options_t_default(z_liveliness_token_options_t *options) { +z_result_t z_liveliness_token_options_default(z_liveliness_token_options_t *options) { options->__dummy = 0; return _Z_RES_OK; }