stats() method on EmulatedEndpoint has to be called from network emulation internal task queue and user has no access to that task queue, so user can't call this method. Because of that remove it from public API and keep it only on implementation. Bug: webrtc:11756 Change-Id: I2fb7256abe94d6900965512f90c6a53a0708a7b0 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/180880 Reviewed-by: Tommi <tommi@webrtc.org> Commit-Queue: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31867}
579 lines
20 KiB
C++
579 lines
20 KiB
C++
/*
|
|
* 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_NETWORK_NETWORK_EMULATION_H_
|
|
#define TEST_NETWORK_NETWORK_EMULATION_H_
|
|
|
|
#include <cstdint>
|
|
#include <deque>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "absl/types/optional.h"
|
|
#include "api/array_view.h"
|
|
#include "api/test/network_emulation_manager.h"
|
|
#include "api/test/simulated_network.h"
|
|
#include "api/units/timestamp.h"
|
|
#include "rtc_base/copy_on_write_buffer.h"
|
|
#include "rtc_base/network.h"
|
|
#include "rtc_base/network_constants.h"
|
|
#include "rtc_base/socket_address.h"
|
|
#include "rtc_base/synchronization/sequence_checker.h"
|
|
#include "rtc_base/task_queue_for_test.h"
|
|
#include "rtc_base/task_utils/repeating_task.h"
|
|
#include "rtc_base/thread_checker.h"
|
|
#include "system_wrappers/include/clock.h"
|
|
|
|
namespace webrtc {
|
|
|
|
// This class is immutable and so thread safe.
|
|
class EmulatedNetworkOutgoingStatsImpl final
|
|
: public EmulatedNetworkOutgoingStats {
|
|
public:
|
|
EmulatedNetworkOutgoingStatsImpl(int64_t packets_sent,
|
|
DataSize bytes_sent,
|
|
DataSize first_sent_packet_size,
|
|
Timestamp first_packet_sent_time,
|
|
Timestamp last_packet_sent_time)
|
|
: packets_sent_(packets_sent),
|
|
bytes_sent_(bytes_sent),
|
|
first_sent_packet_size_(first_sent_packet_size),
|
|
first_packet_sent_time_(first_packet_sent_time),
|
|
last_packet_sent_time_(last_packet_sent_time) {}
|
|
explicit EmulatedNetworkOutgoingStatsImpl(
|
|
const EmulatedNetworkOutgoingStats& stats)
|
|
: packets_sent_(stats.PacketsSent()),
|
|
bytes_sent_(stats.BytesSent()),
|
|
first_sent_packet_size_(stats.FirstSentPacketSize()),
|
|
first_packet_sent_time_(stats.FirstPacketSentTime()),
|
|
last_packet_sent_time_(stats.LastPacketSentTime()) {}
|
|
~EmulatedNetworkOutgoingStatsImpl() override = default;
|
|
|
|
int64_t PacketsSent() const override { return packets_sent_; }
|
|
|
|
DataSize BytesSent() const override { return bytes_sent_; }
|
|
|
|
DataSize FirstSentPacketSize() const override {
|
|
return first_sent_packet_size_;
|
|
}
|
|
|
|
Timestamp FirstPacketSentTime() const override {
|
|
return first_packet_sent_time_;
|
|
}
|
|
|
|
Timestamp LastPacketSentTime() const override {
|
|
return last_packet_sent_time_;
|
|
}
|
|
|
|
DataRate AverageSendRate() const override;
|
|
|
|
private:
|
|
const int64_t packets_sent_;
|
|
const DataSize bytes_sent_;
|
|
const DataSize first_sent_packet_size_;
|
|
const Timestamp first_packet_sent_time_;
|
|
const Timestamp last_packet_sent_time_;
|
|
};
|
|
|
|
// This class is immutable and so thread safe.
|
|
class EmulatedNetworkIncomingStatsImpl final
|
|
: public EmulatedNetworkIncomingStats {
|
|
public:
|
|
EmulatedNetworkIncomingStatsImpl(int64_t packets_received,
|
|
DataSize bytes_received,
|
|
int64_t packets_dropped,
|
|
DataSize bytes_dropped,
|
|
DataSize first_received_packet_size,
|
|
Timestamp first_packet_received_time,
|
|
Timestamp last_packet_received_time)
|
|
: packets_received_(packets_received),
|
|
bytes_received_(bytes_received),
|
|
packets_dropped_(packets_dropped),
|
|
bytes_dropped_(bytes_dropped),
|
|
first_received_packet_size_(first_received_packet_size),
|
|
first_packet_received_time_(first_packet_received_time),
|
|
last_packet_received_time_(last_packet_received_time) {}
|
|
explicit EmulatedNetworkIncomingStatsImpl(
|
|
const EmulatedNetworkIncomingStats& stats)
|
|
: packets_received_(stats.PacketsReceived()),
|
|
bytes_received_(stats.BytesReceived()),
|
|
packets_dropped_(stats.PacketsDropped()),
|
|
bytes_dropped_(stats.BytesDropped()),
|
|
first_received_packet_size_(stats.FirstReceivedPacketSize()),
|
|
first_packet_received_time_(stats.FirstPacketReceivedTime()),
|
|
last_packet_received_time_(stats.LastPacketReceivedTime()) {}
|
|
~EmulatedNetworkIncomingStatsImpl() override = default;
|
|
|
|
int64_t PacketsReceived() const override { return packets_received_; }
|
|
|
|
DataSize BytesReceived() const override { return bytes_received_; }
|
|
|
|
int64_t PacketsDropped() const override { return packets_dropped_; }
|
|
|
|
DataSize BytesDropped() const override { return bytes_dropped_; }
|
|
|
|
DataSize FirstReceivedPacketSize() const override {
|
|
return first_received_packet_size_;
|
|
}
|
|
|
|
Timestamp FirstPacketReceivedTime() const override {
|
|
return first_packet_received_time_;
|
|
}
|
|
|
|
Timestamp LastPacketReceivedTime() const override {
|
|
return last_packet_received_time_;
|
|
}
|
|
|
|
DataRate AverageReceiveRate() const override;
|
|
|
|
private:
|
|
const int64_t packets_received_;
|
|
const DataSize bytes_received_;
|
|
const int64_t packets_dropped_;
|
|
const DataSize bytes_dropped_;
|
|
const DataSize first_received_packet_size_;
|
|
const Timestamp first_packet_received_time_;
|
|
const Timestamp last_packet_received_time_;
|
|
};
|
|
|
|
// This class is immutable and so is thread safe.
|
|
class EmulatedNetworkStatsImpl final : public EmulatedNetworkStats {
|
|
public:
|
|
EmulatedNetworkStatsImpl(
|
|
std::vector<rtc::IPAddress> local_addresses,
|
|
std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
|
|
outgoing_stats_per_destination,
|
|
std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
|
|
incoming_stats_per_source)
|
|
: local_addresses_(std::move(local_addresses)),
|
|
outgoing_stats_per_destination_(
|
|
std::move(outgoing_stats_per_destination)),
|
|
incoming_stats_per_source_(std::move(incoming_stats_per_source)) {}
|
|
~EmulatedNetworkStatsImpl() override = default;
|
|
|
|
std::vector<rtc::IPAddress> LocalAddresses() const override {
|
|
return local_addresses_;
|
|
}
|
|
|
|
int64_t PacketsSent() const override {
|
|
return GetOverallOutgoingStats()->PacketsSent();
|
|
}
|
|
|
|
DataSize BytesSent() const override {
|
|
return GetOverallOutgoingStats()->BytesSent();
|
|
}
|
|
|
|
DataSize FirstSentPacketSize() const override {
|
|
return GetOverallOutgoingStats()->FirstSentPacketSize();
|
|
}
|
|
|
|
Timestamp FirstPacketSentTime() const override {
|
|
return GetOverallOutgoingStats()->FirstPacketSentTime();
|
|
}
|
|
|
|
Timestamp LastPacketSentTime() const override {
|
|
return GetOverallOutgoingStats()->LastPacketSentTime();
|
|
}
|
|
|
|
DataRate AverageSendRate() const override {
|
|
return GetOverallOutgoingStats()->AverageSendRate();
|
|
}
|
|
|
|
int64_t PacketsReceived() const override {
|
|
return GetOverallIncomingStats()->PacketsReceived();
|
|
}
|
|
|
|
DataSize BytesReceived() const override {
|
|
return GetOverallIncomingStats()->BytesReceived();
|
|
}
|
|
|
|
int64_t PacketsDropped() const override {
|
|
return GetOverallIncomingStats()->PacketsDropped();
|
|
}
|
|
|
|
DataSize BytesDropped() const override {
|
|
return GetOverallIncomingStats()->BytesDropped();
|
|
}
|
|
|
|
DataSize FirstReceivedPacketSize() const override {
|
|
return GetOverallIncomingStats()->FirstReceivedPacketSize();
|
|
}
|
|
|
|
Timestamp FirstPacketReceivedTime() const override {
|
|
return GetOverallIncomingStats()->FirstPacketReceivedTime();
|
|
}
|
|
|
|
Timestamp LastPacketReceivedTime() const override {
|
|
return GetOverallIncomingStats()->LastPacketReceivedTime();
|
|
}
|
|
|
|
DataRate AverageReceiveRate() const override {
|
|
return GetOverallIncomingStats()->AverageReceiveRate();
|
|
}
|
|
|
|
std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
|
|
OutgoingStatsPerDestination() const override;
|
|
|
|
std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
|
|
IncomingStatsPerSource() const override;
|
|
|
|
private:
|
|
std::unique_ptr<EmulatedNetworkOutgoingStats> GetOverallOutgoingStats() const;
|
|
std::unique_ptr<EmulatedNetworkIncomingStats> GetOverallIncomingStats() const;
|
|
|
|
const std::vector<rtc::IPAddress> local_addresses_;
|
|
const std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
|
|
outgoing_stats_per_destination_;
|
|
const std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
|
|
incoming_stats_per_source_;
|
|
};
|
|
|
|
class EmulatedNetworkOutgoingStatsBuilder {
|
|
public:
|
|
EmulatedNetworkOutgoingStatsBuilder();
|
|
|
|
void OnPacketSent(Timestamp sent_time, DataSize packet_size);
|
|
|
|
void AddOutgoingStats(const EmulatedNetworkOutgoingStats& stats);
|
|
|
|
std::unique_ptr<EmulatedNetworkOutgoingStats> Build() const;
|
|
|
|
private:
|
|
SequenceChecker sequence_checker_;
|
|
|
|
int64_t packets_sent_ RTC_GUARDED_BY(sequence_checker_) = 0;
|
|
DataSize bytes_sent_ RTC_GUARDED_BY(sequence_checker_) = DataSize::Zero();
|
|
DataSize first_sent_packet_size_ RTC_GUARDED_BY(sequence_checker_) =
|
|
DataSize::Zero();
|
|
Timestamp first_packet_sent_time_ RTC_GUARDED_BY(sequence_checker_) =
|
|
Timestamp::PlusInfinity();
|
|
Timestamp last_packet_sent_time_ RTC_GUARDED_BY(sequence_checker_) =
|
|
Timestamp::MinusInfinity();
|
|
};
|
|
|
|
class EmulatedNetworkIncomingStatsBuilder {
|
|
public:
|
|
EmulatedNetworkIncomingStatsBuilder();
|
|
|
|
void OnPacketDropped(DataSize packet_size);
|
|
|
|
void OnPacketReceived(Timestamp received_time, DataSize packet_size);
|
|
|
|
// Adds stats collected from another endpoints to the builder.
|
|
void AddIncomingStats(const EmulatedNetworkIncomingStats& stats);
|
|
|
|
std::unique_ptr<EmulatedNetworkIncomingStats> Build() const;
|
|
|
|
private:
|
|
SequenceChecker sequence_checker_;
|
|
|
|
int64_t packets_received_ RTC_GUARDED_BY(sequence_checker_) = 0;
|
|
DataSize bytes_received_ RTC_GUARDED_BY(sequence_checker_) = DataSize::Zero();
|
|
int64_t packets_dropped_ RTC_GUARDED_BY(sequence_checker_) = 0;
|
|
DataSize bytes_dropped_ RTC_GUARDED_BY(sequence_checker_) = DataSize::Zero();
|
|
DataSize first_received_packet_size_ RTC_GUARDED_BY(sequence_checker_) =
|
|
DataSize::Zero();
|
|
Timestamp first_packet_received_time_ RTC_GUARDED_BY(sequence_checker_) =
|
|
Timestamp::PlusInfinity();
|
|
Timestamp last_packet_received_time_ RTC_GUARDED_BY(sequence_checker_) =
|
|
Timestamp::MinusInfinity();
|
|
};
|
|
|
|
// All methods of EmulatedNetworkStatsBuilder have to be used on a single
|
|
// thread. It may be created on another thread.
|
|
class EmulatedNetworkStatsBuilder {
|
|
public:
|
|
EmulatedNetworkStatsBuilder();
|
|
explicit EmulatedNetworkStatsBuilder(rtc::IPAddress local_ip);
|
|
|
|
void OnPacketSent(Timestamp sent_time,
|
|
rtc::IPAddress destination_ip,
|
|
DataSize packet_size);
|
|
|
|
void OnPacketDropped(rtc::IPAddress source_ip, DataSize packet_size);
|
|
|
|
void OnPacketReceived(Timestamp received_time,
|
|
rtc::IPAddress source_ip,
|
|
DataSize packet_size);
|
|
|
|
void AddEmulatedNetworkStats(const EmulatedNetworkStats& stats);
|
|
|
|
std::unique_ptr<EmulatedNetworkStats> Build() const;
|
|
|
|
private:
|
|
SequenceChecker sequence_checker_;
|
|
|
|
std::vector<rtc::IPAddress> local_addresses_
|
|
RTC_GUARDED_BY(sequence_checker_);
|
|
std::map<rtc::IPAddress, EmulatedNetworkOutgoingStatsBuilder>
|
|
outgoing_stats_per_destination_ RTC_GUARDED_BY(sequence_checker_);
|
|
std::map<rtc::IPAddress, EmulatedNetworkIncomingStatsBuilder>
|
|
incoming_stats_per_source_ RTC_GUARDED_BY(sequence_checker_);
|
|
};
|
|
|
|
class LinkEmulation : public EmulatedNetworkReceiverInterface {
|
|
public:
|
|
LinkEmulation(Clock* clock,
|
|
rtc::TaskQueue* task_queue,
|
|
std::unique_ptr<NetworkBehaviorInterface> network_behavior,
|
|
EmulatedNetworkReceiverInterface* receiver)
|
|
: clock_(clock),
|
|
task_queue_(task_queue),
|
|
network_behavior_(std::move(network_behavior)),
|
|
receiver_(receiver) {}
|
|
void OnPacketReceived(EmulatedIpPacket packet) override;
|
|
|
|
private:
|
|
struct StoredPacket {
|
|
uint64_t id;
|
|
EmulatedIpPacket packet;
|
|
bool removed;
|
|
};
|
|
void Process(Timestamp at_time) RTC_RUN_ON(task_queue_);
|
|
|
|
Clock* const clock_;
|
|
rtc::TaskQueue* const task_queue_;
|
|
const std::unique_ptr<NetworkBehaviorInterface> network_behavior_
|
|
RTC_GUARDED_BY(task_queue_);
|
|
EmulatedNetworkReceiverInterface* const receiver_;
|
|
RepeatingTaskHandle process_task_ RTC_GUARDED_BY(task_queue_);
|
|
std::deque<StoredPacket> packets_ RTC_GUARDED_BY(task_queue_);
|
|
uint64_t next_packet_id_ RTC_GUARDED_BY(task_queue_) = 1;
|
|
};
|
|
|
|
class NetworkRouterNode : public EmulatedNetworkReceiverInterface {
|
|
public:
|
|
explicit NetworkRouterNode(rtc::TaskQueue* task_queue);
|
|
|
|
void OnPacketReceived(EmulatedIpPacket packet) override;
|
|
void SetReceiver(const rtc::IPAddress& dest_ip,
|
|
EmulatedNetworkReceiverInterface* receiver);
|
|
void RemoveReceiver(const rtc::IPAddress& dest_ip);
|
|
void SetWatcher(std::function<void(const EmulatedIpPacket&)> watcher);
|
|
void SetFilter(std::function<bool(const EmulatedIpPacket&)> filter);
|
|
|
|
private:
|
|
rtc::TaskQueue* const task_queue_;
|
|
std::map<rtc::IPAddress, EmulatedNetworkReceiverInterface*> routing_
|
|
RTC_GUARDED_BY(task_queue_);
|
|
std::function<void(const EmulatedIpPacket&)> watcher_
|
|
RTC_GUARDED_BY(task_queue_);
|
|
std::function<bool(const EmulatedIpPacket&)> filter_
|
|
RTC_GUARDED_BY(task_queue_);
|
|
};
|
|
|
|
// Represents node in the emulated network. Nodes can be connected with each
|
|
// other to form different networks with different behavior. The behavior of
|
|
// the node itself is determined by a concrete implementation of
|
|
// NetworkBehaviorInterface that is provided on construction.
|
|
class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface {
|
|
public:
|
|
// Creates node based on |network_behavior|. The specified |packet_overhead|
|
|
// is added to the size of each packet in the information provided to
|
|
// |network_behavior|.
|
|
// |task_queue| is used to process packets and to forward the packets when
|
|
// they are ready.
|
|
EmulatedNetworkNode(
|
|
Clock* clock,
|
|
rtc::TaskQueue* task_queue,
|
|
std::unique_ptr<NetworkBehaviorInterface> network_behavior);
|
|
~EmulatedNetworkNode() override;
|
|
RTC_DISALLOW_COPY_AND_ASSIGN(EmulatedNetworkNode);
|
|
|
|
void OnPacketReceived(EmulatedIpPacket packet) override;
|
|
|
|
LinkEmulation* link() { return &link_; }
|
|
NetworkRouterNode* router() { return &router_; }
|
|
|
|
// Creates a route for the given receiver_ip over all the given nodes to the
|
|
// given receiver.
|
|
static void CreateRoute(const rtc::IPAddress& receiver_ip,
|
|
std::vector<EmulatedNetworkNode*> nodes,
|
|
EmulatedNetworkReceiverInterface* receiver);
|
|
static void ClearRoute(const rtc::IPAddress& receiver_ip,
|
|
std::vector<EmulatedNetworkNode*> nodes);
|
|
|
|
private:
|
|
NetworkRouterNode router_;
|
|
LinkEmulation link_;
|
|
};
|
|
|
|
// Represents single network interface on the device.
|
|
// It will be used as sender from socket side to send data to the network and
|
|
// will act as packet receiver from emulated network side to receive packets
|
|
// from other EmulatedNetworkNodes.
|
|
class EmulatedEndpointImpl : public EmulatedEndpoint {
|
|
public:
|
|
EmulatedEndpointImpl(uint64_t id,
|
|
const rtc::IPAddress& ip,
|
|
bool is_enabled,
|
|
rtc::AdapterType type,
|
|
rtc::TaskQueue* task_queue,
|
|
Clock* clock);
|
|
~EmulatedEndpointImpl() override;
|
|
|
|
uint64_t GetId() const;
|
|
|
|
NetworkRouterNode* router() { return &router_; }
|
|
|
|
void SendPacket(const rtc::SocketAddress& from,
|
|
const rtc::SocketAddress& to,
|
|
rtc::CopyOnWriteBuffer packet_data,
|
|
uint16_t application_overhead = 0) override;
|
|
|
|
absl::optional<uint16_t> BindReceiver(
|
|
uint16_t desired_port,
|
|
EmulatedNetworkReceiverInterface* receiver) override;
|
|
void UnbindReceiver(uint16_t port) override;
|
|
|
|
rtc::IPAddress GetPeerLocalAddress() const override;
|
|
|
|
// Will be called to deliver packet into endpoint from network node.
|
|
void OnPacketReceived(EmulatedIpPacket packet) override;
|
|
|
|
void Enable();
|
|
void Disable();
|
|
bool Enabled() const;
|
|
|
|
const rtc::Network& network() const { return *network_.get(); }
|
|
|
|
std::unique_ptr<EmulatedNetworkStats> stats() const;
|
|
|
|
private:
|
|
static constexpr uint16_t kFirstEphemeralPort = 49152;
|
|
uint16_t NextPort() RTC_EXCLUSIVE_LOCKS_REQUIRED(receiver_lock_);
|
|
|
|
rtc::RecursiveCriticalSection receiver_lock_;
|
|
rtc::ThreadChecker enabled_state_checker_;
|
|
|
|
uint64_t id_;
|
|
// Peer's local IP address for this endpoint network interface.
|
|
const rtc::IPAddress peer_local_addr_;
|
|
bool is_enabled_ RTC_GUARDED_BY(enabled_state_checker_);
|
|
const rtc::AdapterType type_;
|
|
Clock* const clock_;
|
|
rtc::TaskQueue* const task_queue_;
|
|
std::unique_ptr<rtc::Network> network_;
|
|
NetworkRouterNode router_;
|
|
|
|
uint16_t next_port_ RTC_GUARDED_BY(receiver_lock_);
|
|
std::map<uint16_t, EmulatedNetworkReceiverInterface*> port_to_receiver_
|
|
RTC_GUARDED_BY(receiver_lock_);
|
|
|
|
EmulatedNetworkStatsBuilder stats_builder_ RTC_GUARDED_BY(task_queue_);
|
|
};
|
|
|
|
class EmulatedRoute {
|
|
public:
|
|
EmulatedRoute(EmulatedEndpointImpl* from,
|
|
std::vector<EmulatedNetworkNode*> via_nodes,
|
|
EmulatedEndpointImpl* to)
|
|
: from(from), via_nodes(std::move(via_nodes)), to(to), active(true) {}
|
|
|
|
EmulatedEndpointImpl* from;
|
|
std::vector<EmulatedNetworkNode*> via_nodes;
|
|
EmulatedEndpointImpl* to;
|
|
bool active;
|
|
};
|
|
|
|
class EndpointsContainer {
|
|
public:
|
|
explicit EndpointsContainer(
|
|
const std::vector<EmulatedEndpointImpl*>& endpoints);
|
|
|
|
EmulatedEndpointImpl* LookupByLocalAddress(
|
|
const rtc::IPAddress& local_ip) const;
|
|
bool HasEndpoint(EmulatedEndpointImpl* endpoint) const;
|
|
// Returns list of networks for enabled endpoints. Caller takes ownership of
|
|
// returned rtc::Network objects.
|
|
std::vector<std::unique_ptr<rtc::Network>> GetEnabledNetworks() const;
|
|
std::vector<EmulatedEndpoint*> endpoints() const;
|
|
std::unique_ptr<EmulatedNetworkStats> GetStats() const;
|
|
|
|
private:
|
|
const std::vector<EmulatedEndpointImpl*> endpoints_;
|
|
};
|
|
|
|
template <typename FakePacketType>
|
|
class FakePacketRoute : public EmulatedNetworkReceiverInterface {
|
|
public:
|
|
FakePacketRoute(EmulatedRoute* route,
|
|
std::function<void(FakePacketType, Timestamp)> action)
|
|
: route_(route),
|
|
action_(std::move(action)),
|
|
send_addr_(route_->from->GetPeerLocalAddress(), 0),
|
|
recv_addr_(route_->to->GetPeerLocalAddress(),
|
|
*route_->to->BindReceiver(0, this)) {}
|
|
|
|
~FakePacketRoute() { route_->to->UnbindReceiver(recv_addr_.port()); }
|
|
|
|
void SendPacket(size_t size, FakePacketType packet) {
|
|
RTC_CHECK_GE(size, sizeof(int));
|
|
sent_.emplace(next_packet_id_, packet);
|
|
rtc::CopyOnWriteBuffer buf(size);
|
|
reinterpret_cast<int*>(buf.data())[0] = next_packet_id_++;
|
|
route_->from->SendPacket(send_addr_, recv_addr_, buf);
|
|
}
|
|
|
|
void OnPacketReceived(EmulatedIpPacket packet) override {
|
|
int packet_id = reinterpret_cast<int*>(packet.data.data())[0];
|
|
action_(std::move(sent_[packet_id]), packet.arrival_time);
|
|
sent_.erase(packet_id);
|
|
}
|
|
|
|
private:
|
|
EmulatedRoute* const route_;
|
|
const std::function<void(FakePacketType, Timestamp)> action_;
|
|
const rtc::SocketAddress send_addr_;
|
|
const rtc::SocketAddress recv_addr_;
|
|
int next_packet_id_ = 0;
|
|
std::map<int, FakePacketType> sent_;
|
|
};
|
|
|
|
template <typename RequestPacketType, typename ResponsePacketType>
|
|
class TwoWayFakeTrafficRoute {
|
|
public:
|
|
class TrafficHandlerInterface {
|
|
public:
|
|
virtual void OnRequest(RequestPacketType, Timestamp) = 0;
|
|
virtual void OnResponse(ResponsePacketType, Timestamp) = 0;
|
|
virtual ~TrafficHandlerInterface() = default;
|
|
};
|
|
TwoWayFakeTrafficRoute(TrafficHandlerInterface* handler,
|
|
EmulatedRoute* send_route,
|
|
EmulatedRoute* ret_route)
|
|
: handler_(handler),
|
|
request_handler_{send_route,
|
|
[&](RequestPacketType packet, Timestamp arrival_time) {
|
|
handler_->OnRequest(std::move(packet), arrival_time);
|
|
}},
|
|
response_handler_{
|
|
ret_route, [&](ResponsePacketType packet, Timestamp arrival_time) {
|
|
handler_->OnResponse(std::move(packet), arrival_time);
|
|
}} {}
|
|
void SendRequest(size_t size, RequestPacketType packet) {
|
|
request_handler_.SendPacket(size, std::move(packet));
|
|
}
|
|
void SendResponse(size_t size, ResponsePacketType packet) {
|
|
response_handler_.SendPacket(size, std::move(packet));
|
|
}
|
|
|
|
private:
|
|
TrafficHandlerInterface* handler_;
|
|
FakePacketRoute<RequestPacketType> request_handler_;
|
|
FakePacketRoute<ResponsePacketType> response_handler_;
|
|
};
|
|
} // namespace webrtc
|
|
|
|
#endif // TEST_NETWORK_NETWORK_EMULATION_H_
|