diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d185aad..3506cb9d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,9 @@ option(UCLIENT_PROFILE_MATCHING "Enable QoS matching support." OFF) set(UCLIENT_SHARED_MEMORY_MAX_ENTITIES 4 CACHE STRING "Max number of entities involved in shared memory.") set(UCLIENT_SHARED_MEMORY_STATIC_MEM_SIZE 10 CACHE STRING "Max number data buffers stored in shared memory") +option(UCLIENT_HARD_LIVELINESS_CHECK "Enable hard liveliness check." OFF) +set(UCLIENT_HARD_LIVELINESS_CHECK_TIMEOUT 10000 CACHE STRING "Set the hard liveliness check interval in milliseconds.") + # Off-standard features and tweaks option(UCLIENT_TWEAK_XRCE_WRITE_LIMIT "This feature uses a tweak to allow XRCE WRITE DATA submessages grater than 64 kB." ON) @@ -87,7 +90,7 @@ list(APPEND _deps "microcdr\;${_microcdr_version}") ############################################################################### set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) if(NOT UCLIENT_SUPERBUILD) - project(microxrcedds_client VERSION "2.1.1" LANGUAGES C) + project(microxrcedds_client VERSION "2.2.0" LANGUAGES C) else() project(uclient_superbuild NONE) include(${PROJECT_SOURCE_DIR}/cmake/SuperBuild.cmake) @@ -181,6 +184,8 @@ if(UCLIENT_PROFILE_TCP) list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport.c) if(UCLIENT_PLATFORM_POSIX) list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport_posix.c) + elseif(UCLIENT_PLATFORM_POSIX_NOPOLL) + list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport_posix_nopoll.c) elseif(UCLIENT_PLATFORM_WINDOWS) list(APPEND _transport_src src/c/profile/transport/ip/tcp/tcp_transport_windows.c) elseif(UCLIENT_PLATFORM_FREERTOS_PLUS_TCP) diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index 44f839a0..2001d4f4 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -44,6 +44,9 @@ if(NOT microcdr_FOUND) -DCMAKE_INSTALL_PREFIX= -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_SYSROOT:PATH=${CMAKE_SYSROOT} + -DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS} + -DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS} + -DCMAKE_EXE_LINKER_FLAGS:STRING=${CMAKE_EXE_LINKER_FLAGS} -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} -DCONFIG_BIG_ENDIANNESS=${UCLIENT_BIG_ENDIANNESS} -DUCDR_PIC=${UCLIENT_PIC} diff --git a/cmake/common/check_configuration.cmake b/cmake/common/check_configuration.cmake index e0e3379c..03f27858 100644 --- a/cmake/common/check_configuration.cmake +++ b/cmake/common/check_configuration.cmake @@ -120,15 +120,11 @@ function(set_common_compile_options target) target_compile_options(${target} PRIVATE -Wall -Wextra -Wshadow - $<$:-Wnon-virtual-dtor> -pedantic -Wcast-align -Wunused - $<$:-Woverloaded-virtual> -Wconversion $<$:-Wlogical-op> - $<$,$>:-Wuseless-cast> - $<$:-Wold-style-cast> $<$,$,6.0.0>>>,$,$,6.0.0>>>>:-Wnull-dereference> $<$,$,7.0.0>>>,$,$,7.0.0>>>>:-Wduplicated-branches> $<$,$,6.0.0>>>,$,$,6.0.0>>>>:-Wduplicated-cond> diff --git a/include/uxr/client/config.h.in b/include/uxr/client/config.h.in index e44a674e..55a62692 100644 --- a/include/uxr/client/config.h.in +++ b/include/uxr/client/config.h.in @@ -67,5 +67,18 @@ #cmakedefine UCLIENT_TWEAK_XRCE_WRITE_LIMIT +#cmakedefine UCLIENT_HARD_LIVELINESS_CHECK + +#ifdef UCLIENT_HARD_LIVELINESS_CHECK +#define UXR_CONFIG_HARD_LIVELINESS_CHECK_TIMEOUT_STR "@UCLIENT_HARD_LIVELINESS_CHECK_TIMEOUT@" +#endif + + +// Version checks +#if UXR_CLIENT_VERSION_MAJOR >= 3 +#error UCLIENT_HARD_LIVELINESS_CHECK shall be included in session API +#error MTU must be included in CREATE_CLIENT_Payload properties +#error Reorder ObjectInfo https://github.com/eProsima/Micro-XRCE-DDS/issues/137 +#endif #endif // _UXR_CLIENT_CONFIG_H_ diff --git a/include/uxr/client/core/type/xrce_types.h b/include/uxr/client/core/type/xrce_types.h index cc9fe0c6..f733245e 100644 --- a/include/uxr/client/core/type/xrce_types.h +++ b/include/uxr/client/core/type/xrce_types.h @@ -24,6 +24,7 @@ extern "C" #endif // ifdef __cplusplus #include +#include #include #include @@ -40,7 +41,24 @@ extern "C" #define UXR_SAMPLE_DELTA_SEQUENCE_MAX 8 #define UXR_PACKED_SAMPLES_SEQUENCE_MAX 8 #define UXR_TRANSPORT_LOCATOR_SEQUENCE_MAX 4 + +#ifdef UCLIENT_PROFILE_SHARED_MEMORY +#define PROFILE_SHARED_MEMORY_SEQ_COUNT 1 +#else +#define PROFILE_SHARED_MEMORY_SEQ_COUNT 0 +#endif // ifdef UCLIENT_PROFILE_SHARED_MEMORY + +#ifdef UCLIENT_HARD_LIVELINESS_CHECK +#define HARD_LIVELINESS_CHECK_SEQ_COUNT 1 +#else +#define HARD_LIVELINESS_CHECK_SEQ_COUNT 0 +#endif // ifdef UCLIENT_HARD_LIVELINESS_CHECK + +#if (PROFILE_SHARED_MEMORY_SEQ_COUNT + HARD_LIVELINESS_CHECK_SEQ_COUNT) == 0 #define UXR_PROPERTY_SEQUENCE_MAX 1 +#else +#define UXR_PROPERTY_SEQUENCE_MAX PROFILE_SHARED_MEMORY_SEQ_COUNT + HARD_LIVELINESS_CHECK_SEQ_COUNT +#endif // if (PROFILE_SHARED_MEMORY_SEQ_COUNT + HARD_LIVELINESS_CHECK_SEQ_COUNT) == 0 typedef struct Time_t { diff --git a/include/uxr/client/profile/transport/ip/tcp/tcp_transport_posix_nopoll.h b/include/uxr/client/profile/transport/ip/tcp/tcp_transport_posix_nopoll.h new file mode 100644 index 00000000..892433ee --- /dev/null +++ b/include/uxr/client/profile/transport/ip/tcp/tcp_transport_posix_nopoll.h @@ -0,0 +1,32 @@ +// Copyright 2018 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef UXR_CLIENT_PROFILE_TRANSPORT_IP_TCP_TCPTRANSPORTPOSIXNOPOLL_H_ +#define UXR_CLIENT_PROFILE_TRANSPORT_IP_TCP_TCPTRANSPORTPOSIXNOPOLL_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif // ifdef __cplusplus + +typedef struct uxrTCPPlatform +{ + int fd; +} uxrTCPPlatform; + +#ifdef __cplusplus +} +#endif // ifdef __cplusplus + +#endif // UXR_CLIENT_PROFILE_TRANSPORT_IP_TCP_TCPTRANSPORTPOSIXNOPOLL_H_ \ No newline at end of file diff --git a/include/uxr/client/transport.h b/include/uxr/client/transport.h index e235f5b4..99f4b8c1 100644 --- a/include/uxr/client/transport.h +++ b/include/uxr/client/transport.h @@ -33,7 +33,9 @@ #endif //UCLIENT_PROFILE_UDP #ifdef UCLIENT_PROFILE_TCP -#if defined(UCLIENT_PLATFORM_POSIX) +#if defined(UCLIENT_PLATFORM_POSIX_NOPOLL) +#include +#elif defined(UCLIENT_PLATFORM_POSIX) #include #elif defined(UCLIENT_PLATFORM_WINDOWS) #include diff --git a/include/uxr/client/util/ping.h b/include/uxr/client/util/ping.h index a1589528..20ba934a 100644 --- a/include/uxr/client/util/ping.h +++ b/include/uxr/client/util/ping.h @@ -33,7 +33,7 @@ extern "C" #define UXR_PING_BUF 16 // 4 (HEADER SIZE) + 4 (SUBHEADER_SIZE) + 8 (GET_Info payload) #define GET_INFO_MSG_SIZE 8 -#define GET_INFO_REQUEST_ID 9 +#define GET_INFO_REQUEST_PING_ID 10 struct uxrSession; diff --git a/src/c/core/session/session.c b/src/c/core/session/session.c index 6c26c6d8..d0a37ef0 100644 --- a/src/c/core/session/session.c +++ b/src/c/core/session/session.c @@ -21,13 +21,23 @@ #include "../../profile/shared_memory/shared_memory_internal.h" #ifdef UCLIENT_PROFILE_SHARED_MEMORY -#define CREATE_SESSION_PROPERTIES_MAX_SIZE 21 -#define CREATE_SESSION_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + CREATE_CLIENT_PAYLOAD_SIZE + \ - CREATE_SESSION_PROPERTIES_MAX_SIZE) +#define PROFILE_SHARED_MEMORY_ADD_SIZE 21 #else -#define CREATE_SESSION_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + CREATE_CLIENT_PAYLOAD_SIZE) +#define PROFILE_SHARED_MEMORY_ADD_SIZE 0 #endif /* ifdef UCLIENT_PROFILE_SHARED_MEMORY */ +#ifdef UCLIENT_HARD_LIVELINESS_CHECK +#define HARD_LIVELINESS_CHECK_ADD_SIZE 26 +#else +#define HARD_LIVELINESS_CHECK_ADD_SIZE 0 +#endif /* ifdef UCLIENT_HARD_LIVELINESS_CHECK */ + +#define CREATE_SESSION_PROPERTIES_MAX_SIZE PROFILE_SHARED_MEMORY_ADD_SIZE + HARD_LIVELINESS_CHECK_ADD_SIZE + + +#define CREATE_SESSION_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + CREATE_CLIENT_PAYLOAD_SIZE + \ + CREATE_SESSION_PROPERTIES_MAX_SIZE) + #define DELETE_SESSION_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + DELETE_CLIENT_PAYLOAD_SIZE) #define HEARTBEAT_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + HEARTBEAT_PAYLOAD_SIZE) #define ACKNACK_MAX_MSG_SIZE (MAX_HEADER_SIZE + SUBHEADER_SIZE + ACKNACK_PAYLOAD_SIZE) @@ -102,6 +112,12 @@ static void read_submessage_acknack( static void read_submessage_timestamp_reply( uxrSession* session, ucdrBuffer* submessage); +static void read_submessage_get_info( + uxrSession* session, + ucdrBuffer* submessage); +void read_submessage_info( + uxrSession* session, + ucdrBuffer* submessage); #ifdef PERFORMANCE_TESTING static void read_submessage_performance( uxrSession* session, @@ -125,9 +141,6 @@ static bool run_session_until_sync( uxrSession* session, int timeout); -pong_status_t uxr_acknack_pong( - ucdrBuffer* buffer); - //================================================================== // PUBLIC //================================================================== @@ -626,52 +639,6 @@ void uxr_flash_output_streams( //================================================================== // PRIVATE //================================================================== -pong_status_t uxr_acknack_pong( - ucdrBuffer* buffer) -{ - bool success = false; - bool ret = false; - bool active_session = false; - - if (ucdr_buffer_remaining(buffer) > SUBHEADER_SIZE) - { - uint8_t id = 0; - uint8_t flags = 0; - uint16_t length = 0; - uxr_deserialize_submessage_header(buffer, &id, &flags, &length); - success = ucdr_buffer_remaining(buffer) >= length; - - if (success && id == SUBMESSAGE_ID_INFO) - { - INFO_Payload info_payload; - - success &= uxr_deserialize_BaseObjectReply(buffer, &info_payload.base); - active_session = info_payload.base.result.implementation_status; - - success &= ucdr_deserialize_bool(buffer, &info_payload.object_info.optional_config); - - if (info_payload.object_info.optional_config) - { - success &= uxr_deserialize_ObjectVariant(buffer, &info_payload.object_info.config); - } - - success &= ucdr_deserialize_bool(buffer, &info_payload.object_info.optional_activity); - if (info_payload.object_info.optional_activity) - { - success &= ucdr_deserialize_uint8_t(buffer, &info_payload.object_info.activity.kind); - if (success && DDS_XRCE_OBJK_AGENT == info_payload.object_info.activity.kind) - { - success &= ucdr_deserialize_int16_t(buffer, - &info_payload.object_info.activity._.agent.availability); - ret = success && (info_payload.object_info.activity._.agent.availability > 0); - } - } - } - } - - return ret ? (active_session ? PONG_IN_SESSION_STATUS : PONG_NO_SESSION_STATUS) : NO_PONG_STATUS; -} - bool uxr_run_session_until_pong( uxrSession* session, int timeout_ms) @@ -781,7 +748,15 @@ bool wait_session_status( for (size_t i = 0; i < attempts && session->info.last_requested_status == UXR_STATUS_NONE; ++i) { send_message(session, buffer, length); - listen_message(session, UXR_CONFIG_MIN_SESSION_CONNECTION_INTERVAL); + + int64_t start_timestamp = uxr_millis(); + int remaining_time = UXR_CONFIG_MIN_SESSION_CONNECTION_INTERVAL; + + do + { + listen_message(session, remaining_time); + remaining_time = UXR_CONFIG_MIN_SESSION_CONNECTION_INTERVAL - (int)(uxr_millis() - start_timestamp); + } while (remaining_time > 0 && session->info.last_requested_status == UXR_STATUS_NONE); } return session->info.last_requested_status != UXR_STATUS_NONE; @@ -877,10 +852,6 @@ void read_message( uxrStreamId id = uxr_stream_id_from_raw(stream_id_raw, UXR_INPUT_STREAM); read_stream(session, ub, id, seq_num); } - else - { - session->on_pong_flag = uxr_acknack_pong(ub); - } } void read_stream( @@ -989,6 +960,14 @@ void read_submessage( read_submessage_timestamp_reply(session, submessage); break; + case SUBMESSAGE_ID_GET_INFO: + read_submessage_get_info(session, submessage); + break; + + case SUBMESSAGE_ID_INFO: + read_submessage_info(session, submessage); + break; + #ifdef PERFORMANCE_TESTING case SUBMESSAGE_ID_PERFORMANCE: read_submessage_performance(session, submessage, length); @@ -1095,6 +1074,66 @@ void read_submessage_timestamp_reply( process_timestamp_reply(session, ×tamp_reply); } +void read_submessage_get_info( + uxrSession* session, + ucdrBuffer* submessage) +{ + GET_INFO_Payload get_info_payload = { + 0 + }; + INFO_Payload info_payload = { + 0 + }; + + uxr_deserialize_GET_INFO_Payload(submessage, &get_info_payload); + + info_payload.base.related_request.request_id = get_info_payload.base.request_id; + + uint8_t buffer[12]; + ucdrBuffer ub; + ucdr_init_buffer_origin_offset(&ub, buffer, sizeof(buffer), 0u, uxr_session_header_offset(&session->info)); + + uxr_serialize_INFO_Payload(&ub, &info_payload); + uxr_stamp_session_header(&session->info, 0, 0, ub.init); + + send_message(session, buffer, ucdr_buffer_length(&ub)); +} + +void read_submessage_info( + uxrSession* session, + ucdrBuffer* submessage) +{ + INFO_Payload info_payload; + + bool success = true; + + success &= uxr_deserialize_BaseObjectReply(submessage, &info_payload.base); + bool active_session = info_payload.base.result.implementation_status; + + success &= ucdr_deserialize_bool(submessage, &info_payload.object_info.optional_config); + + if (info_payload.object_info.optional_config) + { + success &= uxr_deserialize_ObjectVariant(submessage, &info_payload.object_info.config); + } + + success &= ucdr_deserialize_bool(submessage, &info_payload.object_info.optional_activity); + if (info_payload.object_info.optional_activity) + { + success &= ucdr_deserialize_uint8_t(submessage, &info_payload.object_info.activity.kind); + if (success && DDS_XRCE_OBJK_AGENT == info_payload.object_info.activity.kind) + { + success &= ucdr_deserialize_int16_t(submessage, + &info_payload.object_info.activity._.agent.availability); + session->on_pong_flag = (success && (info_payload.object_info.activity._.agent.availability > 0)) ? + (active_session ? + PONG_IN_SESSION_STATUS : + PONG_NO_SESSION_STATUS) : + NO_PONG_STATUS; + } + } +} + #ifdef PERFORMANCE_TESTING void read_submessage_performance( uxrSession* session, diff --git a/src/c/core/session/session_info.c b/src/c/core/session/session_info.c index 6209d689..b2dcea2d 100644 --- a/src/c/core/session/session_info.c +++ b/src/c/core/session/session_info.c @@ -44,7 +44,9 @@ void uxr_buffer_create_session( ucdrBuffer* ub, uint16_t mtu) { - CREATE_CLIENT_Payload payload; + CREATE_CLIENT_Payload payload = { + 0 + }; payload.client_representation.xrce_cookie = DDS_XRCE_XRCE_COOKIE; payload.client_representation.xrce_version = DDS_XRCE_XRCE_VERSION; payload.client_representation.xrce_vendor_id = VENDOR_ID_EPROSIMA; @@ -54,12 +56,35 @@ void uxr_buffer_create_session( payload.client_representation.client_key.data[3] = info->key[3]; payload.client_representation.session_id = info->id; payload.client_representation.optional_properties = false; + #ifdef UCLIENT_PROFILE_SHARED_MEMORY payload.client_representation.optional_properties = true; - payload.client_representation.properties.size = 1; - payload.client_representation.properties.data[0].name = "uxr_sm"; - payload.client_representation.properties.data[0].value = "1"; + payload.client_representation.properties.data[payload.client_representation.properties.size].name = "uxr_sm"; + payload.client_representation.properties.data[payload.client_representation.properties.size].value = "1"; + payload.client_representation.properties.size++; #endif /* ifdef UCLIENT_PROFILE_SHARED_MEMORY */ + +#ifdef UCLIENT_HARD_LIVELINESS_CHECK + payload.client_representation.optional_properties = true; + payload.client_representation.properties.data[payload.client_representation.properties.size].name = "uxr_hl"; + + const char* str = UXR_CONFIG_HARD_LIVELINESS_CHECK_TIMEOUT_STR; + + if (strlen(str) > 6) + { + str = "999999"; + } + + char buffer[7]; + const size_t leading_zeros = 6 - strlen(str); + memset(buffer, '0', leading_zeros); + memcpy(buffer + leading_zeros, str, strlen(str)); + buffer[6] = '\0'; + + payload.client_representation.properties.data[payload.client_representation.properties.size].value = buffer; + payload.client_representation.properties.size++; +#endif /* ifdef UCLIENT_HARD_LIVELINESS_CHECK */ + payload.client_representation.mtu = mtu; info->last_request_id = UXR_REQUEST_LOGIN; diff --git a/src/c/profile/transport/ip/tcp/tcp_transport_posix_nopoll.c b/src/c/profile/transport/ip/tcp/tcp_transport_posix_nopoll.c new file mode 100644 index 00000000..96e17bce --- /dev/null +++ b/src/c/profile/transport/ip/tcp/tcp_transport_posix_nopoll.c @@ -0,0 +1,126 @@ +#include +#include "tcp_transport_internal.h" + +#include +#include +#include +#include +#include +#include +#include + +bool uxr_init_tcp_platform( + uxrTCPPlatform* platform, + uxrIpProtocol ip_protocol, + const char* ip, + const char* port) +{ + bool rv = false; + + switch (ip_protocol) + { + case UXR_IPv4: + platform->fd = socket(AF_INET, SOCK_STREAM, 0); + break; + case UXR_IPv6: + platform->fd = socket(AF_INET6, SOCK_STREAM, 0); + break; + } + + if (-1 != platform->fd) + { + struct addrinfo hints; + struct addrinfo* result; + struct addrinfo* ptr; + + memset(&hints, 0, sizeof(hints)); + switch (ip_protocol) + { + case UXR_IPv4: + hints.ai_family = AF_INET; + break; + case UXR_IPv6: + hints.ai_family = AF_INET6; + break; + } + hints.ai_socktype = SOCK_DGRAM; + + if (0 == getaddrinfo(ip, port, &hints, &result)) + { + for (ptr = result; ptr != NULL; ptr = ptr->ai_next) + { + if (0 == connect(platform->fd, ptr->ai_addr, ptr->ai_addrlen)) + { + rv = true; + break; + } + } + } + freeaddrinfo(result); + } + return rv; +} + +bool uxr_close_tcp_platform( + uxrTCPPlatform* platform) +{ + return (-1 == platform->fd) ? true : (0 == close(platform->fd)); +} + +size_t uxr_write_tcp_data_platform( + uxrTCPPlatform* platform, + const uint8_t* buf, + size_t len, + uint8_t* errcode) +{ + size_t rv = 0; + ssize_t bytes_sent = send(platform->fd, (void*)buf, len, 0); + if (-1 != bytes_sent) + { + rv = (size_t)bytes_sent; + *errcode = 0; + } + else + { + *errcode = 1; + } + return rv; +} + +size_t uxr_read_tcp_data_platform( + uxrTCPPlatform* platform, + uint8_t* buf, + size_t len, + int timeout, + uint8_t* errcode) +{ + size_t rv = 0; + + timeout = (timeout <= 0) ? 1 : timeout; + + struct timeval tv; + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + setsockopt(platform->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + + ssize_t bytes_received = recv(platform->fd, (void*)buf, len, 0); + if (-1 != bytes_received) + { + rv = (size_t)bytes_received; + *errcode = 0; + } + else + { + *errcode = 1; + } + + return rv; +} + +void uxr_disconnect_tcp_platform( + struct uxrTCPPlatform* platform) +{ + close(platform->fd); + platform->fd = -1; +} diff --git a/src/c/util/ping.c b/src/c/util/ping.c index 33719924..dc4ac961 100644 --- a/src/c/util/ping.c +++ b/src/c/util/ping.c @@ -11,7 +11,8 @@ #include "../core/session/submessage_internal.h" bool serialize_get_info_message( - ucdrBuffer* ub); + ucdrBuffer* ub, + const uint8_t session_id); pong_status_t uxr_acknack_pong( ucdrBuffer* buffer); @@ -30,6 +31,10 @@ bool uxr_read_session_header( uint8_t* stream_id_raw, uxrSeqNum* seq_num); +void read_submessage_info( + uxrSession* session, + ucdrBuffer* submessage); + //================================================================== // PUBLIC //================================================================== @@ -43,7 +48,7 @@ bool uxr_ping_agent_session( ucdr_init_buffer(&ub, output_buffer, sizeof(output_buffer)); bool ret = false; - if (serialize_get_info_message(&ub)) + if (serialize_get_info_message(&ub, session->info.id)) { size_t message_length = ucdr_buffer_length(&ub); @@ -69,7 +74,7 @@ bool uxr_ping_agent_attempts( ucdrBuffer ub; ucdr_init_buffer(&ub, output_buffer, sizeof(output_buffer)); - if (serialize_get_info_message(&ub)) + if (serialize_get_info_message(&ub, SESSION_ID_WITHOUT_CLIENT_KEY)) { size_t message_length = ucdr_buffer_length(&ub); @@ -110,19 +115,20 @@ inline bool uxr_ping_agent( // PRIVATE //================================================================== bool serialize_get_info_message( - ucdrBuffer* ub) + ucdrBuffer* ub, + const uint8_t session_id) { bool res = true; GET_INFO_Payload gi_payload; gi_payload.base.request_id = (RequestId){{ - 0x00, GET_INFO_REQUEST_ID + 0x00, GET_INFO_REQUEST_PING_ID } }; gi_payload.base.object_id = DDS_XRCE_OBJECTID_AGENT; gi_payload.info_mask = INFO_ACTIVITY; - uxr_serialize_message_header(ub, SESSION_ID_WITHOUT_CLIENT_KEY, 0, 0, 0); + uxr_serialize_message_header(ub, session_id, 0, 0, 0); res &= uxr_buffer_submessage_header(ub, SUBMESSAGE_ID_GET_INFO, GET_INFO_MSG_SIZE, 0); res &= uxr_serialize_GET_INFO_Payload(ub, &gi_payload); @@ -158,3 +164,29 @@ bool listen_info_message( return success; } + +pong_status_t uxr_acknack_pong( + ucdrBuffer* buffer) +{ + bool success = false; + uxrSession fake_session = { + 0 + }; + + if (ucdr_buffer_remaining(buffer) > SUBHEADER_SIZE) + { + uint8_t id = 0; + uint8_t flags = 0; + uint16_t length = 0; + uxr_deserialize_submessage_header(buffer, &id, &flags, &length); + success = ucdr_buffer_remaining(buffer) >= length; + + if (success && id == SUBMESSAGE_ID_INFO) + { + fake_session.on_pong_flag = NO_PONG_STATUS; + read_submessage_info(&fake_session, buffer); + } + } + + return fake_session.on_pong_flag; +} diff --git a/test/unitary/session/Session.cpp b/test/unitary/session/Session.cpp index 936da846..12a44204 100644 --- a/test/unitary/session/Session.cpp +++ b/test/unitary/session/Session.cpp @@ -361,9 +361,15 @@ TEST_F(SessionTest, WaitSessionStatusBad) uint8_t buffer[MTU]; size_t length = 0; size_t attempts = 10; + int64_t start_timestamp = uxr_millis(); bool found = wait_session_status(&session, buffer, length, attempts); EXPECT_FALSE(found); - EXPECT_EQ(attempts, size_t(SessionTest::listening_counter)); + EXPECT_GE(size_t(SessionTest::listening_counter), attempts); + + // Check elapsed time with 100 ms tolerance + int64_t final_time = uxr_millis() - start_timestamp; + int64_t expected_time = (int64_t) (UXR_CONFIG_MIN_SESSION_CONNECTION_INTERVAL * attempts); + EXPECT_NEAR((double) final_time, (double) expected_time, 100); } TEST_F(SessionTest, SendMessageOk)