diff --git a/resources/network_tester/client_config.dat.sha1 b/resources/network_tester/client_config.dat.sha1 new file mode 100644 index 0000000000..925be43053 --- /dev/null +++ b/resources/network_tester/client_config.dat.sha1 @@ -0,0 +1 @@ +8a7265ba397c621574b321a451605ac94f58b1d3 \ No newline at end of file diff --git a/resources/network_tester/server_config.dat.sha1 b/resources/network_tester/server_config.dat.sha1 new file mode 100644 index 0000000000..925be43053 --- /dev/null +++ b/resources/network_tester/server_config.dat.sha1 @@ -0,0 +1 @@ +8a7265ba397c621574b321a451605ac94f58b1d3 \ No newline at end of file diff --git a/webrtc/tools/BUILD.gn b/webrtc/tools/BUILD.gn index 5a4c1af4be..05b7adbf79 100644 --- a/webrtc/tools/BUILD.gn +++ b/webrtc/tools/BUILD.gn @@ -36,6 +36,7 @@ group("tools") { public_deps += [ ":event_log_visualizer", ":rtp_analyzer", + "network_tester", ] } } @@ -311,6 +312,10 @@ if (rtc_include_tests) { "//testing/gtest", ] + if (rtc_enable_protobuf) { + deps += [ "network_tester:network_tester_unittests" ] + } + data = tools_unittests_resources if (is_android) { deps += [ "//testing/android/native_test:native_test_support" ] diff --git a/webrtc/tools/DEPS b/webrtc/tools/DEPS index 84bf153174..92a068cbfd 100644 --- a/webrtc/tools/DEPS +++ b/webrtc/tools/DEPS @@ -10,5 +10,6 @@ include_rules = [ "+webrtc/modules/congestion_controller", "+webrtc/modules/rtp_rtcp", "+webrtc/system_wrappers", + "+webrtc/p2p", ] diff --git a/webrtc/tools/network_tester/BUILD.gn b/webrtc/tools/network_tester/BUILD.gn new file mode 100644 index 0000000000..6cdedf9f7f --- /dev/null +++ b/webrtc/tools/network_tester/BUILD.gn @@ -0,0 +1,93 @@ +# Copyright (c) 2017 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") +import("//third_party/protobuf/proto_library.gni") + +if (rtc_enable_protobuf) { + proto_library("network_tester_config_proto") { + sources = [ + "network_tester_config.proto", + ] + proto_out_dir = "webrtc/tools/network_tester" + } + + proto_library("network_tester_packet_proto") { + sources = [ + "network_tester_packet.proto", + ] + proto_out_dir = "webrtc/tools/network_tester" + } + + rtc_static_library("network_tester") { + sources = [ + "config_reader.cc", + "config_reader.h", + "packet_sender.cc", + "packet_sender.h", + "test_controller.cc", + "test_controller.h", + ] + + defines = [ "WEBRTC_NETWORK_TESTER_PROTO" ] + + deps = [ + ":network_tester_config_proto", + ":network_tester_packet_proto", + "../../base:rtc_task_queue", + "../../p2p", + ] + + if (!build_with_chromium && is_clang) { + # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] + } + } + + network_tester_unittests_resources = [ + "//resources/network_tester/client_config.dat", + "//resources/network_tester/server_config.dat", + ] + + if (is_ios) { + bundle_data("network_tester_unittests_bundle_data") { + testonly = true + sources = network_tester_unittests_resources + outputs = [ + "{{bundle_resources_dir}}/{{source_file_part}}", + ] + } + } + + rtc_source_set("network_tester_unittests") { + sources = [ + "network_tester_unittest.cc", + ] + + testonly = true + deps = [ + ":network_tester", + "//testing/gtest", + "//webrtc/base:rtc_base_tests_utils", + "//webrtc/test:test_support", + ] + + if (is_ios) { + deps += [ ":network_tester_unittests_bundle_data" ] + } + + defines = [ "GTEST_RELATIVE_PATH" ] + + data = network_tester_unittests_resources + + if (!build_with_chromium && is_clang) { + # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] + } + } +} diff --git a/webrtc/tools/network_tester/config_reader.cc b/webrtc/tools/network_tester/config_reader.cc new file mode 100644 index 0000000000..2718524d56 --- /dev/null +++ b/webrtc/tools/network_tester/config_reader.cc @@ -0,0 +1,50 @@ +/* + * Copyright 2017 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 "webrtc/tools/network_tester/config_reader.h" + +#include +#include + +namespace webrtc { + +ConfigReader::ConfigReader(const std::string& config_file_path) + : proto_config_index_(0) { + std::ifstream config_stream(config_file_path, + std::ios_base::in | std::ios_base::binary); + RTC_DCHECK(config_stream.is_open()); + RTC_DCHECK(config_stream.good()); + std::string config_data((std::istreambuf_iterator(config_stream)), + (std::istreambuf_iterator())); + if (config_data.size() > 0) { + proto_all_configs_.ParseFromString(config_data); + } +} + +ConfigReader::~ConfigReader() = default; + +rtc::Optional ConfigReader::GetNextConfig() { +#ifdef WEBRTC_NETWORK_TESTER_PROTO + if (proto_config_index_ >= proto_all_configs_.configs_size()) + return rtc::Optional(); + auto proto_config = proto_all_configs_.configs(proto_config_index_++); + RTC_DCHECK(proto_config.has_packet_send_interval_ms()); + RTC_DCHECK(proto_config.has_packet_size()); + RTC_DCHECK(proto_config.has_execution_time_ms()); + Config config; + config.packet_send_interval_ms = proto_config.packet_send_interval_ms(); + config.packet_size = proto_config.packet_size(); + config.execution_time_ms = proto_config.execution_time_ms(); + return rtc::Optional(config); +#else + return rtc::Optional(); +#endif // WEBRTC_NETWORK_TESTER_PROTO +} + +} // namespace webrtc diff --git a/webrtc/tools/network_tester/config_reader.h b/webrtc/tools/network_tester/config_reader.h new file mode 100644 index 0000000000..62e03da5b8 --- /dev/null +++ b/webrtc/tools/network_tester/config_reader.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017 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 WEBRTC_TOOLS_NETWORK_TESTER_CONFIG_READER_H_ +#define WEBRTC_TOOLS_NETWORK_TESTER_CONFIG_READER_H_ + +#include +#include + +#include "webrtc/base/constructormagic.h" +#include "webrtc/base/optional.h" + +#include "webrtc/base/ignore_wundef.h" + +#ifdef WEBRTC_NETWORK_TESTER_PROTO +RTC_PUSH_IGNORING_WUNDEF() +#include "webrtc/tools/network_tester/network_tester_config.pb.h" +RTC_POP_IGNORING_WUNDEF() +using webrtc::network_tester::config::NetworkTesterAllConfigs; +#else +class NetworkTesterConfigs; +#endif // WEBRTC_NETWORK_TESTER_PROTO + +namespace webrtc { + +class ConfigReader { + public: + struct Config { + int packet_send_interval_ms; + int packet_size; + int execution_time_ms; + }; + explicit ConfigReader(const std::string& config_file_path); + ~ConfigReader(); + + rtc::Optional GetNextConfig(); + + private: + NetworkTesterAllConfigs proto_all_configs_; + int proto_config_index_; + RTC_DISALLOW_COPY_AND_ASSIGN(ConfigReader); +}; + +} // namespace webrtc + +#endif // WEBRTC_TOOLS_NETWORK_TESTER_CONFIG_READER_H_ diff --git a/webrtc/tools/network_tester/create_network_tester_config.py b/webrtc/tools/network_tester/create_network_tester_config.py new file mode 100644 index 0000000000..57c1eb894f --- /dev/null +++ b/webrtc/tools/network_tester/create_network_tester_config.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# Copyright (c) 2017 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 network_tester_config_pb2 + + +def AddConfig(all_configs, + packet_send_interval_ms, + packet_size, + execution_time_ms): + config = all_configs.configs.add() + config.packet_send_interval_ms = packet_send_interval_ms + config.packet_size = packet_size + config.execution_time_ms = execution_time_ms + +def main(): + all_configs = network_tester_config_pb2.NetworkTesterAllConfigs() + AddConfig(all_configs, 10, 50, 200) + AddConfig(all_configs, 10, 100, 200) + with open("network_tester_config.dat", 'wb') as f: + f.write(all_configs.SerializeToString()) + +if __name__ == "__main__": + main() diff --git a/webrtc/tools/network_tester/network_tester_config.proto b/webrtc/tools/network_tester/network_tester_config.proto new file mode 100644 index 0000000000..54a23a2d83 --- /dev/null +++ b/webrtc/tools/network_tester/network_tester_config.proto @@ -0,0 +1,13 @@ +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; +package webrtc.network_tester.config; + +message NetworkTesterConfig { + optional int32 packet_send_interval_ms = 1; + optional float packet_size = 2; + optional int32 execution_time_ms = 3; +} + +message NetworkTesterAllConfigs { + repeated NetworkTesterConfig configs = 1; +} \ No newline at end of file diff --git a/webrtc/tools/network_tester/network_tester_packet.proto b/webrtc/tools/network_tester/network_tester_packet.proto new file mode 100644 index 0000000000..c3bcec5ec7 --- /dev/null +++ b/webrtc/tools/network_tester/network_tester_packet.proto @@ -0,0 +1,18 @@ +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; +package webrtc.network_tester.packet; + +message NetworkTesterPacket { + enum Type { + HAND_SHAKING = 0; + TEST_START = 1; + TEST_DATA = 2; + TEST_DONE = 3; + } + + optional Type type = 1; + optional int64 send_timestamp = 2; + optional int64 arrival_timestamp = 3; + optional int64 sequence_number = 4; + optional int32 packet_size = 5; +} diff --git a/webrtc/tools/network_tester/network_tester_unittest.cc b/webrtc/tools/network_tester/network_tester_unittest.cc new file mode 100644 index 0000000000..b7fcedac22 --- /dev/null +++ b/webrtc/tools/network_tester/network_tester_unittest.cc @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017 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 "webrtc/tools/network_tester/test_controller.h" + +#include "webrtc/base/gunit.h" +#include "webrtc/test/gtest.h" +#include "webrtc/test/testsupport/fileutils.h" + +namespace webrtc { + +TEST(NetworkTesterTest, ServerClient) { + TestController client( + 0, 0, webrtc::test::ResourcePath("network_tester/client_config", "dat")); + TestController server( + 9090, 9090, + webrtc::test::ResourcePath("network_tester/server_config", "dat")); + client.SendConnectTo("127.0.0.1", 9090); + EXPECT_TRUE_WAIT(server.IsTestDone() && client.IsTestDone(), 2000); +} + +} // namespace webrtc diff --git a/webrtc/tools/network_tester/packet_sender.cc b/webrtc/tools/network_tester/packet_sender.cc new file mode 100644 index 0000000000..5d72806398 --- /dev/null +++ b/webrtc/tools/network_tester/packet_sender.cc @@ -0,0 +1,126 @@ +/* + * Copyright 2017 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 "webrtc/tools/network_tester/packet_sender.h" + +#include +#include + +#include "webrtc/base/timeutils.h" +#include "webrtc/tools/network_tester/config_reader.h" +#include "webrtc/tools/network_tester/test_controller.h" + +namespace webrtc { + +namespace { + +class SendPacketTask : public rtc::QueuedTask { + public: + explicit SendPacketTask(PacketSender* packet_sender) + : packet_sender_(packet_sender) {} + + private: + bool Run() override { + if (packet_sender_->IsSending()) { + packet_sender_->SendPacket(); + rtc::TaskQueue::Current()->PostDelayedTask( + std::unique_ptr(this), + packet_sender_->GetSendIntervalMs()); + return false; + } else { + return true; + } + } + PacketSender* const packet_sender_; +}; + +class UpdateTestSettingTask : public rtc::QueuedTask { + public: + UpdateTestSettingTask(PacketSender* packet_sender, + std::unique_ptr config_reader) + : packet_sender_(packet_sender), + config_reader_(std::move(config_reader)) {} + + private: + bool Run() override { + auto config = config_reader_->GetNextConfig(); + if (config) { + packet_sender_->UpdateTestSetting((*config).packet_size, + (*config).packet_send_interval_ms); + rtc::TaskQueue::Current()->PostDelayedTask( + std::unique_ptr(this), (*config).execution_time_ms); + return false; + } else { + packet_sender_->StopSending(); + return true; + } + } + PacketSender* const packet_sender_; + const std::unique_ptr config_reader_; +}; + +} // namespace + +PacketSender::PacketSender(TestController* test_controller, + const std::string& config_file_path) + : worker_queue_("Packet Sender", rtc::TaskQueue::Priority::HIGH), + packet_size_(0), + send_interval_ms_(0), + sequence_number_(0), + sending_(false), + config_file_path_(config_file_path), + test_controller_(test_controller) {} + +PacketSender::~PacketSender() = default; + +void PacketSender::StartSending() { + sending_ = true; + worker_queue_checker_.Detach(); + worker_queue_.PostTask( + std::unique_ptr(new UpdateTestSettingTask( + this, + std::unique_ptr(new ConfigReader(config_file_path_))))); + worker_queue_.PostTask( + std::unique_ptr(new SendPacketTask(this))); +} + +void PacketSender::StopSending() { + RTC_DCHECK_CALLED_SEQUENTIALLY(&worker_queue_checker_); + sending_ = false; + test_controller_->OnTestDone(); +} + +bool PacketSender::IsSending() const { + RTC_DCHECK_CALLED_SEQUENTIALLY(&worker_queue_checker_); + return sending_; +} + +void PacketSender::SendPacket() { + RTC_DCHECK_CALLED_SEQUENTIALLY(&worker_queue_checker_); + NetworkTesterPacket packet; + packet.set_type(NetworkTesterPacket::TEST_DATA); + packet.set_sequence_number(sequence_number_++); + packet.set_send_timestamp(rtc::TimeMicros()); + test_controller_->SendData(packet, rtc::Optional(packet_size_)); +} + +int64_t PacketSender::GetSendIntervalMs() const { + RTC_DCHECK_CALLED_SEQUENTIALLY(&worker_queue_checker_); + return send_interval_ms_; +} + +void PacketSender::UpdateTestSetting(size_t packet_size, + int64_t send_interval_ms) { + RTC_DCHECK_CALLED_SEQUENTIALLY(&worker_queue_checker_); + send_interval_ms_ = send_interval_ms; + packet_size_ = packet_size; +} + +} // namespace webrtc diff --git a/webrtc/tools/network_tester/packet_sender.h b/webrtc/tools/network_tester/packet_sender.h new file mode 100644 index 0000000000..7a26535174 --- /dev/null +++ b/webrtc/tools/network_tester/packet_sender.h @@ -0,0 +1,65 @@ +/* + * Copyright 2017 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 WEBRTC_TOOLS_NETWORK_TESTER_PACKET_SENDER_H_ +#define WEBRTC_TOOLS_NETWORK_TESTER_PACKET_SENDER_H_ + +#include +#include + +#include "webrtc/base/ignore_wundef.h" +#include "webrtc/base/sequenced_task_checker.h" +#include "webrtc/base/task_queue.h" + +#ifdef WEBRTC_NETWORK_TESTER_PROTO +RTC_PUSH_IGNORING_WUNDEF() +#include "webrtc/tools/network_tester/network_tester_packet.pb.h" +RTC_POP_IGNORING_WUNDEF() +using webrtc::network_tester::packet::NetworkTesterPacket; +#else +class NetworkTesterPacket; +#endif // WEBRTC_NETWORK_TESTER_PROTO + +namespace webrtc { + +class TestController; + +class PacketSender { + public: + PacketSender(TestController* test_controller, + const std::string& config_file_path); + ~PacketSender(); + + void StartSending(); + void StopSending(); + bool IsSending() const; + + void SendPacket(); + + int64_t GetSendIntervalMs() const; + void UpdateTestSetting(size_t packet_size, int64_t send_interval_ms); + + private: + rtc::TaskQueue worker_queue_; + rtc::SequencedTaskChecker worker_queue_checker_; + + size_t packet_size_; + int64_t send_interval_ms_; + int64_t sequence_number_; + bool sending_; + const std::string config_file_path_; + TestController* const test_controller_; + + RTC_DISALLOW_COPY_AND_ASSIGN(PacketSender); +}; + +} // namespace webrtc + +#endif // WEBRTC_TOOLS_NETWORK_TESTER_PACKET_SENDER_H_ diff --git a/webrtc/tools/network_tester/test_controller.cc b/webrtc/tools/network_tester/test_controller.cc new file mode 100644 index 0000000000..713a974995 --- /dev/null +++ b/webrtc/tools/network_tester/test_controller.cc @@ -0,0 +1,118 @@ +/* + * Copyright 2017 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 "webrtc/tools/network_tester/test_controller.h" + +namespace webrtc { + +TestController::TestController(int min_port, + int max_port, + const std::string& config_file_path) + : config_file_path_(config_file_path), + local_test_done_(false), + remote_test_done_(false) { + RTC_DCHECK_RUN_ON(&test_controller_thread_checker_); + send_data_.fill(42); + packet_sender_checker_.Detach(); + auto socket = + std::unique_ptr(socket_factory_.CreateUdpSocket( + rtc::SocketAddress(rtc::GetAnyIP(AF_INET), 0), min_port, max_port)); + socket->SignalReadPacket.connect(this, &TestController::OnReadPacket); + udp_transport_.reset( + new cricket::UdpTransport("network tester transport", std::move(socket))); +} + +void TestController::SendConnectTo(const std::string& hostname, int port) { + RTC_DCHECK_RUN_ON(&test_controller_thread_checker_); + udp_transport_->SetRemoteAddress(rtc::SocketAddress(hostname, port)); + NetworkTesterPacket packet; + packet.set_type(NetworkTesterPacket::HAND_SHAKING); + SendData(packet, rtc::Optional()); + rtc::CritScope scoped_lock(&local_test_done_lock_); + local_test_done_ = false; + remote_test_done_ = false; +} + +void TestController::Run() { + RTC_DCHECK_RUN_ON(&test_controller_thread_checker_); + rtc::Thread::Current()->ProcessMessages(0); +} + +void TestController::SendData(const NetworkTesterPacket& packet, + rtc::Optional data_size) { + // Can be call from packet_sender or from test_controller thread. + size_t packet_size = packet.ByteSize(); + send_data_[0] = packet_size; + packet.SerializeToArray(&send_data_[1], std::numeric_limits::max()); + if (data_size && *data_size > packet_size) + packet_size = *data_size; + udp_transport_->SendPacket(send_data_.data(), packet_size + 1, + rtc::PacketOptions(), 0); +} + +void TestController::OnTestDone() { + RTC_DCHECK_CALLED_SEQUENTIALLY(&packet_sender_checker_); + NetworkTesterPacket packet; + packet.set_type(NetworkTesterPacket::TEST_DONE); + SendData(packet, rtc::Optional()); + rtc::CritScope scoped_lock(&local_test_done_lock_); + local_test_done_ = true; +} + +bool TestController::IsTestDone() { + RTC_DCHECK_RUN_ON(&test_controller_thread_checker_); + rtc::CritScope scoped_lock(&local_test_done_lock_); + return local_test_done_ && remote_test_done_; +} + +void TestController::OnReadPacket(rtc::AsyncPacketSocket* socket, + const char* data, + size_t len, + const rtc::SocketAddress& remote_addr, + const rtc::PacketTime& packet_time) { + RTC_DCHECK_RUN_ON(&test_controller_thread_checker_); + size_t packet_size = data[0]; + std::string receive_data(&data[1], packet_size); + NetworkTesterPacket packet; + packet.ParseFromString(receive_data); + RTC_CHECK(packet.has_type()); + switch (packet.type()) { + case NetworkTesterPacket::HAND_SHAKING: { + NetworkTesterPacket packet; + packet.set_type(NetworkTesterPacket::TEST_START); + udp_transport_->SetRemoteAddress(remote_addr); + SendData(packet, rtc::Optional()); + packet_sender_.reset(new PacketSender(this, config_file_path_)); + packet_sender_->StartSending(); + rtc::CritScope scoped_lock(&local_test_done_lock_); + local_test_done_ = false; + remote_test_done_ = false; + break; + } + case NetworkTesterPacket::TEST_START: { + packet_sender_.reset(new PacketSender(this, config_file_path_)); + packet_sender_->StartSending(); + break; + } + case NetworkTesterPacket::TEST_DATA: { + packet.set_arrival_timestamp(packet_time.timestamp); + packet.set_packet_size(len); + // log packet + break; + } + case NetworkTesterPacket::TEST_DONE: { + remote_test_done_ = true; + break; + } + default: { RTC_NOTREACHED(); } + } +} + +} // namespace webrtc diff --git a/webrtc/tools/network_tester/test_controller.h b/webrtc/tools/network_tester/test_controller.h new file mode 100644 index 0000000000..5dae3eaf8b --- /dev/null +++ b/webrtc/tools/network_tester/test_controller.h @@ -0,0 +1,75 @@ +/* + * Copyright 2017 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 WEBRTC_TOOLS_NETWORK_TESTER_TEST_CONTROLLER_H_ +#define WEBRTC_TOOLS_NETWORK_TESTER_TEST_CONTROLLER_H_ + +#include +#include +#include +#include +#include + +#include "webrtc/base/ignore_wundef.h" +#include "webrtc/p2p/base/basicpacketsocketfactory.h" +#include "webrtc/p2p/base/udptransport.h" +#include "webrtc/tools/network_tester/packet_sender.h" + +#ifdef WEBRTC_NETWORK_TESTER_PROTO +RTC_PUSH_IGNORING_WUNDEF() +#include "webrtc/tools/network_tester/network_tester_packet.pb.h" +RTC_POP_IGNORING_WUNDEF() +using webrtc::network_tester::packet::NetworkTesterPacket; +#else +class NetworkTesterPacket; +#endif // WEBRTC_NETWORK_TESTER_PROTO + +namespace webrtc { + +constexpr size_t kEthernetMtu = 1500; + +class TestController : public sigslot::has_slots<> { + public: + TestController(int min_port, + int max_port, + const std::string& config_file_path); + + void Run(); + + void SendConnectTo(const std::string& hostname, int port); + + void SendData(const NetworkTesterPacket& packet, + rtc::Optional data_size); + + void OnTestDone(); + + bool IsTestDone(); + + private: + void OnReadPacket(rtc::AsyncPacketSocket* socket, + const char* data, + size_t len, + const rtc::SocketAddress& remote_addr, + const rtc::PacketTime& packet_time); + rtc::ThreadChecker test_controller_thread_checker_; + rtc::SequencedTaskChecker packet_sender_checker_; + rtc::BasicPacketSocketFactory socket_factory_; + const std::string config_file_path_; + rtc::CriticalSection local_test_done_lock_; + bool local_test_done_ GUARDED_BY(local_test_done_lock_); + bool remote_test_done_; + std::array send_data_; + std::unique_ptr udp_transport_; + std::unique_ptr packet_sender_; +}; + +} // namespace webrtc + +#endif // WEBRTC_TOOLS_NETWORK_TESTER_TEST_CONTROLLER_H_