Skip to content

Commit 775ed56

Browse files
author
Gallardo994
committed
Max payload size should be limited by receive window
1 parent 10cf3b9 commit 775ed56

3 files changed

Lines changed: 65 additions & 7 deletions

File tree

imkcpp/include/imkcpp.hpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -330,12 +330,9 @@ namespace imkcpp {
330330

331331
/// Calculates the maximum payload size that can be sent in a single send() call.
332332
[[nodiscard]] auto estimate_max_payload_size() const noexcept -> size_t {
333-
const size_t max_segments_count = std::min(
334-
static_cast<size_t>(this->congestion_controller.get_send_window()),
335-
static_cast<size_t>(std::numeric_limits<u8>::max())
336-
);
337-
338-
return MAX_SEGMENT_SIZE * max_segments_count;
333+
return MAX_SEGMENT_SIZE * std::min(
334+
static_cast<size_t>(this->congestion_controller.get_receive_window()),
335+
static_cast<size_t>(std::numeric_limits<u8>::max()));
339336
}
340337
};
341338
}

imkcpp/include/sender.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ namespace imkcpp {
6060
return tl::unexpected(error::too_many_fragments);
6161
}
6262

63-
if (count > this->congestion_controller.get_send_window()) {
63+
// We should limit sending by receive window because we can send more than send_wnd segments,
64+
// but cannot receive more than rcv_wnd segments.
65+
if (count > this->congestion_controller.get_receive_window()) {
6466
return tl::unexpected(error::exceeds_window_size);
6567
}
6668

tests/Send_Tests.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,65 @@ TEST(Send_Tests, Send_LossyScenario) {
214214
std::cout << "Send_LossyScenario finished in simulated " << update_idx << " calls" << std::endl;
215215
}
216216

217+
TEST(Send_Tests, Send_SendWindowSmallerThanReceive) {
218+
using namespace imkcpp;
219+
220+
constexpr size_t max_segment_size = MTU_TO_MSS<constants::IKCP_MTU_DEF>();
221+
constexpr size_t size = max_segment_size * 250;
222+
223+
ImKcpp<constants::IKCP_MTU_DEF> kcp_output(0);
224+
kcp_output.set_send_window(128);
225+
kcp_output.set_receive_window(256);
226+
kcp_output.set_interval(10);
227+
kcp_output.update(0, [](std::span<const std::byte>) { });
228+
229+
ImKcpp<constants::IKCP_MTU_DEF> kcp_input(0);
230+
kcp_input.set_send_window(128);
231+
kcp_input.set_receive_window(256);
232+
kcp_input.set_interval(10);
233+
kcp_input.update(0, [](std::span<const std::byte>) { });
234+
235+
std::vector<std::byte> send_buffer(size);
236+
for (u32 j = 0; j < size; ++j) {
237+
send_buffer[j] = static_cast<std::byte>(j);
238+
}
239+
240+
auto send_result = kcp_output.send(send_buffer);
241+
ASSERT_TRUE(send_result.has_value()) << err_to_str(send_result.error());
242+
ASSERT_EQ(send_result.value(), size);
243+
244+
auto output_to_input = [&](const std::span<const std::byte> data) {
245+
kcp_input.input(data);
246+
};
247+
248+
auto input_to_output = [&](const std::span<const std::byte> data) {
249+
kcp_output.input(data);
250+
};
251+
252+
size_t update_idx = 0;
253+
254+
while (kcp_output.get_state() == State::Alive && kcp_input.peek_size() != size) {
255+
const auto now = static_cast<u32>(update_idx * 10);
256+
257+
kcp_output.update(now, output_to_input);
258+
kcp_input.update(now, input_to_output);
259+
260+
++update_idx;
261+
}
262+
263+
ASSERT_EQ(kcp_output.get_state(), State::Alive);
264+
265+
std::vector<std::byte> recv_buffer(size);
266+
auto recv_result = kcp_input.recv(recv_buffer);
267+
ASSERT_TRUE(recv_result.has_value()) << err_to_str(recv_result.error());
268+
269+
for (size_t j = 0; j < size; ++j) {
270+
EXPECT_EQ(send_buffer.at(j), recv_buffer.at(j));
271+
}
272+
273+
std::cout << "Send_LossyScenario finished in simulated " << update_idx << " calls" << std::endl;
274+
}
275+
217276
TEST(Send_Tests, Send_FragmentedValidValues) {
218277
using namespace imkcpp;
219278

0 commit comments

Comments
 (0)