Skip to content

Commit 6e56837

Browse files
mergify[bot]EugenioColladoMiguelCompany
authored
Handle socket buffer size setting when system's maximum exceeded (#5527, #5631) (#5563)
* Handle socket buffer size setting when system's maximum exceeded (#5527) * Regression tests for asio_helpers socket buffer size Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com> * Regression tests udp & tcp Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com> * Refs #22210. Ensure that actual set value is returned by `asio_helpers::try_setting_buffer_size` Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Fix corner case infinite loop Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com> * Uncrustify Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com> * Fix UDP tests Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com> * Fix windows compilation Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com> * Applied suggestions to regression test Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com> * Applied suggestions to udp tests Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com> * Uncrustify Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com> --------- Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com> Signed-off-by: Miguel Company <miguelcompany@eprosima.com> Co-authored-by: Miguel Company <miguelcompany@eprosima.com> * Fix error handling logic in `try_setting_buffer_size` (#5631) * Refs #22208. Fix error handling logic in `try_setting_buffer_size`. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Refs #22756. Apply suggestion. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> --------- Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Fix included headers Signed-off-by: Miguel Company <miguelcompany@eprosima.com> * Avoid using make_unique. Signed-off-by: Miguel Company <miguelcompany@eprosima.com> --------- Signed-off-by: Eugenio Collado <eugeniocollado@eprosima.com> Signed-off-by: Miguel Company <miguelcompany@eprosima.com> Co-authored-by: EugenioCollado <121509066+EugenioCollado@users.noreply.github.com> Co-authored-by: Miguel Company <miguelcompany@eprosima.com>
1 parent 2148998 commit 6e56837

File tree

5 files changed

+201
-9
lines changed

5 files changed

+201
-9
lines changed

src/cpp/rtps/transport/asio_helpers.hpp

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,53 @@ struct asio_helpers
5050
{
5151
asio::error_code ec;
5252

53+
assert(initial_buffer_value >= minimum_buffer_value);
54+
5355
final_buffer_value = initial_buffer_value;
54-
while (final_buffer_value >= minimum_buffer_value)
56+
while (final_buffer_value > minimum_buffer_value)
5557
{
56-
socket.set_option(BufferOptionType(static_cast<int32_t>(final_buffer_value)), ec);
58+
int32_t value_to_set = static_cast<int32_t>(final_buffer_value);
59+
socket.set_option(BufferOptionType(value_to_set), ec);
5760
if (!ec)
5861
{
59-
return true;
62+
BufferOptionType option;
63+
socket.get_option(option, ec);
64+
if (!ec)
65+
{
66+
if (option.value() == value_to_set)
67+
{
68+
// Option actually set to the desired value
69+
return true;
70+
}
71+
// Try again with the value actually set
72+
final_buffer_value = option.value();
73+
continue;
74+
}
75+
// Could not determine the actual value, even though the option was set successfully.
76+
// The current buffer size is not defined.
77+
return false;
6078
}
6179

6280
final_buffer_value /= 2;
6381
}
6482

83+
// Perform a final attempt to set the minimum value
6584
final_buffer_value = minimum_buffer_value;
66-
socket.set_option(BufferOptionType(final_buffer_value), ec);
67-
return !ec;
85+
int32_t value_to_set = static_cast<int32_t>(final_buffer_value);
86+
socket.set_option(BufferOptionType(value_to_set), ec);
87+
if (!ec)
88+
{
89+
// Last attempt was successful. Get the actual value set.
90+
int32_t max_value = static_cast<int32_t>(initial_buffer_value);
91+
BufferOptionType option;
92+
socket.get_option(option, ec);
93+
if (!ec && (option.value() >= value_to_set) && (option.value() <= max_value))
94+
{
95+
final_buffer_value = option.value();
96+
return true;
97+
}
98+
}
99+
return false;
68100
}
69101

