diff --git a/api/test/network_emulation/network_emulation_interfaces.h b/api/test/network_emulation/network_emulation_interfaces.h index 5d75bf354a..0986df4a08 100644 --- a/api/test/network_emulation/network_emulation_interfaces.h +++ b/api/test/network_emulation/network_emulation_interfaces.h @@ -99,7 +99,8 @@ class EmulatedEndpoint : public EmulatedNetworkReceiverInterface { // on destination endpoint. virtual void SendPacket(const rtc::SocketAddress& from, const rtc::SocketAddress& to, - rtc::CopyOnWriteBuffer packet_data) = 0; + rtc::CopyOnWriteBuffer packet_data, + uint16_t application_overhead = 0) = 0; // Binds receiver to this endpoint to send and receive data. // |desired_port| is a port that should be used. If it is equal to 0, diff --git a/test/network/network_emulation.cc b/test/network/network_emulation.cc index f21b0eb1e6..a0ac5aee40 100644 --- a/test/network/network_emulation.cc +++ b/test/network/network_emulation.cc @@ -203,10 +203,11 @@ uint64_t EmulatedEndpointImpl::GetId() const { void EmulatedEndpointImpl::SendPacket(const rtc::SocketAddress& from, const rtc::SocketAddress& to, - rtc::CopyOnWriteBuffer packet_data) { + rtc::CopyOnWriteBuffer packet_data, + uint16_t application_overhead) { RTC_CHECK(from.ipaddr() == peer_local_addr_); EmulatedIpPacket packet(from, to, std::move(packet_data), - clock_->CurrentTime()); + clock_->CurrentTime(), application_overhead); task_queue_->PostTask([this, packet = std::move(packet)]() mutable { RTC_DCHECK_RUN_ON(task_queue_); Timestamp current_time = clock_->CurrentTime(); diff --git a/test/network/network_emulation.h b/test/network/network_emulation.h index b5e8164be1..bb5319f1a4 100644 --- a/test/network/network_emulation.h +++ b/test/network/network_emulation.h @@ -140,7 +140,8 @@ class EmulatedEndpointImpl : public EmulatedEndpoint { void SendPacket(const rtc::SocketAddress& from, const rtc::SocketAddress& to, - rtc::CopyOnWriteBuffer packet_data) override; + rtc::CopyOnWriteBuffer packet_data, + uint16_t application_overhead = 0) override; absl::optional BindReceiver( uint16_t desired_port, diff --git a/test/scenario/call_client.cc b/test/scenario/call_client.cc index 61612c5a04..fb888df694 100644 --- a/test/scenario/call_client.cc +++ b/test/scenario/call_client.cc @@ -318,6 +318,17 @@ void CallClient::SendTask(std::function task) { task_queue_.SendTask(std::move(task), RTC_FROM_HERE); } +int16_t CallClient::Bind(EmulatedEndpoint* endpoint) { + uint16_t port = endpoint->BindReceiver(0, this).value(); + endpoints_.push_back({endpoint, port}); + return port; +} + +void CallClient::UnBind() { + for (auto ep_port : endpoints_) + ep_port.first->UnbindReceiver(ep_port.second); +} + CallClientPair::~CallClientPair() = default; } // namespace test diff --git a/test/scenario/call_client.h b/test/scenario/call_client.h index a4c04affb1..1fbe256531 100644 --- a/test/scenario/call_client.h +++ b/test/scenario/call_client.h @@ -130,6 +130,8 @@ class CallClient : public EmulatedNetworkReceiverInterface { uint32_t GetNextRtxSsrc(); void AddExtensions(std::vector extensions); void SendTask(std::function task); + int16_t Bind(EmulatedEndpoint* endpoint); + void UnBind(); TimeController* const time_controller_; Clock* clock_; @@ -140,6 +142,7 @@ class CallClient : public EmulatedNetworkReceiverInterface { std::unique_ptr call_; std::unique_ptr transport_; std::unique_ptr const header_parser_; + std::vector> endpoints_; int next_video_ssrc_index_ = 0; int next_video_local_ssrc_index_ = 0; diff --git a/test/scenario/network_node.cc b/test/scenario/network_node.cc index c430b876de..48555203f3 100644 --- a/test/scenario/network_node.cc +++ b/test/scenario/network_node.cc @@ -85,48 +85,42 @@ bool NetworkNodeTransport::SendRtp(const uint8_t* packet, sent_packet.info.packet_type = rtc::PacketType::kData; sender_call_->OnSentPacket(sent_packet); - Timestamp send_time = Timestamp::ms(send_time_ms); rtc::CritScope crit(&crit_sect_); - if (!send_net_) + if (!endpoint_) return false; rtc::CopyOnWriteBuffer buffer(packet, length); - send_net_->OnPacketReceived( - EmulatedIpPacket(local_address_, receiver_address_, buffer, send_time, - packet_overhead_.bytes())); + endpoint_->SendPacket(local_address_, remote_address_, buffer, + packet_overhead_.bytes()); return true; } bool NetworkNodeTransport::SendRtcp(const uint8_t* packet, size_t length) { rtc::CopyOnWriteBuffer buffer(packet, length); - Timestamp send_time = sender_clock_->CurrentTime(); rtc::CritScope crit(&crit_sect_); - if (!send_net_) + if (!endpoint_) return false; - send_net_->OnPacketReceived( - EmulatedIpPacket(local_address_, receiver_address_, buffer, send_time, - packet_overhead_.bytes())); + endpoint_->SendPacket(local_address_, remote_address_, buffer, + packet_overhead_.bytes()); return true; } -void NetworkNodeTransport::Connect(EmulatedNetworkNode* send_node, - const rtc::IPAddress& receiver_ip, +void NetworkNodeTransport::Connect(EmulatedEndpoint* endpoint, + const rtc::SocketAddress& receiver_address, DataSize packet_overhead) { rtc::NetworkRoute route; route.connected = true; - route.local_network_id = - static_cast(receiver_ip.v4AddressAsHostOrderInteger()); - route.remote_network_id = - static_cast(receiver_ip.v4AddressAsHostOrderInteger()); + // We assume that the address will be unique in the lower bytes. + route.local_network_id = static_cast( + receiver_address.ipaddr().v4AddressAsHostOrderInteger()); + route.remote_network_id = static_cast( + receiver_address.ipaddr().v4AddressAsHostOrderInteger()); { - // Only IPv4 address is supported. We don't use full range of IPs in - // scenario framework and also we need a simple way to convert IP into - // network_id to signal network route. - RTC_CHECK_EQ(receiver_ip.family(), AF_INET); - RTC_CHECK_LE(receiver_ip.v4AddressAsHostOrderInteger(), - std::numeric_limits::max()); + // Only IPv4 address is supported. + RTC_CHECK_EQ(receiver_address.family(), AF_INET); rtc::CritScope crit(&crit_sect_); - send_net_ = send_node; - receiver_address_ = rtc::SocketAddress(receiver_ip, 0); + endpoint_ = endpoint; + local_address_ = rtc::SocketAddress(endpoint_->GetPeerLocalAddress(), 0); + remote_address_ = receiver_address; packet_overhead_ = packet_overhead; current_network_route_ = route; } @@ -141,7 +135,7 @@ void NetworkNodeTransport::Disconnect() { sender_call_->GetTransportControllerSend()->OnNetworkRouteChanged( kDummyTransportName, current_network_route_); current_network_route_ = {}; - send_net_ = nullptr; + endpoint_ = nullptr; } } // namespace test diff --git a/test/scenario/network_node.h b/test/scenario/network_node.h index 80f8a99d2d..b3d093b84e 100644 --- a/test/scenario/network_node.h +++ b/test/scenario/network_node.h @@ -59,8 +59,8 @@ class NetworkNodeTransport : public Transport { const PacketOptions& options) override; bool SendRtcp(const uint8_t* packet, size_t length) override; - void Connect(EmulatedNetworkNode* send_node, - const rtc::IPAddress& receiver_ip, + void Connect(EmulatedEndpoint* endpoint, + const rtc::SocketAddress& receiver_address, DataSize packet_overhead); void Disconnect(); @@ -73,10 +73,9 @@ class NetworkNodeTransport : public Transport { rtc::CriticalSection crit_sect_; Clock* const sender_clock_; Call* const sender_call_; - // Store local address here for consistency with receiver address. - const rtc::SocketAddress local_address_; - EmulatedNetworkNode* send_net_ RTC_GUARDED_BY(crit_sect_) = nullptr; - rtc::SocketAddress receiver_address_ RTC_GUARDED_BY(crit_sect_); + EmulatedEndpoint* endpoint_ RTC_GUARDED_BY(crit_sect_) = nullptr; + rtc::SocketAddress local_address_ RTC_GUARDED_BY(crit_sect_); + rtc::SocketAddress remote_address_ RTC_GUARDED_BY(crit_sect_); DataSize packet_overhead_ RTC_GUARDED_BY(crit_sect_) = DataSize::Zero(); rtc::NetworkRoute current_network_route_ RTC_GUARDED_BY(crit_sect_); }; diff --git a/test/scenario/scenario.cc b/test/scenario/scenario.cc index 9d27e6a4e2..0c5e3814fd 100644 --- a/test/scenario/scenario.cc +++ b/test/scenario/scenario.cc @@ -75,10 +75,10 @@ Scenario::Scenario( bool real_time) : log_writer_factory_(std::move(log_writer_factory)), time_controller_(CreateTimeController(real_time)), + network_manager_(time_controller_.get()), clock_(time_controller_->GetClock()), audio_decoder_factory_(CreateBuiltinAudioDecoderFactory()), audio_encoder_factory_(CreateBuiltinAudioEncoderFactory()), - network_manager_(time_controller_.get()), task_queue_(time_controller_->GetTaskQueueFactory()->CreateTaskQueue( "Scenario", TaskQueueFactory::Priority::NORMAL)) {} @@ -86,8 +86,10 @@ Scenario::Scenario( Scenario::~Scenario() { if (start_time_.IsFinite()) Stop(); - for (auto& call_client : clients_) + for (auto& call_client : clients_) { call_client->transport_->Disconnect(); + call_client->UnBind(); + } } ColumnPrinter Scenario::TimePrinter() { @@ -165,9 +167,10 @@ void Scenario::ChangeRoute(std::pair clients, void Scenario::ChangeRoute(std::pair clients, std::vector over_nodes, DataSize overhead) { - rtc::IPAddress route_ip(next_route_id_++); - EmulatedNetworkNode::CreateRoute(route_ip, over_nodes, clients.second); - clients.first->transport_->Connect(over_nodes.front(), route_ip, overhead); + EmulatedRoute* route = network_manager_.CreateRoute(over_nodes); + uint16_t port = clients.second->Bind(route->to); + auto addr = rtc::SocketAddress(route->to->GetPeerLocalAddress(), port); + clients.first->transport_->Connect(route->from, addr, overhead); } EmulatedNetworkNode* Scenario::CreateSimulationNode( diff --git a/test/scenario/scenario.h b/test/scenario/scenario.h index a4dc47108a..a5803bf60d 100644 --- a/test/scenario/scenario.h +++ b/test/scenario/scenario.h @@ -162,6 +162,7 @@ class Scenario { const std::unique_ptr log_writer_factory_; std::unique_ptr time_controller_; + NetworkEmulationManagerImpl network_manager_; Clock* clock_; std::vector> clients_; @@ -171,12 +172,10 @@ class Scenario { std::vector> simulation_nodes_; std::vector> printers_; - int64_t next_route_id_ = 40000; rtc::scoped_refptr audio_decoder_factory_; rtc::scoped_refptr audio_encoder_factory_; Timestamp start_time_ = Timestamp::PlusInfinity(); - NetworkEmulationManagerImpl network_manager_; // Defined last so it's destroyed first. rtc::TaskQueue task_queue_; };