| /* |
| * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "rtc_base/async_udp_socket.h" |
| |
| #include <cstdint> |
| #include <deque> |
| #include <memory> |
| #include <utility> |
| |
| #include "api/environment/environment.h" |
| #include "api/units/time_delta.h" |
| #include "api/units/timestamp.h" |
| #include "rtc_base/async_packet_socket.h" |
| #include "rtc_base/mock_socket.h" |
| #include "rtc_base/network/received_packet.h" |
| #include "rtc_base/socket.h" |
| #include "rtc_base/socket_address.h" |
| #include "rtc_base/virtual_socket_server.h" |
| #include "system_wrappers/include/clock.h" |
| #include "test/create_test_environment.h" |
| #include "test/gmock.h" |
| #include "test/gtest.h" |
| |
| namespace webrtc { |
| |
| using ::testing::_; |
| using ::testing::MockFunction; |
| using ::testing::NotNull; |
| |
| TEST(AsyncUDPSocketTest, SetSocketOptionIfEctChange) { |
| const SocketAddress kAddr("22.22.22.22", 0); |
| VirtualSocketServer socket_server; |
| std::unique_ptr<AsyncUDPSocket> udp_socket = |
| AsyncUDPSocket::Create(CreateTestEnvironment(), kAddr, socket_server); |
| ASSERT_THAT(udp_socket, NotNull()); |
| |
| int ect = 0; |
| udp_socket->GetOption(Socket::OPT_SEND_ECN, &ect); |
| ASSERT_EQ(ect, 0); |
| |
| uint8_t buffer[] = "hello"; |
| AsyncSocketPacketOptions packet_options; |
| packet_options.ect_1 = false; |
| udp_socket->SendTo(buffer, 5, kAddr, packet_options); |
| udp_socket->GetOption(Socket::OPT_SEND_ECN, &ect); |
| EXPECT_EQ(ect, 0); |
| |
| packet_options.ect_1 = true; |
| udp_socket->SendTo(buffer, 5, kAddr, packet_options); |
| udp_socket->GetOption(Socket::OPT_SEND_ECN, &ect); |
| EXPECT_EQ(ect, 1); |
| |
| packet_options.ect_1 = false; |
| udp_socket->SendTo(buffer, 5, kAddr, packet_options); |
| udp_socket->GetOption(Socket::OPT_SEND_ECN, &ect); |
| EXPECT_EQ(ect, 0); |
| } |
| |
| TEST(AsyncUDPSocketTest, ArrivalTimeStampCanBeBeforeCurrentTime) { |
| SimulatedClock webrtc_clock(Timestamp::Seconds(456)); |
| Environment env = CreateTestEnvironment({.time = &webrtc_clock}); |
| std::unique_ptr<MockSocket> socket = std::make_unique<MockSocket>(); |
| MockSocket* socket_ptr = socket.get(); |
| AsyncUDPSocket async_socket(env, std::move(socket)); |
| testing::MockFunction<void(AsyncPacketSocket*, const ReceivedIpPacket&)> |
| received_packet_callback; |
| async_socket.RegisterReceivedPacketCallback( |
| received_packet_callback.AsStdFunction()); |
| |
| const Timestamp kSocketEpoch = Timestamp::Seconds(123); |
| EXPECT_CALL(*socket_ptr, RecvFrom(_)) |
| .WillRepeatedly([&](Socket::ReceiveBuffer& buffer) { |
| buffer.payload = "hello"; |
| buffer.arrival_time = kSocketEpoch; |
| return buffer.payload.size(); |
| }); |
| EXPECT_CALL(received_packet_callback, Call) |
| .WillRepeatedly([&](AsyncPacketSocket*, const ReceivedIpPacket& packet) { |
| EXPECT_EQ(packet.arrival_time(), webrtc_clock.CurrentTime()); |
| }); |
| socket_ptr->SignalReadEvent(socket_ptr); |
| |
| // Let 10ms pass until next read event. |
| webrtc_clock.AdvanceTime(TimeDelta::Millis(10)); |
| |
| EXPECT_CALL(*socket_ptr, RecvFrom(_)) |
| .WillRepeatedly([&](Socket::ReceiveBuffer& buffer) { |
| buffer.payload = "hello"; |
| // But only 5 ms has passed since the last received packet. |
| buffer.arrival_time = kSocketEpoch + TimeDelta::Millis(5); |
| return buffer.payload.size(); |
| }); |
| EXPECT_CALL(received_packet_callback, Call) |
| .WillRepeatedly([&](AsyncPacketSocket*, const ReceivedIpPacket& packet) { |
| EXPECT_EQ(packet.arrival_time(), |
| webrtc_clock.CurrentTime() - TimeDelta::Millis(5)); |
| }); |
| socket_ptr->SignalReadEvent(socket_ptr); |
| } |
| |
| TEST(AsyncUDPSocketTest, InitiallyBufferedPacketsGetSameArrivalTime) { |
| SimulatedClock webrtc_clock(Timestamp::Seconds(456)); |
| Environment env = CreateTestEnvironment({.time = &webrtc_clock}); |
| std::unique_ptr<MockSocket> socket = std::make_unique<MockSocket>(); |
| MockSocket* socket_ptr = socket.get(); |
| AsyncUDPSocket async_socket(env, std::move(socket)); |
| testing::MockFunction<void(AsyncPacketSocket*, const ReceivedIpPacket&)> |
| received_packet_callback; |
| async_socket.RegisterReceivedPacketCallback( |
| received_packet_callback.AsStdFunction()); |
| |
| // Simulate that three packets are received with some time delta. |
| const Timestamp kSocketEpoch = Timestamp::Seconds(123); |
| std::deque<Timestamp> socket_arrival_times = { |
| kSocketEpoch, kSocketEpoch + TimeDelta::Millis(10), |
| kSocketEpoch + TimeDelta::Millis(20)}; |
| |
| EXPECT_CALL(*socket_ptr, RecvFrom(_)) |
| .Times(3) |
| .WillRepeatedly([&](Socket::ReceiveBuffer& buffer) { |
| buffer.payload = "hello"; |
| buffer.arrival_time = socket_arrival_times.front(); |
| socket_arrival_times.pop_front(); |
| return buffer.payload.size(); |
| }); |
| |
| EXPECT_CALL(received_packet_callback, Call) |
| .Times(3) |
| .WillRepeatedly([&](AsyncPacketSocket*, const ReceivedIpPacket& packet) { |
| // Despite the packets being received at different times, They all have |
| // the same timestamp. |
| EXPECT_EQ(packet.arrival_time(), webrtc_clock.CurrentTime()); |
| }); |
| // But assume, CPU is blocked and can not read the packet at the pace they |
| // arrive. Instead they are read one after each other a bit later. |
| socket_ptr->SignalReadEvent(socket_ptr); |
| socket_ptr->SignalReadEvent(socket_ptr); |
| socket_ptr->SignalReadEvent(socket_ptr); |
| } |
| |
| TEST(AsyncUDPSocketTest, ArrivalTimeStampCanNotBeAfterCurrentTime) { |
| SimulatedClock webrtc_clock(Timestamp::Seconds(456)); |
| Environment env = CreateTestEnvironment({.time = &webrtc_clock}); |
| std::unique_ptr<MockSocket> socket = std::make_unique<MockSocket>(); |
| MockSocket* socket_ptr = socket.get(); |
| AsyncUDPSocket async_socket(env, std::move(socket)); |
| testing::MockFunction<void(AsyncPacketSocket*, const ReceivedIpPacket&)> |
| received_packet_callback; |
| async_socket.RegisterReceivedPacketCallback( |
| received_packet_callback.AsStdFunction()); |
| |
| const Timestamp kSocketEpoch = Timestamp::Seconds(123); |
| EXPECT_CALL(*socket_ptr, RecvFrom(_)) |
| .WillRepeatedly([&](Socket::ReceiveBuffer& buffer) { |
| buffer.payload = "hello"; |
| buffer.arrival_time = kSocketEpoch; |
| return buffer.payload.size(); |
| }); |
| EXPECT_CALL(received_packet_callback, Call) |
| .WillRepeatedly([&](AsyncPacketSocket*, const ReceivedIpPacket& packet) { |
| EXPECT_EQ(packet.arrival_time(), webrtc_clock.CurrentTime()); |
| }); |
| socket_ptr->SignalReadEvent(socket_ptr); |
| |
| // Let 10ms pass until next read event. |
| webrtc_clock.AdvanceTime(TimeDelta::Millis(10)); |
| |
| EXPECT_CALL(*socket_ptr, RecvFrom(_)) |
| .WillRepeatedly([&](Socket::ReceiveBuffer& buffer) { |
| buffer.payload = "hello"; |
| // But the next packet indicate it is received 25 ms after the previous. |
| buffer.arrival_time = kSocketEpoch + TimeDelta::Millis(25); |
| return buffer.payload.size(); |
| }); |
| EXPECT_CALL(received_packet_callback, Call) |
| .WillRepeatedly([&](AsyncPacketSocket*, const ReceivedIpPacket& packet) { |
| // We still expect the arrival time to be set no later than the current |
| // time. |
| EXPECT_EQ(packet.arrival_time(), webrtc_clock.CurrentTime()); |
| }); |
| socket_ptr->SignalReadEvent(socket_ptr); |
| } |
| |
| } // namespace webrtc |