2019-01-04 15:45:01 +01:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2019-07-05 10:48:17 +02:00
|
|
|
#ifndef TEST_NETWORK_NETWORK_EMULATION_H_
|
|
|
|
|
#define TEST_NETWORK_NETWORK_EMULATION_H_
|
2019-01-04 15:45:01 +01:00
|
|
|
|
|
|
|
|
#include <cstdint>
|
2019-07-05 10:48:17 +02:00
|
|
|
#include <deque>
|
2019-01-08 15:41:45 +01:00
|
|
|
#include <map>
|
2019-01-04 15:45:01 +01:00
|
|
|
#include <memory>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <utility>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
#include "absl/types/optional.h"
|
2020-07-23 02:19:02 +02:00
|
|
|
#include "api/array_view.h"
|
2019-04-12 12:17:19 +02:00
|
|
|
#include "api/test/network_emulation_manager.h"
|
2019-01-08 15:41:45 +01:00
|
|
|
#include "api/test/simulated_network.h"
|
2019-01-04 15:45:01 +01:00
|
|
|
#include "api/units/timestamp.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "rtc_base/copy_on_write_buffer.h"
|
2019-03-28 12:11:09 +01:00
|
|
|
#include "rtc_base/network.h"
|
2020-01-23 15:46:45 +01:00
|
|
|
#include "rtc_base/network_constants.h"
|
2019-01-11 09:11:00 -08:00
|
|
|
#include "rtc_base/socket_address.h"
|
2020-07-23 02:19:02 +02:00
|
|
|
#include "rtc_base/synchronization/sequence_checker.h"
|
2019-04-01 14:33:53 +02:00
|
|
|
#include "rtc_base/task_queue_for_test.h"
|
|
|
|
|
#include "rtc_base/task_utils/repeating_task.h"
|
2019-03-28 12:11:09 +01:00
|
|
|
#include "rtc_base/thread_checker.h"
|
2019-01-30 15:26:05 +01:00
|
|
|
#include "system_wrappers/include/clock.h"
|
2019-01-04 15:45:01 +01:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
2019-03-15 15:00:37 +01:00
|
|
|
|
2020-07-31 12:57:24 +02:00
|
|
|
// This class is immutable and so thread safe.
|
|
|
|
|
class EmulatedNetworkOutgoingStatsImpl final
|
|
|
|
|
: public EmulatedNetworkOutgoingStats {
|
2020-07-23 02:19:02 +02:00
|
|
|
public:
|
2020-07-31 12:57:24 +02:00
|
|
|
EmulatedNetworkOutgoingStatsImpl(int64_t packets_sent,
|
|
|
|
|
DataSize bytes_sent,
|
|
|
|
|
DataSize first_sent_packet_size,
|
|
|
|
|
Timestamp first_packet_sent_time,
|
|
|
|
|
Timestamp last_packet_sent_time)
|
2020-07-23 02:19:02 +02:00
|
|
|
: packets_sent_(packets_sent),
|
|
|
|
|
bytes_sent_(bytes_sent),
|
|
|
|
|
first_sent_packet_size_(first_sent_packet_size),
|
|
|
|
|
first_packet_sent_time_(first_packet_sent_time),
|
2020-07-31 12:57:24 +02:00
|
|
|
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;
|
2020-07-23 02:19:02 +02:00
|
|
|
|
|
|
|
|
int64_t PacketsSent() const override { return packets_sent_; }
|
|
|
|
|
|
|
|
|
|
DataSize BytesSent() const override { return bytes_sent_; }
|
|
|
|
|
|
2020-07-31 12:57:24 +02:00
|
|
|
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;
|
|
|
|
|
|
2020-07-23 02:19:02 +02:00
|
|
|
std::vector<rtc::IPAddress> LocalAddresses() const override {
|
|
|
|
|
return local_addresses_;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-31 12:57:24 +02:00
|
|
|
int64_t PacketsSent() const override {
|
|
|
|
|
return GetOverallOutgoingStats()->PacketsSent();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DataSize BytesSent() const override {
|
|
|
|
|
return GetOverallOutgoingStats()->BytesSent();
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-23 02:19:02 +02:00
|
|
|
DataSize FirstSentPacketSize() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallOutgoingStats()->FirstSentPacketSize();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Timestamp FirstPacketSentTime() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallOutgoingStats()->FirstPacketSentTime();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Timestamp LastPacketSentTime() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallOutgoingStats()->LastPacketSentTime();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DataRate AverageSendRate() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallOutgoingStats()->AverageSendRate();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t PacketsReceived() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallIncomingStats()->PacketsReceived();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DataSize BytesReceived() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallIncomingStats()->BytesReceived();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64_t PacketsDropped() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallIncomingStats()->PacketsDropped();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DataSize BytesDropped() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallIncomingStats()->BytesDropped();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DataSize FirstReceivedPacketSize() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallIncomingStats()->FirstReceivedPacketSize();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Timestamp FirstPacketReceivedTime() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallIncomingStats()->FirstPacketReceivedTime();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Timestamp LastPacketReceivedTime() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallIncomingStats()->LastPacketReceivedTime();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DataRate AverageReceiveRate() const override {
|
2020-07-31 12:57:24 +02:00
|
|
|
return GetOverallIncomingStats()->AverageReceiveRate();
|
2020-07-23 02:19:02 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-31 12:57:24 +02:00
|
|
|
std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>>
|
|
|
|
|
OutgoingStatsPerDestination() const override;
|
|
|
|
|
|
|
|
|
|
std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>>
|
|
|
|
|
IncomingStatsPerSource() const override;
|
2020-07-23 02:19:02 +02:00
|
|
|
|
|
|
|
|
private:
|
2020-07-31 12:57:24 +02:00
|
|
|
std::unique_ptr<EmulatedNetworkOutgoingStats> GetOverallOutgoingStats() const;
|
|
|
|
|
std::unique_ptr<EmulatedNetworkIncomingStats> GetOverallIncomingStats() const;
|
2020-07-23 02:19:02 +02:00
|
|
|
|
|
|
|
|
const std::vector<rtc::IPAddress> local_addresses_;
|
2020-07-31 12:57:24 +02:00
|
|
|
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_;
|
|
|
|
|
};
|
2020-07-23 02:19:02 +02:00
|
|
|
|
2020-07-31 12:57:24 +02:00
|
|
|
class EmulatedNetworkOutgoingStatsBuilder {
|
|
|
|
|
public:
|
|
|
|
|
EmulatedNetworkOutgoingStatsBuilder();
|
2020-07-23 02:19:02 +02:00
|
|
|
|
2020-07-31 12:57:24 +02:00
|
|
|
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();
|
2020-07-23 02:19:02 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
2020-07-31 12:57:24 +02:00
|
|
|
void OnPacketSent(Timestamp sent_time,
|
|
|
|
|
rtc::IPAddress destination_ip,
|
|
|
|
|
DataSize packet_size);
|
2020-07-23 02:19:02 +02:00
|
|
|
|
|
|
|
|
void OnPacketDropped(rtc::IPAddress source_ip, DataSize packet_size);
|
|
|
|
|
|
|
|
|
|
void OnPacketReceived(Timestamp received_time,
|
|
|
|
|
rtc::IPAddress source_ip,
|
|
|
|
|
DataSize packet_size);
|
|
|
|
|
|
2020-07-31 12:57:24 +02:00
|
|
|
void AddEmulatedNetworkStats(const EmulatedNetworkStats& stats);
|
2020-07-23 02:19:02 +02:00
|
|
|
|
|
|
|
|
std::unique_ptr<EmulatedNetworkStats> Build() const;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
SequenceChecker sequence_checker_;
|
|
|
|
|
|
|
|
|
|
std::vector<rtc::IPAddress> local_addresses_
|
|
|
|
|
RTC_GUARDED_BY(sequence_checker_);
|
2020-07-31 12:57:24 +02:00
|
|
|
std::map<rtc::IPAddress, EmulatedNetworkOutgoingStatsBuilder>
|
|
|
|
|
outgoing_stats_per_destination_ RTC_GUARDED_BY(sequence_checker_);
|
|
|
|
|
std::map<rtc::IPAddress, EmulatedNetworkIncomingStatsBuilder>
|
2020-07-23 02:19:02 +02:00
|
|
|
incoming_stats_per_source_ RTC_GUARDED_BY(sequence_checker_);
|
|
|
|
|
};
|
2019-01-04 15:45:01 +01:00
|
|
|
|
2019-04-01 18:23:58 +02:00
|
|
|
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;
|
2020-01-03 12:37:56 +01:00
|
|
|
void SetReceiver(const rtc::IPAddress& dest_ip,
|
2019-04-01 18:23:58 +02:00
|
|
|
EmulatedNetworkReceiverInterface* receiver);
|
2020-01-03 12:37:56 +01:00
|
|
|
void RemoveReceiver(const rtc::IPAddress& dest_ip);
|
2019-08-14 11:31:02 +02:00
|
|
|
void SetWatcher(std::function<void(const EmulatedIpPacket&)> watcher);
|
2020-01-14 14:25:41 +01:00
|
|
|
void SetFilter(std::function<bool(const EmulatedIpPacket&)> filter);
|
2019-04-01 18:23:58 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
rtc::TaskQueue* const task_queue_;
|
|
|
|
|
std::map<rtc::IPAddress, EmulatedNetworkReceiverInterface*> routing_
|
|
|
|
|
RTC_GUARDED_BY(task_queue_);
|
2019-08-14 11:31:02 +02:00
|
|
|
std::function<void(const EmulatedIpPacket&)> watcher_
|
|
|
|
|
RTC_GUARDED_BY(task_queue_);
|
2020-01-14 14:25:41 +01:00
|
|
|
std::function<bool(const EmulatedIpPacket&)> filter_
|
|
|
|
|
RTC_GUARDED_BY(task_queue_);
|
2019-04-01 18:23:58 +02:00
|
|
|
};
|
|
|
|
|
|
2019-01-08 15:41:45 +01:00
|
|
|
// 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|.
|
2019-04-01 14:33:53 +02:00
|
|
|
// |task_queue| is used to process packets and to forward the packets when
|
|
|
|
|
// they are ready.
|
2019-04-01 18:23:58 +02:00
|
|
|
EmulatedNetworkNode(
|
2019-04-01 14:33:53 +02:00
|
|
|
Clock* clock,
|
|
|
|
|
rtc::TaskQueue* task_queue,
|
2019-01-29 15:59:17 +01:00
|
|
|
std::unique_ptr<NetworkBehaviorInterface> network_behavior);
|
2019-01-08 15:41:45 +01:00
|
|
|
~EmulatedNetworkNode() override;
|
|
|
|
|
RTC_DISALLOW_COPY_AND_ASSIGN(EmulatedNetworkNode);
|
|
|
|
|
|
|
|
|
|
void OnPacketReceived(EmulatedIpPacket packet) override;
|
2019-04-01 18:23:58 +02:00
|
|
|
|
|
|
|
|
LinkEmulation* link() { return &link_; }
|
|
|
|
|
NetworkRouterNode* router() { return &router_; }
|
2019-01-08 15:41:45 +01:00
|
|
|
|
2019-04-01 11:01:16 +02:00
|
|
|
// Creates a route for the given receiver_ip over all the given nodes to the
|
2019-01-08 15:41:45 +01:00
|
|
|
// given receiver.
|
2020-01-03 12:37:56 +01:00
|
|
|
static void CreateRoute(const rtc::IPAddress& receiver_ip,
|
2019-01-08 15:41:45 +01:00
|
|
|
std::vector<EmulatedNetworkNode*> nodes,
|
|
|
|
|
EmulatedNetworkReceiverInterface* receiver);
|
2020-01-03 12:37:56 +01:00
|
|
|
static void ClearRoute(const rtc::IPAddress& receiver_ip,
|
2019-01-08 15:41:45 +01:00
|
|
|
std::vector<EmulatedNetworkNode*> nodes);
|
|
|
|
|
|
|
|
|
|
private:
|
2019-04-01 18:23:58 +02:00
|
|
|
NetworkRouterNode router_;
|
|
|
|
|
LinkEmulation link_;
|
2019-01-08 15:41:45 +01:00
|
|
|
};
|
|
|
|
|
|
2019-01-30 15:26:05 +01:00
|
|
|
// 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.
|
2019-12-04 14:26:50 +01:00
|
|
|
class EmulatedEndpointImpl : public EmulatedEndpoint {
|
2019-01-30 15:26:05 +01:00
|
|
|
public:
|
2019-12-04 14:26:50 +01:00
|
|
|
EmulatedEndpointImpl(uint64_t id,
|
|
|
|
|
const rtc::IPAddress& ip,
|
|
|
|
|
bool is_enabled,
|
2020-01-23 15:46:45 +01:00
|
|
|
rtc::AdapterType type,
|
2019-12-04 14:26:50 +01:00
|
|
|
rtc::TaskQueue* task_queue,
|
|
|
|
|
Clock* clock);
|
|
|
|
|
~EmulatedEndpointImpl() override;
|
2019-01-30 15:26:05 +01:00
|
|
|
|
|
|
|
|
uint64_t GetId() const;
|
|
|
|
|
|
2019-04-05 11:19:52 +02:00
|
|
|
NetworkRouterNode* router() { return &router_; }
|
2019-12-04 14:26:50 +01:00
|
|
|
|
2019-01-30 15:26:05 +01:00
|
|
|
void SendPacket(const rtc::SocketAddress& from,
|
|
|
|
|
const rtc::SocketAddress& to,
|
2020-01-17 13:05:54 +01:00
|
|
|
rtc::CopyOnWriteBuffer packet_data,
|
|
|
|
|
uint16_t application_overhead = 0) override;
|
2019-12-04 14:26:50 +01:00
|
|
|
|
2019-01-30 15:26:05 +01:00
|
|
|
absl::optional<uint16_t> BindReceiver(
|
|
|
|
|
uint16_t desired_port,
|
2019-12-04 14:26:50 +01:00
|
|
|
EmulatedNetworkReceiverInterface* receiver) override;
|
|
|
|
|
void UnbindReceiver(uint16_t port) override;
|
2019-01-30 15:26:05 +01:00
|
|
|
|
2019-12-04 14:26:50 +01:00
|
|
|
rtc::IPAddress GetPeerLocalAddress() const override;
|
2019-01-30 15:26:05 +01:00
|
|
|
|
|
|
|
|
// Will be called to deliver packet into endpoint from network node.
|
|
|
|
|
void OnPacketReceived(EmulatedIpPacket packet) override;
|
|
|
|
|
|
2019-03-28 12:11:09 +01:00
|
|
|
void Enable();
|
|
|
|
|
void Disable();
|
|
|
|
|
bool Enabled() const;
|
|
|
|
|
|
|
|
|
|
const rtc::Network& network() const { return *network_.get(); }
|
|
|
|
|
|
2020-08-04 11:19:28 +02:00
|
|
|
std::unique_ptr<EmulatedNetworkStats> stats() const;
|
2019-04-12 12:17:19 +02:00
|
|
|
|
2019-01-30 15:26:05 +01:00
|
|
|
private:
|
|
|
|
|
static constexpr uint16_t kFirstEphemeralPort = 49152;
|
|
|
|
|
uint16_t NextPort() RTC_EXCLUSIVE_LOCKS_REQUIRED(receiver_lock_);
|
|
|
|
|
|
2020-07-16 16:16:09 +02:00
|
|
|
rtc::RecursiveCriticalSection receiver_lock_;
|
2019-03-28 12:11:09 +01:00
|
|
|
rtc::ThreadChecker enabled_state_checker_;
|
2019-01-30 15:26:05 +01:00
|
|
|
|
|
|
|
|
uint64_t id_;
|
|
|
|
|
// Peer's local IP address for this endpoint network interface.
|
|
|
|
|
const rtc::IPAddress peer_local_addr_;
|
2019-03-28 12:11:09 +01:00
|
|
|
bool is_enabled_ RTC_GUARDED_BY(enabled_state_checker_);
|
2020-01-23 15:46:45 +01:00
|
|
|
const rtc::AdapterType type_;
|
2019-01-30 15:26:05 +01:00
|
|
|
Clock* const clock_;
|
2019-04-05 11:19:52 +02:00
|
|
|
rtc::TaskQueue* const task_queue_;
|
2019-03-28 12:11:09 +01:00
|
|
|
std::unique_ptr<rtc::Network> network_;
|
2019-04-05 11:19:52 +02:00
|
|
|
NetworkRouterNode router_;
|
2019-01-30 15:26:05 +01:00
|
|
|
|
|
|
|
|
uint16_t next_port_ RTC_GUARDED_BY(receiver_lock_);
|
|
|
|
|
std::map<uint16_t, EmulatedNetworkReceiverInterface*> port_to_receiver_
|
|
|
|
|
RTC_GUARDED_BY(receiver_lock_);
|
2019-04-12 12:17:19 +02:00
|
|
|
|
2020-07-23 02:19:02 +02:00
|
|
|
EmulatedNetworkStatsBuilder stats_builder_ RTC_GUARDED_BY(task_queue_);
|
2019-01-30 15:26:05 +01:00
|
|
|
};
|
|
|
|
|
|
2019-03-12 13:48:32 +01:00
|
|
|
class EmulatedRoute {
|
|
|
|
|
public:
|
2019-12-04 14:26:50 +01:00
|
|
|
EmulatedRoute(EmulatedEndpointImpl* from,
|
2019-03-12 13:48:32 +01:00
|
|
|
std::vector<EmulatedNetworkNode*> via_nodes,
|
2019-12-04 14:26:50 +01:00
|
|
|
EmulatedEndpointImpl* to)
|
2019-03-12 13:48:32 +01:00
|
|
|
: from(from), via_nodes(std::move(via_nodes)), to(to), active(true) {}
|
|
|
|
|
|
2019-12-04 14:26:50 +01:00
|
|
|
EmulatedEndpointImpl* from;
|
2019-03-12 13:48:32 +01:00
|
|
|
std::vector<EmulatedNetworkNode*> via_nodes;
|
2019-12-04 14:26:50 +01:00
|
|
|
EmulatedEndpointImpl* to;
|
2019-03-12 13:48:32 +01:00
|
|
|
bool active;
|
|
|
|
|
};
|
2020-07-21 09:50:11 +02:00
|
|
|
|
2019-03-28 12:11:09 +01:00
|
|
|
class EndpointsContainer {
|
|
|
|
|
public:
|
2019-12-04 14:26:50 +01:00
|
|
|
explicit EndpointsContainer(
|
|
|
|
|
const std::vector<EmulatedEndpointImpl*>& endpoints);
|
2019-03-28 12:11:09 +01:00
|
|
|
|
2019-12-04 14:26:50 +01:00
|
|
|
EmulatedEndpointImpl* LookupByLocalAddress(
|
|
|
|
|
const rtc::IPAddress& local_ip) const;
|
|
|
|
|
bool HasEndpoint(EmulatedEndpointImpl* endpoint) const;
|
2019-03-28 12:11:09 +01:00
|
|
|
// Returns list of networks for enabled endpoints. Caller takes ownership of
|
|
|
|
|
// returned rtc::Network objects.
|
|
|
|
|
std::vector<std::unique_ptr<rtc::Network>> GetEnabledNetworks() const;
|
2020-07-28 13:45:16 +02:00
|
|
|
std::vector<EmulatedEndpoint*> endpoints() const;
|
2020-07-23 02:19:02 +02:00
|
|
|
std::unique_ptr<EmulatedNetworkStats> GetStats() const;
|
2019-03-28 12:11:09 +01:00
|
|
|
|
|
|
|
|
private:
|
2019-12-04 14:26:50 +01:00
|
|
|
const std::vector<EmulatedEndpointImpl*> endpoints_;
|
2019-03-28 12:11:09 +01:00
|
|
|
};
|
|
|
|
|
|
2019-06-07 13:06:00 +02:00
|
|
|
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)) {}
|
|
|
|
|
|
2019-10-11 17:00:39 +02:00
|
|
|
~FakePacketRoute() { route_->to->UnbindReceiver(recv_addr_.port()); }
|
|
|
|
|
|
2019-06-07 13:06:00 +02:00
|
|
|
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_;
|
|
|
|
|
};
|
2019-01-04 15:45:01 +01:00
|
|
|
} // namespace webrtc
|
|
|
|
|
|
2019-07-05 10:48:17 +02:00
|
|
|
#endif // TEST_NETWORK_NETWORK_EMULATION_H_
|