Extract NetworkReceiverInterface and introduce EmulatedIpPacket
It is a step in the big refactoring to introduce new network emulation layer for peer connection level e2e test, which will be based on system sockets level injection. Bug: webrtc:10138 Change-Id: Ie3854d22aa3eec289617bc432026ea670646556a Reviewed-on: https://webrtc-review.googlesource.com/c/115943 Reviewed-by: Sebastian Jansson <srte@webrtc.org> Commit-Queue: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/master@{#26137}
This commit is contained in:
parent
45f2f2a4c2
commit
40f511540b
@ -86,6 +86,7 @@ if (rtc_include_tests) {
|
||||
"../../modules/video_coding:webrtc_vp8",
|
||||
"../../modules/video_coding:webrtc_vp9",
|
||||
"../../rtc_base:checks",
|
||||
"../../rtc_base:rtc_base",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"../../rtc_base:rtc_base_tests_utils",
|
||||
"../../rtc_base:rtc_task_queue",
|
||||
@ -94,6 +95,7 @@ if (rtc_include_tests) {
|
||||
"../../system_wrappers",
|
||||
"../../system_wrappers:field_trial",
|
||||
"../../video",
|
||||
"network:emulated_network",
|
||||
"//third_party/abseil-cpp/absl/memory",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
|
||||
@ -166,25 +166,26 @@ Call::Stats CallClient::GetStats() {
|
||||
return call_->GetStats();
|
||||
}
|
||||
|
||||
void CallClient::DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) {
|
||||
void CallClient::OnPacketReceived(EmulatedIpPacket packet) {
|
||||
// Removes added overhead before delivering packet to sender.
|
||||
RTC_DCHECK_GE(packet.size(), route_overhead_.at(receiver).bytes());
|
||||
packet.SetSize(packet.size() - route_overhead_.at(receiver).bytes());
|
||||
RTC_DCHECK_GE(packet.data.size(),
|
||||
route_overhead_.at(packet.dest_endpoint_id).bytes());
|
||||
packet.data.SetSize(packet.data.size() -
|
||||
route_overhead_.at(packet.dest_endpoint_id).bytes());
|
||||
|
||||
MediaType media_type = MediaType::ANY;
|
||||
if (!RtpHeaderParser::IsRtcp(packet.cdata(), packet.size())) {
|
||||
if (!RtpHeaderParser::IsRtcp(packet.cdata(), packet.data.size())) {
|
||||
RTPHeader header;
|
||||
bool success =
|
||||
header_parser_->Parse(packet.cdata(), packet.size(), &header);
|
||||
header_parser_->Parse(packet.cdata(), packet.data.size(), &header);
|
||||
if (!success) {
|
||||
RTC_DLOG(LS_ERROR) << "Failed to parse RTP header of packet";
|
||||
return;
|
||||
}
|
||||
media_type = ssrc_media_types_[header.ssrc];
|
||||
}
|
||||
call_->Receiver()->DeliverPacket(media_type, packet, at_time.us());
|
||||
call_->Receiver()->DeliverPacket(media_type, packet.data,
|
||||
packet.arrival_time.us());
|
||||
}
|
||||
|
||||
uint32_t CallClient::GetNextVideoSsrc() {
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "modules/rtp_rtcp/include/rtp_header_parser.h"
|
||||
#include "rtc_base/constructormagic.h"
|
||||
#include "test/scenario/column_printer.h"
|
||||
#include "test/scenario/network/network_emulation.h"
|
||||
#include "test/scenario/network_node.h"
|
||||
#include "test/scenario/scenario_config.h"
|
||||
|
||||
@ -56,7 +57,7 @@ struct CallClientFakeAudio {
|
||||
// CallClient represents a participant in a call scenario. It is created by the
|
||||
// Scenario class and is used as sender and receiver when setting up a media
|
||||
// stream session.
|
||||
class CallClient : public NetworkReceiverInterface {
|
||||
class CallClient : public EmulatedNetworkReceiverInterface {
|
||||
public:
|
||||
CallClient(Clock* clock,
|
||||
std::string name,
|
||||
@ -71,9 +72,7 @@ class CallClient : public NetworkReceiverInterface {
|
||||
return DataRate::bps(GetStats().send_bandwidth_bps);
|
||||
}
|
||||
|
||||
void DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) override;
|
||||
void OnPacketReceived(EmulatedIpPacket packet) override;
|
||||
|
||||
private:
|
||||
friend class Scenario;
|
||||
@ -100,8 +99,8 @@ class CallClient : public NetworkReceiverInterface {
|
||||
RtpHeaderParser* const header_parser_;
|
||||
|
||||
std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory_;
|
||||
// Stores the configured overhead per known incomming route. This is used to
|
||||
// subtract the overhead before processing.
|
||||
// Stores the configured overhead per known destination endpoint. This is used
|
||||
// to subtract the overhead before processing.
|
||||
std::map<uint64_t, DataSize> route_overhead_;
|
||||
int next_video_ssrc_index_ = 0;
|
||||
int next_rtx_ssrc_index_ = 0;
|
||||
|
||||
21
test/scenario/network/BUILD.gn
Normal file
21
test/scenario/network/BUILD.gn
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2018 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.
|
||||
|
||||
import("../../../webrtc.gni")
|
||||
|
||||
rtc_source_set("emulated_network") {
|
||||
sources = [
|
||||
"network_emulation.cc",
|
||||
"network_emulation.h",
|
||||
]
|
||||
deps = [
|
||||
"../../../api/units:timestamp",
|
||||
"../../../rtc_base:rtc_base",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
32
test/scenario/network/network_emulation.cc
Normal file
32
test/scenario/network/network_emulation.cc
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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 "test/scenario/network/network_emulation.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
EmulatedIpPacket::EmulatedIpPacket(const rtc::SocketAddress& from,
|
||||
const rtc::SocketAddress& to,
|
||||
uint64_t dest_endpoint_id,
|
||||
rtc::CopyOnWriteBuffer data,
|
||||
Timestamp arrival_time)
|
||||
: from(from),
|
||||
to(to),
|
||||
dest_endpoint_id(dest_endpoint_id),
|
||||
data(data),
|
||||
arrival_time(arrival_time) {}
|
||||
|
||||
EmulatedIpPacket::~EmulatedIpPacket() = default;
|
||||
|
||||
EmulatedIpPacket::EmulatedIpPacket(EmulatedIpPacket&&) = default;
|
||||
|
||||
} // namespace webrtc
|
||||
64
test/scenario/network/network_emulation.h
Normal file
64
test/scenario/network/network_emulation.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2018 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.
|
||||
*/
|
||||
|
||||
#ifndef TEST_SCENARIO_NETWORK_NETWORK_EMULATION_H_
|
||||
#define TEST_SCENARIO_NETWORK_NETWORK_EMULATION_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "rtc_base/asyncsocket.h"
|
||||
#include "rtc_base/copyonwritebuffer.h"
|
||||
#include "rtc_base/socketaddress.h"
|
||||
#include "rtc_base/thread.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
struct EmulatedIpPacket {
|
||||
public:
|
||||
EmulatedIpPacket(const rtc::SocketAddress& from,
|
||||
const rtc::SocketAddress& to,
|
||||
uint64_t dest_endpoint_id,
|
||||
rtc::CopyOnWriteBuffer data,
|
||||
Timestamp arrival_time);
|
||||
|
||||
~EmulatedIpPacket();
|
||||
// This object is not copyable or assignable.
|
||||
EmulatedIpPacket(const EmulatedIpPacket&) = delete;
|
||||
EmulatedIpPacket& operator=(const EmulatedIpPacket&) = delete;
|
||||
// This object is only moveable.
|
||||
EmulatedIpPacket(EmulatedIpPacket&&);
|
||||
EmulatedIpPacket& operator=(EmulatedIpPacket&&);
|
||||
|
||||
size_t size() const { return data.size(); }
|
||||
const uint8_t* cdata() const { return data.cdata(); }
|
||||
|
||||
rtc::SocketAddress from;
|
||||
rtc::SocketAddress to;
|
||||
uint64_t dest_endpoint_id;
|
||||
rtc::CopyOnWriteBuffer data;
|
||||
Timestamp arrival_time;
|
||||
};
|
||||
|
||||
class EmulatedNetworkReceiverInterface {
|
||||
public:
|
||||
virtual ~EmulatedNetworkReceiverInterface() = default;
|
||||
|
||||
virtual void OnPacketReceived(EmulatedIpPacket packet) = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // TEST_SCENARIO_NETWORK_NETWORK_EMULATION_H_
|
||||
@ -27,16 +27,12 @@ SimulatedNetwork::Config CreateSimulationConfig(NetworkNodeConfig config) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void NullReceiver::DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) {}
|
||||
void NullReceiver::OnPacketReceived(EmulatedIpPacket packet) {}
|
||||
|
||||
ActionReceiver::ActionReceiver(std::function<void()> action)
|
||||
: action_(action) {}
|
||||
|
||||
void ActionReceiver::DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) {
|
||||
void ActionReceiver::OnPacketReceived(EmulatedIpPacket packet) {
|
||||
action_();
|
||||
}
|
||||
|
||||
@ -47,7 +43,8 @@ NetworkNode::NetworkNode(NetworkNodeConfig config,
|
||||
: packet_overhead_(config.packet_overhead.bytes()),
|
||||
behavior_(std::move(behavior)) {}
|
||||
|
||||
void NetworkNode::SetRoute(uint64_t receiver, NetworkReceiverInterface* node) {
|
||||
void NetworkNode::SetRoute(uint64_t receiver,
|
||||
EmulatedNetworkReceiverInterface* node) {
|
||||
rtc::CritScope crit(&crit_sect_);
|
||||
routing_[receiver] = node;
|
||||
}
|
||||
@ -58,16 +55,15 @@ void NetworkNode::ClearRoute(uint64_t receiver_id) {
|
||||
routing_.erase(it);
|
||||
}
|
||||
|
||||
void NetworkNode::DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) {
|
||||
void NetworkNode::OnPacketReceived(EmulatedIpPacket packet) {
|
||||
rtc::CritScope crit(&crit_sect_);
|
||||
if (routing_.find(receiver) == routing_.end())
|
||||
if (routing_.find(packet.dest_endpoint_id) == routing_.end())
|
||||
return;
|
||||
uint64_t packet_id = next_packet_id_++;
|
||||
if (behavior_->EnqueuePacket(PacketInFlightInfo(
|
||||
packet.size() + packet_overhead_, at_time.us(), packet_id))) {
|
||||
packets_.emplace_back(StoredPacket{packet, receiver, packet_id, false});
|
||||
if (behavior_->EnqueuePacket(
|
||||
PacketInFlightInfo(packet.data.size() + packet_overhead_,
|
||||
packet.arrival_time.us(), packet_id))) {
|
||||
packets_.emplace_back(StoredPacket{std::move(packet), packet_id, false});
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +79,7 @@ void NetworkNode::Process(Timestamp at_time) {
|
||||
}
|
||||
for (PacketDeliveryInfo& delivery_info : delivery_infos) {
|
||||
StoredPacket* packet = nullptr;
|
||||
NetworkReceiverInterface* receiver = nullptr;
|
||||
EmulatedNetworkReceiverInterface* receiver = nullptr;
|
||||
{
|
||||
rtc::CritScope crit(&crit_sect_);
|
||||
for (StoredPacket& stored_packet : packets_) {
|
||||
@ -94,13 +90,13 @@ void NetworkNode::Process(Timestamp at_time) {
|
||||
}
|
||||
RTC_CHECK(packet);
|
||||
RTC_DCHECK(!packet->removed);
|
||||
receiver = routing_[packet->receiver_id];
|
||||
receiver = routing_[packet->packet.dest_endpoint_id];
|
||||
packet->removed = true;
|
||||
}
|
||||
// We don't want to keep the lock here. Otherwise we would get a deadlock if
|
||||
// the receiver tries to push a new packet.
|
||||
receiver->DeliverPacket(packet->packet_data, packet->receiver_id,
|
||||
Timestamp::us(delivery_info.receive_time_us));
|
||||
packet->packet.arrival_time = Timestamp::us(delivery_info.receive_time_us);
|
||||
receiver->OnPacketReceived(std::move(packet->packet));
|
||||
{
|
||||
rtc::CritScope crit(&crit_sect_);
|
||||
while (!packets_.empty() && packets_.front().removed) {
|
||||
@ -110,16 +106,16 @@ void NetworkNode::Process(Timestamp at_time) {
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkNode::Route(int64_t receiver_id,
|
||||
void NetworkNode::Route(uint64_t receiver_id,
|
||||
std::vector<NetworkNode*> nodes,
|
||||
NetworkReceiverInterface* receiver) {
|
||||
EmulatedNetworkReceiverInterface* receiver) {
|
||||
RTC_CHECK(!nodes.empty());
|
||||
for (size_t i = 0; i + 1 < nodes.size(); ++i)
|
||||
nodes[i]->SetRoute(receiver_id, nodes[i + 1]);
|
||||
nodes.back()->SetRoute(receiver_id, receiver);
|
||||
}
|
||||
|
||||
void NetworkNode::ClearRoute(int64_t receiver_id,
|
||||
void NetworkNode::ClearRoute(uint64_t receiver_id,
|
||||
std::vector<NetworkNode*> nodes) {
|
||||
for (NetworkNode* node : nodes)
|
||||
node->ClearRoute(receiver_id);
|
||||
@ -191,7 +187,9 @@ bool NetworkNodeTransport::SendRtp(const uint8_t* packet,
|
||||
rtc::CopyOnWriteBuffer buffer(packet, length,
|
||||
length + packet_overhead_.bytes());
|
||||
buffer.SetSize(length + packet_overhead_.bytes());
|
||||
send_net_->DeliverPacket(buffer, receiver_id_, send_time);
|
||||
send_net_->OnPacketReceived(EmulatedIpPacket(
|
||||
rtc::SocketAddress() /*from*/, rtc::SocketAddress() /*to*/, receiver_id_,
|
||||
buffer, send_time));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -202,7 +200,9 @@ bool NetworkNodeTransport::SendRtcp(const uint8_t* packet, size_t length) {
|
||||
buffer.SetSize(length + packet_overhead_.bytes());
|
||||
if (!send_net_)
|
||||
return false;
|
||||
send_net_->DeliverPacket(buffer, receiver_id_, send_time);
|
||||
send_net_->OnPacketReceived(EmulatedIpPacket(
|
||||
rtc::SocketAddress() /*from*/, rtc::SocketAddress() /*to*/, receiver_id_,
|
||||
buffer, send_time));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -223,7 +223,7 @@ void NetworkNodeTransport::Connect(NetworkNode* send_node,
|
||||
transport_name, route);
|
||||
}
|
||||
|
||||
CrossTrafficSource::CrossTrafficSource(NetworkReceiverInterface* target,
|
||||
CrossTrafficSource::CrossTrafficSource(EmulatedNetworkReceiverInterface* target,
|
||||
uint64_t receiver_id,
|
||||
CrossTrafficConfig config)
|
||||
: target_(target),
|
||||
@ -259,8 +259,9 @@ void CrossTrafficSource::Process(Timestamp at_time, TimeDelta delta) {
|
||||
}
|
||||
pending_size_ += TrafficRate() * delta;
|
||||
if (pending_size_ > config_.min_packet_size) {
|
||||
target_->DeliverPacket(rtc::CopyOnWriteBuffer(pending_size_.bytes()),
|
||||
receiver_id_, at_time);
|
||||
target_->OnPacketReceived(EmulatedIpPacket(
|
||||
rtc::SocketAddress() /*from*/, rtc::SocketAddress() /*to*/,
|
||||
receiver_id_, rtc::CopyOnWriteBuffer(pending_size_.bytes()), at_time));
|
||||
pending_size_ = DataSize::Zero();
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,31 +23,22 @@
|
||||
#include "rtc_base/constructormagic.h"
|
||||
#include "rtc_base/copyonwritebuffer.h"
|
||||
#include "test/scenario/column_printer.h"
|
||||
#include "test/scenario/network/network_emulation.h"
|
||||
#include "test/scenario/scenario_config.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
class NetworkReceiverInterface {
|
||||
class NullReceiver : public EmulatedNetworkReceiverInterface {
|
||||
public:
|
||||
virtual void DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) = 0;
|
||||
virtual ~NetworkReceiverInterface() = default;
|
||||
void OnPacketReceived(EmulatedIpPacket packet) override;
|
||||
};
|
||||
class NullReceiver : public NetworkReceiverInterface {
|
||||
public:
|
||||
void DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) override;
|
||||
};
|
||||
class ActionReceiver : public NetworkReceiverInterface {
|
||||
class ActionReceiver : public EmulatedNetworkReceiverInterface {
|
||||
public:
|
||||
explicit ActionReceiver(std::function<void()> action);
|
||||
virtual ~ActionReceiver() = default;
|
||||
void DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) override;
|
||||
|
||||
void OnPacketReceived(EmulatedIpPacket packet) override;
|
||||
|
||||
private:
|
||||
std::function<void()> action_;
|
||||
@ -55,19 +46,17 @@ class ActionReceiver : public NetworkReceiverInterface {
|
||||
|
||||
// NetworkNode represents one link in a simulated network. It is created by a
|
||||
// scenario and can be used when setting up audio and video stream sessions.
|
||||
class NetworkNode : public NetworkReceiverInterface {
|
||||
class NetworkNode : public EmulatedNetworkReceiverInterface {
|
||||
public:
|
||||
~NetworkNode() override;
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(NetworkNode);
|
||||
|
||||
void DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) override;
|
||||
void OnPacketReceived(EmulatedIpPacket packet) override;
|
||||
// Creates a route for the given receiver_id over all the given nodes to the
|
||||
// given receiver.
|
||||
static void Route(int64_t receiver_id,
|
||||
static void Route(uint64_t receiver_id,
|
||||
std::vector<NetworkNode*> nodes,
|
||||
NetworkReceiverInterface* receiver);
|
||||
EmulatedNetworkReceiverInterface* receiver);
|
||||
|
||||
protected:
|
||||
friend class Scenario;
|
||||
@ -76,23 +65,22 @@ class NetworkNode : public NetworkReceiverInterface {
|
||||
|
||||
NetworkNode(NetworkNodeConfig config,
|
||||
std::unique_ptr<NetworkBehaviorInterface> simulation);
|
||||
static void ClearRoute(int64_t receiver_id, std::vector<NetworkNode*> nodes);
|
||||
static void ClearRoute(uint64_t receiver_id, std::vector<NetworkNode*> nodes);
|
||||
void Process(Timestamp at_time);
|
||||
|
||||
private:
|
||||
struct StoredPacket {
|
||||
rtc::CopyOnWriteBuffer packet_data;
|
||||
uint64_t receiver_id;
|
||||
EmulatedIpPacket packet;
|
||||
uint64_t id;
|
||||
bool removed;
|
||||
};
|
||||
void SetRoute(uint64_t receiver, NetworkReceiverInterface* node);
|
||||
void SetRoute(uint64_t receiver, EmulatedNetworkReceiverInterface* node);
|
||||
void ClearRoute(uint64_t receiver_id);
|
||||
rtc::CriticalSection crit_sect_;
|
||||
size_t packet_overhead_ RTC_GUARDED_BY(crit_sect_);
|
||||
const std::unique_ptr<NetworkBehaviorInterface> behavior_
|
||||
RTC_GUARDED_BY(crit_sect_);
|
||||
std::map<uint64_t, NetworkReceiverInterface*> routing_
|
||||
std::map<uint64_t, EmulatedNetworkReceiverInterface*> routing_
|
||||
RTC_GUARDED_BY(crit_sect_);
|
||||
std::deque<StoredPacket> packets_ RTC_GUARDED_BY(crit_sect_);
|
||||
|
||||
@ -155,12 +143,12 @@ class CrossTrafficSource {
|
||||
|
||||
private:
|
||||
friend class Scenario;
|
||||
CrossTrafficSource(NetworkReceiverInterface* target,
|
||||
CrossTrafficSource(EmulatedNetworkReceiverInterface* target,
|
||||
uint64_t receiver_id,
|
||||
CrossTrafficConfig config);
|
||||
void Process(Timestamp at_time, TimeDelta delta);
|
||||
|
||||
NetworkReceiverInterface* const target_;
|
||||
EmulatedNetworkReceiverInterface* const target_;
|
||||
const uint64_t receiver_id_;
|
||||
CrossTrafficConfig config_;
|
||||
webrtc::Random random_;
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
#include "api/audio_codecs/builtin_audio_decoder_factory.h"
|
||||
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
|
||||
#include "rtc_base/flags.h"
|
||||
#include "rtc_base/socketaddress.h"
|
||||
#include "test/scenario/network/network_emulation.h"
|
||||
#include "test/testsupport/fileutils.h"
|
||||
|
||||
WEBRTC_DEFINE_bool(scenario_logs, false, "Save logs from scenario framework.");
|
||||
@ -225,21 +227,23 @@ NetworkNode* Scenario::CreateNetworkNode(
|
||||
void Scenario::TriggerPacketBurst(std::vector<NetworkNode*> over_nodes,
|
||||
size_t num_packets,
|
||||
size_t packet_size) {
|
||||
int64_t route_id = next_route_id_++;
|
||||
uint64_t route_id = next_route_id_++;
|
||||
NetworkNode::Route(route_id, over_nodes, &null_receiver_);
|
||||
for (size_t i = 0; i < num_packets; ++i)
|
||||
over_nodes[0]->DeliverPacket(rtc::CopyOnWriteBuffer(packet_size), route_id,
|
||||
Now());
|
||||
over_nodes[0]->OnPacketReceived(EmulatedIpPacket(
|
||||
rtc::SocketAddress() /*from*/, rtc::SocketAddress(), /*to*/
|
||||
route_id, rtc::CopyOnWriteBuffer(packet_size), Now()));
|
||||
}
|
||||
|
||||
void Scenario::NetworkDelayedAction(std::vector<NetworkNode*> over_nodes,
|
||||
size_t packet_size,
|
||||
std::function<void()> action) {
|
||||
int64_t route_id = next_route_id_++;
|
||||
uint64_t route_id = next_route_id_++;
|
||||
action_receivers_.emplace_back(new ActionReceiver(action));
|
||||
NetworkNode::Route(route_id, over_nodes, action_receivers_.back().get());
|
||||
over_nodes[0]->DeliverPacket(rtc::CopyOnWriteBuffer(packet_size), route_id,
|
||||
Now());
|
||||
over_nodes[0]->OnPacketReceived(EmulatedIpPacket(
|
||||
rtc::SocketAddress() /*from*/, rtc::SocketAddress() /*to*/, route_id,
|
||||
rtc::CopyOnWriteBuffer(packet_size), Now()));
|
||||
}
|
||||
|
||||
CrossTrafficSource* Scenario::CreateCrossTraffic(
|
||||
@ -253,7 +257,7 @@ CrossTrafficSource* Scenario::CreateCrossTraffic(
|
||||
CrossTrafficSource* Scenario::CreateCrossTraffic(
|
||||
std::vector<NetworkNode*> over_nodes,
|
||||
CrossTrafficConfig config) {
|
||||
int64_t route_id = next_route_id_++;
|
||||
uint64_t route_id = next_route_id_++;
|
||||
cross_traffic_sources_.emplace_back(
|
||||
new CrossTrafficSource(over_nodes.front(), route_id, config));
|
||||
CrossTrafficSource* node = cross_traffic_sources_.back().get();
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/socketaddress.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
@ -210,15 +211,13 @@ SimulatedFeedback::SimulatedFeedback(SimulatedTimeClientConfig config,
|
||||
|
||||
// Polls receiver side for a feedback report and sends it to the stream sender
|
||||
// via return_node_,
|
||||
void SimulatedFeedback::DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) {
|
||||
void SimulatedFeedback::OnPacketReceived(EmulatedIpPacket packet) {
|
||||
int64_t sequence_number;
|
||||
memcpy(&sequence_number, packet.cdata(), sizeof(sequence_number));
|
||||
receive_times_.insert({sequence_number, at_time});
|
||||
receive_times_.insert({sequence_number, packet.arrival_time});
|
||||
if (last_feedback_time_.IsInfinite())
|
||||
last_feedback_time_ = at_time;
|
||||
if (at_time >= last_feedback_time_ + config_.feedback.interval) {
|
||||
last_feedback_time_ = packet.arrival_time;
|
||||
if (packet.arrival_time >= last_feedback_time_ + config_.feedback.interval) {
|
||||
SimpleFeedbackReportPacket report;
|
||||
for (; next_feedback_seq_num_ <= sequence_number;
|
||||
++next_feedback_seq_num_) {
|
||||
@ -231,15 +230,17 @@ void SimulatedFeedback::DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
}
|
||||
if (report.receive_times.size() >=
|
||||
RawFeedbackReportPacket::MAX_FEEDBACKS) {
|
||||
return_node_->DeliverPacket(FeedbackToBuffer(report),
|
||||
return_receiver_id_, at_time);
|
||||
return_node_->OnPacketReceived(
|
||||
EmulatedIpPacket(packet.to, packet.from, return_receiver_id_,
|
||||
FeedbackToBuffer(report), packet.arrival_time));
|
||||
report = SimpleFeedbackReportPacket();
|
||||
}
|
||||
}
|
||||
if (!report.receive_times.empty())
|
||||
return_node_->DeliverPacket(FeedbackToBuffer(report), return_receiver_id_,
|
||||
at_time);
|
||||
last_feedback_time_ = at_time;
|
||||
return_node_->OnPacketReceived(
|
||||
EmulatedIpPacket(packet.to, packet.from, return_receiver_id_,
|
||||
FeedbackToBuffer(report), packet.arrival_time));
|
||||
last_feedback_time_ = packet.arrival_time;
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,11 +284,9 @@ SimulatedTimeClient::SimulatedTimeClient(
|
||||
|
||||
// Pulls feedback reports from sender side based on the recieved feedback
|
||||
// packet. Updates congestion controller with the resulting report.
|
||||
void SimulatedTimeClient::DeliverPacket(rtc::CopyOnWriteBuffer raw_buffer,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) {
|
||||
auto report =
|
||||
sender_.PullFeedbackReport(FeedbackFromBuffer(raw_buffer), at_time);
|
||||
void SimulatedTimeClient::OnPacketReceived(EmulatedIpPacket packet) {
|
||||
auto report = sender_.PullFeedbackReport(FeedbackFromBuffer(packet.data),
|
||||
packet.arrival_time);
|
||||
for (PacketResult& feedback : report.packet_feedbacks) {
|
||||
if (packet_log_)
|
||||
fprintf(packet_log_, "%" PRId64 " %" PRId64 " %.3lf %.3lf %.3lf\n",
|
||||
@ -295,7 +294,7 @@ void SimulatedTimeClient::DeliverPacket(rtc::CopyOnWriteBuffer raw_buffer,
|
||||
feedback.sent_packet.size.bytes(),
|
||||
feedback.sent_packet.send_time.seconds<double>(),
|
||||
feedback.receive_time.seconds<double>(),
|
||||
at_time.seconds<double>());
|
||||
packet.arrival_time.seconds<double>());
|
||||
}
|
||||
Update(congestion_controller_->OnTransportPacketsFeedback(report));
|
||||
}
|
||||
@ -329,8 +328,9 @@ void SimulatedTimeClient::CongestionProcess(Timestamp at_time) {
|
||||
void SimulatedTimeClient::PacerProcess(Timestamp at_time) {
|
||||
ProcessFrames(at_time);
|
||||
for (auto to_send : sender_.PaceAndPullSendPackets(at_time)) {
|
||||
sender_.send_node_->DeliverPacket(to_send.data, sender_.send_receiver_id_,
|
||||
at_time);
|
||||
sender_.send_node_->OnPacketReceived(EmulatedIpPacket(
|
||||
rtc::SocketAddress() /*from*/, rtc::SocketAddress() /*to*/,
|
||||
sender_.send_receiver_id_, to_send.data, at_time));
|
||||
Update(congestion_controller_->OnSentPacket(to_send.send_info));
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,14 +47,13 @@ class PacketStream {
|
||||
int64_t budget_ = 0;
|
||||
};
|
||||
|
||||
class SimulatedFeedback : NetworkReceiverInterface {
|
||||
class SimulatedFeedback : EmulatedNetworkReceiverInterface {
|
||||
public:
|
||||
SimulatedFeedback(SimulatedTimeClientConfig config,
|
||||
uint64_t return_receiver_id,
|
||||
NetworkNode* return_node);
|
||||
void DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) override;
|
||||
|
||||
void OnPacketReceived(EmulatedIpPacket packet) override;
|
||||
|
||||
private:
|
||||
friend class SimulatedTimeClient;
|
||||
@ -119,7 +118,7 @@ class SimulatedSender {
|
||||
// unit tests to ensure that congestion controllers behave in a reasonable way.
|
||||
// It does not, however, completely simulate the actual behavior of WebRTC. For
|
||||
// a more accurate simulation, use the real time only CallClient.
|
||||
class SimulatedTimeClient : NetworkReceiverInterface {
|
||||
class SimulatedTimeClient : EmulatedNetworkReceiverInterface {
|
||||
public:
|
||||
SimulatedTimeClient(std::string log_filename,
|
||||
SimulatedTimeClientConfig config,
|
||||
@ -141,9 +140,7 @@ class SimulatedTimeClient : NetworkReceiverInterface {
|
||||
DataRate link_capacity() const;
|
||||
DataRate padding_rate() const;
|
||||
|
||||
void DeliverPacket(rtc::CopyOnWriteBuffer packet,
|
||||
uint64_t receiver,
|
||||
Timestamp at_time) override;
|
||||
void OnPacketReceived(EmulatedIpPacket packet) override;
|
||||
|
||||
private:
|
||||
friend class Scenario;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user