70102
/**
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright 2023 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <limits>
16+
#include <memory>
17+
#include <thread>
18+
19+
#include <asio.hpp>
20+
#include <gtest/gtest.h>
21+
22+
#include <fastdds/dds/log/Log.hpp>
23+
#include <fastrtps/transport/UDPv4TransportDescriptor.h>
24+
#include <fastrtps/utils/IPFinder.h>
25+
#include <fastrtps/utils/IPLocator.h>
26+
#include <fastrtps/utils/Semaphore.h>
27+
28+
#include <MockReceiverResource.h>
29+
#include <rtps/transport/asio_helpers.hpp>
30+
#include <rtps/transport/UDPv4Transport.h>
31+
32+
using namespace eprosima::fastdds::rtps;
33+
34+
35+
// Regression tests for redmine issue #22210
36+
37+
template <typename BufferOption, typename SocketType, typename Protocol>
38+
void test_buffer_setting(
39+
int initial_buffer_value,
40+
int minimum_buffer_value)
41+
{
42+
asio::io_service io_service;
43+
std::unique_ptr<SocketType> socket(new SocketType(io_service));
44+
45+
// Open the socket with the provided protocol
46+
socket->open(Protocol::v4());
47+
48+
uint32_t final_buffer_value = 0;
49+
50+
// Replace this with your actual implementation of try_setting_buffer_size
51+
ASSERT_TRUE(asio_helpers::try_setting_buffer_size<BufferOption>(
52+
*socket, initial_buffer_value, minimum_buffer_value, final_buffer_value));
53+
54+
55+
56+
BufferOption option;
57+
asio::error_code ec;
58+
socket->get_option(option, ec);
59+
if (!ec)
60+
{
61+
ASSERT_EQ(static_cast<uint32_t>(option.value()), final_buffer_value);
62+
}
63+
else
64+
{
65+
throw std::runtime_error("Failed to get buffer option");
66+
}
67+
}
68+
69+
// Test that the UDP buffer size is set actually to the value stored as the final value
70+
TEST(AsioHelpersTests, udp_buffer_size)
71+
{
72+
uint32_t minimum_buffer_value = 0;
73+
for (uint32_t initial_buffer_value = std::numeric_limits<uint32_t>::max(); initial_buffer_value > 0;
74+
initial_buffer_value /= 4)
75+
{
76+
test_buffer_setting<asio::socket_base::send_buffer_size, asio::ip::udp::socket, asio::ip::udp>(
77+
initial_buffer_value, minimum_buffer_value);
78+
test_buffer_setting<asio::socket_base::receive_buffer_size, asio::ip::udp::socket, asio::ip::udp>(
79+
initial_buffer_value, minimum_buffer_value);
80+
}
81+
}
82+
83+
// Test that the TCP buffer size is set actually to the value stored as the final value
84+
TEST(AsioHelpersTests, tcp_buffer_size)
85+
{
86+
uint32_t minimum_buffer_value = 0;
87+
for (uint32_t initial_buffer_value = std::numeric_limits<uint32_t>::max(); initial_buffer_value > 0;
88+
initial_buffer_value /= 4)
89+
{
90+
test_buffer_setting<asio::socket_base::send_buffer_size, asio::ip::tcp::socket, asio::ip::tcp>(
91+
initial_buffer_value, minimum_buffer_value);
92+
test_buffer_setting<asio::socket_base::receive_buffer_size, asio::ip::tcp::socket, asio::ip::tcp>(
93+
initial_buffer_value, minimum_buffer_value);
94+
}
95+
}
96+
97+
int main(
98+
int argc,
99+
char** argv)
100+
{
101+
testing::InitGoogleTest(&argc, argv);
102+
return RUN_ALL_TESTS();
103+
}

test/unittest/transport/CMakeLists.txt

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,28 @@ set(UDPV4TESTS_SOURCE
8585
${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Time_t.cpp
8686
)
8787

88+
set(ASIOHELPERSTESTS_SOURCE
89+
AsioHelpersTests.cpp
90+
mock/MockReceiverResource.cpp
91+
${PROJECT_SOURCE_DIR}/src/cpp/utils/IPFinder.cpp
92+
${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/Log.cpp
93+
${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/OStreamConsumer.cpp
94+
${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutConsumer.cpp
95+
${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutErrConsumer.cpp
96+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/attributes/PropertyPolicy.cpp
97+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/ThroughputControllerDescriptor.cpp
98+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/UDPv4Transport.cpp
99+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/UDPTransportInterface.cpp
100+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/ChannelResource.cpp
101+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/UDPChannelResource.cpp
102+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/network/NetworkFactory.cpp
103+
${TCPTransportInterface_SOURCE}
104+
${PROJECT_SOURCE_DIR}/src/cpp/utils/IPLocator.cpp
105+
${PROJECT_SOURCE_DIR}/src/cpp/utils/SystemInfo.cpp
106+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Time_t.cpp
107+
)
108+
109+
88110
set(UDPV6TESTS_SOURCE
89111
UDPv6Tests.cpp
90112
mock/MockReceiverResource.cpp
@@ -225,6 +247,9 @@ if(ANDROID)
225247
list(APPEND UDPV4TESTS_SOURCE
226248
${ANDROID_IFADDRS_SOURCE_DIR}/ifaddrs.c
227249
)
250+
list(APPEND ASIOHELPERSTESTS_SOURCE
251+
${ANDROID_IFADDRS_SOURCE_DIR}/ifaddrs.c
252+
)
228253
list(APPEND SHAREDMEMTESTS_SOURCE
229254
${ANDROID_IFADDRS_SOURCE_DIR}/ifaddrs.c
230255
)
@@ -399,11 +424,43 @@ foreach(TRANSPORT_XFAIL_TEST ${TRANSPORT_XFAIL_LIST})
399424
add_xfail_label(${CMAKE_CURRENT_SOURCE_DIR}/${TRANSPORT_XFAIL_TEST}.list)
400425
endforeach()
401426

427+
#####################################
428+
# AsioHelpers tests
429+
#####################################
430+
add_executable(AsioHelpersTests ${ASIOHELPERSTESTS_SOURCE})
431+
target_compile_definitions(AsioHelpersTests PRIVATE
432+
BOOST_ASIO_STANDALONE
433+
ASIO_STANDALONE
434+
$<$<AND:$<NOT:$<BOOL:${WIN32}>>,$<STREQUAL:"${CMAKE_BUILD_TYPE}","Debug">>:__DEBUG>
435+
$<$<BOOL:${INTERNAL_DEBUG}>:__INTERNALDEBUG> # Internal debug activated.
436+
)
437+
target_include_directories(AsioHelpersTests PRIVATE
438+
${Asio_INCLUDE_DIR}
439+
${PROJECT_SOURCE_DIR}/test/mock/rtps/MessageReceiver
440+
${PROJECT_SOURCE_DIR}/test/mock/rtps/ReceiverResource
441+
${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include
442+
${PROJECT_SOURCE_DIR}/src/cpp
443+
$<$<BOOL:${ANDROID}>:${ANDROID_IFADDRS_INCLUDE_DIR}>
444+
)
445+
target_link_libraries(AsioHelpersTests GTest::gtest ${MOCKS}
446+
$<$<BOOL:${TLS_FOUND}>:OpenSSL::SSL$<SEMICOLON>OpenSSL::Crypto>)
447+
if(QNX)
448+
target_link_libraries(AsioHelpersTests socket)
449+
endif()
450+
if(MSVC OR MSVC_IDE)
451+
target_link_libraries(AsioHelpersTests ${PRIVACY} fastcdr iphlpapi Shlwapi)
452+
else()
453+
target_link_libraries(AsioHelpersTests ${PRIVACY} fastcdr)
454+
endif()
455+
add_gtest(AsioHelpersTests SOURCES ${ASIOHELPERSTESTS_SOURCE})
456+
402457
if(ANDROID)
403458
set_property(TARGET UDPv4Tests PROPERTY CROSSCOMPILING_EMULATOR "adb;shell;cd;${CMAKE_CURRENT_BINARY_DIR};&&")
404459
set_property(TARGET UDPv6Tests PROPERTY CROSSCOMPILING_EMULATOR "adb;shell;cd;${CMAKE_CURRENT_BINARY_DIR};&&")
405460
set_property(TARGET TCPv4Tests PROPERTY CROSSCOMPILING_EMULATOR "adb;shell;cd;${CMAKE_CURRENT_BINARY_DIR};&&")
406461
set_property(TARGET TCPv6Tests PROPERTY CROSSCOMPILING_EMULATOR "adb;shell;cd;${CMAKE_CURRENT_BINARY_DIR};&&")
407462
set_property(TARGET SharedMemTests PROPERTY CROSSCOMPILING_EMULATOR "adb;shell;cd;${CMAKE_CURRENT_BINARY_DIR};&&")
408463
set_property(TARGET test_UDPv4Tests PROPERTY CROSSCOMPILING_EMULATOR "adb;shell;cd;${CMAKE_CURRENT_BINARY_DIR};&&")
464+
set_property(TARGET AsioHelpersTests PROPERTY CROSSCOMPILING_EMULATOR "adb;shell;cd;${CMAKE_CURRENT_BINARY_DIR};&&")
409465
endif()
466+

test/unittest/transport/UDPv4Tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -794,8 +794,8 @@ TEST_F(UDPv4Tests, double_binding_fails)
794794
void UDPv4Tests::HELPER_SetDescriptorDefaults()
795795
{
796796
descriptor.maxMessageSize = 5;
797-
descriptor.sendBufferSize = 5;
798-
descriptor.receiveBufferSize = 5;
797+
descriptor.sendBufferSize = 5000;
798+
descriptor.receiveBufferSize = 5000;
799799
descriptor.interfaceWhiteList.clear();
800800
}
801801

test/unittest/transport/UDPv6Tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -826,8 +826,8 @@ TEST_F(UDPv6Tests, double_binding_fails)
826826
void UDPv6Tests::HELPER_SetDescriptorDefaults()
827827
{
828828
descriptor.maxMessageSize = 5;
829-
descriptor.sendBufferSize = 5;
830-
descriptor.receiveBufferSize = 5;
829+
descriptor.sendBufferSize = 5000;
830+
descriptor.receiveBufferSize = 5000;
831831
}
832832

833833
int main(

0 commit comments

Comments
 (0)