Add first part of the network_tester functionality.
BUG=webrtc:7426
Review-Url: https://codereview.webrtc.org/2779233002
Cr-Commit-Position: refs/heads/master@{#17635}
diff --git a/resources/network_tester/client_config.dat.sha1 b/resources/network_tester/client_config.dat.sha1
new file mode 100644
index 0000000..925be430
--- /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 0000000..925be430
--- /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 5a4c1af..05b7adb 100644
--- a/webrtc/tools/BUILD.gn
+++ b/webrtc/tools/BUILD.gn
@@ -36,6 +36,7 @@
public_deps += [
":event_log_visualizer",
":rtp_analyzer",
+ "network_tester",
]
}
}
@@ -311,6 +312,10 @@
"//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 84bf153..92a068c 100644
--- a/webrtc/tools/DEPS
+++ b/webrtc/tools/DEPS
@@ -10,5 +10,6 @@
"+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 0000000..6cdedf9
--- /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 0000000..2718524
--- /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 <string>
+#include <vector>
+
+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<char>(config_stream)),
+ (std::istreambuf_iterator<char>()));
+ if (config_data.size() > 0) {
+ proto_all_configs_.ParseFromString(config_data);
+ }
+}
+
+ConfigReader::~ConfigReader() = default;
+
+rtc::Optional<ConfigReader::Config> ConfigReader::GetNextConfig() {
+#ifdef WEBRTC_NETWORK_TESTER_PROTO
+ if (proto_config_index_ >= proto_all_configs_.configs_size())
+ return rtc::Optional<Config>();
+ 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>(config);
+#else
+ return rtc::Optional<Config>();
+#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 0000000..62e03da
--- /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 <fstream>
+#include <string>
+
+#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<Config> 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 0000000..57c1eb8
--- /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 0000000..54a23a2
--- /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 0000000..c3bcec5
--- /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 0000000..b7fceda
--- /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 0000000..5d72806
--- /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 <string>
+#include <utility>
+
+#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<QueuedTask>(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<ConfigReader> 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<QueuedTask>(this), (*config).execution_time_ms);
+ return false;
+ } else {
+ packet_sender_->StopSending();
+ return true;
+ }
+ }
+ PacketSender* const packet_sender_;
+ const std::unique_ptr<ConfigReader> 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<rtc::QueuedTask>(new UpdateTestSettingTask(
+ this,
+ std::unique_ptr<ConfigReader>(new ConfigReader(config_file_path_)))));
+ worker_queue_.PostTask(
+ std::unique_ptr<rtc::QueuedTask>(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<size_t>(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 0000000..7a26535
--- /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 <memory>
+#include <string>
+
+#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 0000000..713a974
--- /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<rtc::AsyncPacketSocket>(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<size_t>());
+ 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<size_t> 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<char>::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<size_t>());
+ 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<size_t>());
+ 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 0000000..5dae3ea
--- /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 <array>
+#include <limits>
+#include <memory>
+#include <string>
+#include <utility>
+
+#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<size_t> 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<char, kEthernetMtu> send_data_;
+ std::unique_ptr<cricket::UdpTransport> udp_transport_;
+ std::unique_ptr<PacketSender> packet_sender_;
+};
+
+} // namespace webrtc
+
+#endif // WEBRTC_TOOLS_NETWORK_TESTER_TEST_CONTROLLER_H_