Skip to content

Commit 6c1d7eb

Browse files
Handle socket buffer size setting when system's maximum exceeded (#5527)
* Regression tests for asio_helpers socket buffer size Signed-off-by: Eugenio Collado <[email protected]> * Regression tests udp & tcp Signed-off-by: Eugenio Collado <[email protected]> * Refs #22210. Ensure that actual set value is returned by `asio_helpers::try_setting_buffer_size` Signed-off-by: Miguel Company <[email protected]> * Fix corner case infinite loop Signed-off-by: Eugenio Collado <[email protected]> * Uncrustify Signed-off-by: Eugenio Collado <[email protected]> * Fix UDP tests Signed-off-by: Eugenio Collado <[email protected]> * Fix windows compilation Signed-off-by: Eugenio Collado <[email protected]> * Applied suggestions to regression test Signed-off-by: Eugenio Collado <[email protected]> * Applied suggestions to udp tests Signed-off-by: Eugenio Collado <[email protected]> * Uncrustify Signed-off-by: Eugenio Collado <[email protected]> --------- Signed-off-by: Eugenio Collado <[email protected]> Signed-off-by: Miguel Company <[email protected]> Co-authored-by: Miguel Company <[email protected]> (cherry picked from commit 5fc7786)
1 parent 9adca59 commit 6c1d7eb

File tree

5 files changed

+209
-8
lines changed

5 files changed

+209
-8
lines changed

src/cpp/rtps/transport/asio_helpers.hpp

+33-4
Original file line numberDiff line numberDiff line change
@@ -51,20 +51,49 @@ struct asio_helpers
5151
asio::error_code ec;
5252

5353
final_buffer_value = initial_buffer_value;
54-
while (final_buffer_value >= minimum_buffer_value)
54+
while (final_buffer_value > minimum_buffer_value)
5555
{
56-
socket.set_option(BufferOptionType(static_cast<int32_t>(final_buffer_value)), ec);
56+
int32_t value_to_set = static_cast<int32_t>(final_buffer_value);
57+
socket.set_option(BufferOptionType(value_to_set), ec);
5758
if (!ec)
5859
{
60+
BufferOptionType option;
61+
socket.get_option(option, ec);
62+
if (!ec)
63+
{
64+
if (option.value() == value_to_set)
65+
{
66+
// Option actually set to the desired value
67+
return true;
68+
}
69+
// Try again with the value actually set
70+
final_buffer_value = option.value();
71+
continue;
72+
}
73+
// Could not determine the actual value, but the option was set successfully.
74+
// Assume the option was set to the desired value.
5975
return true;
6076
}
6177

6278
final_buffer_value /= 2;
6379
}
6480

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

7099
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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 <fastdds/rtps/transport/UDPv4TransportDescriptor.hpp>
24+
#include <fastdds/utils/IPFinder.hpp>
25+
#include <fastdds/utils/IPLocator.hpp>
26+
27+
#include <utils/Semaphore.hpp>
28+
29+
#include <MockReceiverResource.h>
30+
#include <rtps/transport/asio_helpers.hpp>
31+
#include <rtps/transport/UDPv4Transport.h>
32+
33+
using namespace eprosima::fastdds::rtps;
34+
35+
36+
// Regression tests for redmine issue #22210
37+
38+
template <typename BufferOption, typename SocketType, typename Protocol>
39+
void test_buffer_setting(
40+
int initial_buffer_value,
41+
int minimum_buffer_value)
42+
{
43+
asio::io_service io_service;
44+
auto socket = std::make_unique<SocketType>(io_service);
45+
46+
// Open the socket with the provided protocol
47+
socket->open(Protocol::v4());
48+
49+
uint32_t final_buffer_value = 0;
50+
51+
// Replace this with your actual implementation of try_setting_buffer_size
52+
ASSERT_TRUE(asio_helpers::try_setting_buffer_size<BufferOption>(
53+
*socket, initial_buffer_value, minimum_buffer_value, final_buffer_value));
54+
55+
56+
57+
BufferOption option;
58+
asio::error_code ec;
59+
socket->get_option(option, ec);
60+
if (!ec)
61+
{
62+
ASSERT_EQ(static_cast<uint32_t>(option.value()), final_buffer_value);
63+
}
64+
else
65+
{
66+
throw std::runtime_error("Failed to get buffer option");
67+
}
68+
}
69+
70+
// Test that the UDP buffer size is set actually to the value stored as the final value
71+
TEST(AsioHelpersTests, udp_buffer_size)
72+
{
73+
uint32_t minimum_buffer_value = 0;
74+
for (uint32_t initial_buffer_value = std::numeric_limits<uint32_t>::max(); initial_buffer_value > 0;
75+
initial_buffer_value /= 4)
76+
{
77+
test_buffer_setting<asio::socket_base::send_buffer_size, asio::ip::udp::socket, asio::ip::udp>(
78+
initial_buffer_value, minimum_buffer_value);
79+
test_buffer_setting<asio::socket_base::receive_buffer_size, asio::ip::udp::socket, asio::ip::udp>(
80+
initial_buffer_value, minimum_buffer_value);
81+
}
82+
}
83+
84+
// Test that the TCP buffer size is set actually to the value stored as the final value
85+
TEST(AsioHelpersTests, tcp_buffer_size)
86+
{
87+
uint32_t minimum_buffer_value = 0;
88+
for (uint32_t initial_buffer_value = std::numeric_limits<uint32_t>::max(); initial_buffer_value > 0;
89+
initial_buffer_value /= 4)
90+
{
91+
test_buffer_setting<asio::socket_base::send_buffer_size, asio::ip::tcp::socket, asio::ip::tcp>(
92+
initial_buffer_value, minimum_buffer_value);
93+
test_buffer_setting<asio::socket_base::receive_buffer_size, asio::ip::tcp::socket, asio::ip::tcp>(
94+
initial_buffer_value, minimum_buffer_value);
95+
}
96+
}
97+
98+
int main(
99+
int argc,
100+
char** argv)
101+
{
102+
testing::InitGoogleTest(&argc, argv);
103+
return RUN_ALL_TESTS();
104+
}

test/unittest/transport/CMakeLists.txt

+68
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,39 @@ set(UDPV4TESTS_SOURCE
9696
${TCPTransportInterface_SOURCE}
9797
)
9898

99+
set(ASIOHELPERSTESTS_SOURCE
100+
AsioHelpersTests.cpp
101+
mock/MockReceiverResource.cpp
102+
${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/Time_t.cpp
103+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/attributes/PropertyPolicy.cpp
104+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/attributes/ThreadSettings.cpp
105+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/GuidPrefix_t.cpp
106+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/LocatorWithMask.cpp
107+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/SerializedPayload.cpp
108+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Time_t.cpp
109+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/messages/CDRMessage.cpp
110+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/network/NetworkBuffer.cpp
111+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/network/NetworkFactory.cpp
112+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/network/utils/netmask_filter.cpp
113+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/network/utils/network.cpp
114+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/ChannelResource.cpp
115+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/network/NetmaskFilterKind.cpp
116+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/network/NetworkInterface.cpp
117+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/network/NetworkInterfaceWithFilter.cpp
118+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/PortBasedTransportDescriptor.cpp
119+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TransportInterface.cpp
120+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/UDPChannelResource.cpp
121+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/UDPTransportInterface.cpp
122+
${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/UDPv4Transport.cpp
123+
${PROJECT_SOURCE_DIR}/src/cpp/utils/Host.cpp
124+
${PROJECT_SOURCE_DIR}/src/cpp/utils/IPFinder.cpp
125+
${PROJECT_SOURCE_DIR}/src/cpp/utils/IPLocator.cpp
126+
${PROJECT_SOURCE_DIR}/src/cpp/utils/md5.cpp
127+
${PROJECT_SOURCE_DIR}/src/cpp/utils/SystemInfo.cpp
128+
${TCPTransportInterface_SOURCE}
129+
)
130+
131+
99132
set(UDPV6TESTS_SOURCE
100133
UDPv6Tests.cpp
101134
mock/MockReceiverResource.cpp
@@ -499,3 +532,38 @@ target_link_libraries(${PORTBASED_TRANSPORTDESCRIPTOR_TESTS_TARGET}
499532
${MOCKS})
500533

501534
gtest_discover_tests(${PORTBASED_TRANSPORTDESCRIPTOR_TESTS_TARGET})
535+
536+
#####################################
537+
# AsioHelpers tests
538+
#####################################
539+
add_executable(AsioHelpersTests ${ASIOHELPERSTESTS_SOURCE})
540+
target_compile_definitions(AsioHelpersTests PRIVATE
541+
BOOST_ASIO_STANDALONE
542+
ASIO_STANDALONE
543+
$<$<AND:$<NOT:$<BOOL:${WIN32}>>,$<STREQUAL:"${CMAKE_BUILD_TYPE}","Debug">>:__DEBUG>
544+
$<$<BOOL:${INTERNAL_DEBUG}>:__INTERNALDEBUG> # Internal debug activated.
545+
)
546+
target_include_directories(AsioHelpersTests PRIVATE
547+
${Asio_INCLUDE_DIR}
548+
${PROJECT_SOURCE_DIR}/test/mock/rtps/MessageReceiver
549+
${PROJECT_SOURCE_DIR}/test/mock/rtps/ReceiverResource
550+
${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include
551+
${PROJECT_SOURCE_DIR}/src/cpp
552+
$<$<BOOL:${ANDROID}>:${ANDROID_IFADDRS_INCLUDE_DIR}>
553+
)
554+
target_link_libraries(AsioHelpersTests
555+
fastcdr
556+
fastdds::log
557+
GTest::gtest
558+
${MOCKS}
559+
$<$<BOOL:${TLS_FOUND}>:OpenSSL::SSL$<SEMICOLON>OpenSSL::Crypto>)
560+
if(QNX)
561+
target_link_libraries(AsioHelpersTests socket)
562+
endif()
563+
if(MSVC OR MSVC_IDE)
564+
target_link_libraries(AsioHelpersTests ${PRIVACY} iphlpapi Shlwapi )
565+
endif()
566+
if (APPLE)
567+
target_link_libraries(AsioHelpersTests ${PRIVACY} "-framework CoreFoundation" "-framework IOKit")
568+
endif()
569+
gtest_discover_tests(AsioHelpersTests)

test/unittest/transport/UDPv4Tests.cpp

+2-2
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

+2-2
Original file line numberDiff line numberDiff line change
@@ -834,8 +834,8 @@ TEST_F(UDPv6Tests, double_binding_fails)
834834
void UDPv6Tests::HELPER_SetDescriptorDefaults()
835835
{
836836
descriptor.maxMessageSize = 5;
837-
descriptor.sendBufferSize = 5;
838-
descriptor.receiveBufferSize = 5;
837+
descriptor.sendBufferSize = 5000;
838+
descriptor.receiveBufferSize = 5000;
839839
}
840840

841841
int main(

0 commit comments

Comments
 (0)