Exposing more features in the network emulation manager API.

Bug: webrtc:9883
Change-Id: I2a687b46e3374db0dd08b0c02dfea1482e6fb89f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/161229
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30024}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index 51ae6e5..eba1f04 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -420,6 +420,7 @@
     ]
   }
 
+  # TODO(srte): Move to network_emulation sub directory.
   rtc_library("create_network_emulation_manager") {
     visibility = [ "*" ]
     testonly = true
@@ -541,6 +542,7 @@
   ]
 }
 
+# TODO(srte): Move to network_emulation sub directory.
 rtc_source_set("simulated_network_api") {
   visibility = [ "*" ]
   sources = [
@@ -553,14 +555,18 @@
   ]
 }
 
+# TODO(srte): Move to network_emulation sub directory.
 rtc_source_set("network_emulation_manager_api") {
   visibility = [ "*" ]
   sources = [
+    "test/network_emulation_manager.cc",
     "test/network_emulation_manager.h",
   ]
   deps = [
     ":simulated_network_api",
+    "../call:simulated_network",
     "../rtc_base",
+    "test/network_emulation",
     "units:data_rate",
     "units:data_size",
     "units:timestamp",
diff --git a/api/test/network_emulation/BUILD.gn b/api/test/network_emulation/BUILD.gn
new file mode 100644
index 0000000..5fda1e2
--- /dev/null
+++ b/api/test/network_emulation/BUILD.gn
@@ -0,0 +1,28 @@
+# Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS.  All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+import("../../../webrtc.gni")
+
+rtc_library("network_emulation") {
+  visibility = [ "*" ]
+
+  sources = [
+    "network_emulation_interfaces.cc",
+    "network_emulation_interfaces.h",
+  ]
+
+  deps = [
+    "../../../rtc_base",
+    "../../../rtc_base:checks",
+    "../../../rtc_base:rtc_base_approved",
+    "../../units:data_rate",
+    "../../units:data_size",
+    "../../units:timestamp",
+    "//third_party/abseil-cpp/absl/types:optional",
+  ]
+}
diff --git a/api/test/network_emulation/DEPS b/api/test/network_emulation/DEPS
new file mode 100644
index 0000000..0cf1288
--- /dev/null
+++ b/api/test/network_emulation/DEPS
@@ -0,0 +1,7 @@
+specific_include_rules = {
+  ".*": [
+    "+rtc_base/socket_address.h",
+    "+rtc_base/ip_address.h",
+    "+rtc_base/copy_on_write_buffer.h",
+  ],
+}
diff --git a/api/test/network_emulation/network_emulation_interfaces.cc b/api/test/network_emulation/network_emulation_interfaces.cc
new file mode 100644
index 0000000..50f8bed
--- /dev/null
+++ b/api/test/network_emulation/network_emulation_interfaces.cc
@@ -0,0 +1,32 @@
+/*
+ *  Copyright (c) 2019 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 "api/test/network_emulation/network_emulation_interfaces.h"
+
+namespace webrtc {
+
+namespace {
+constexpr size_t kIPv4HeaderSize = 20;
+constexpr size_t kIPv6HeaderSize = 40;
+}  // namespace
+
+EmulatedIpPacket::EmulatedIpPacket(const rtc::SocketAddress& from,
+                                   const rtc::SocketAddress& to,
+                                   rtc::CopyOnWriteBuffer data,
+                                   Timestamp arrival_time)
+    : from(from),
+      to(to),
+      data(data),
+      ip_header_size((to.family() == AF_INET) ? kIPv4HeaderSize
+                                              : kIPv6HeaderSize),
+      arrival_time(arrival_time) {
+  RTC_DCHECK(to.family() == AF_INET || to.family() == AF_INET6);
+}
+
+}  // namespace webrtc
diff --git a/api/test/network_emulation/network_emulation_interfaces.h b/api/test/network_emulation/network_emulation_interfaces.h
new file mode 100644
index 0000000..35ebabc
--- /dev/null
+++ b/api/test/network_emulation/network_emulation_interfaces.h
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (c) 2019 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 API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_
+#define API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_
+
+#include "absl/types/optional.h"
+#include "api/units/data_rate.h"
+#include "api/units/data_size.h"
+#include "api/units/timestamp.h"
+#include "rtc_base/copy_on_write_buffer.h"
+#include "rtc_base/ip_address.h"
+#include "rtc_base/socket_address.h"
+
+namespace webrtc {
+
+struct EmulatedIpPacket {
+ public:
+  static constexpr int kUdpHeaderSize = 8;
+
+  EmulatedIpPacket(const rtc::SocketAddress& from,
+                   const rtc::SocketAddress& to,
+                   rtc::CopyOnWriteBuffer data,
+                   Timestamp arrival_time);
+  ~EmulatedIpPacket() = default;
+  // This object is not copyable or assignable.
+  EmulatedIpPacket(const EmulatedIpPacket&) = delete;
+  EmulatedIpPacket& operator=(const EmulatedIpPacket&) = delete;
+  // This object is only moveable.
+  EmulatedIpPacket(EmulatedIpPacket&&) = default;
+  EmulatedIpPacket& operator=(EmulatedIpPacket&&) = default;
+
+  size_t size() const { return data.size(); }
+  const uint8_t* cdata() const { return data.cdata(); }
+
+  size_t ip_packet_size() const {
+    return size() + kUdpHeaderSize + ip_header_size;
+  }
+  rtc::SocketAddress from;
+  rtc::SocketAddress to;
+  // Holds the UDP payload.
+  rtc::CopyOnWriteBuffer data;
+  int ip_header_size;
+  Timestamp arrival_time;
+};
+
+// Interface for handling IP packets from an emulated network. This is used with
+// EmulatedEndpoint to receive packets on a specific port.
+class EmulatedNetworkReceiverInterface {
+ public:
+  virtual ~EmulatedNetworkReceiverInterface() = default;
+
+  virtual void OnPacketReceived(EmulatedIpPacket packet) = 0;
+};
+
+struct EmulatedNetworkStats {
+  int64_t packets_sent = 0;
+  DataSize bytes_sent = DataSize::Zero();
+  // Total amount of packets received with or without destination.
+  int64_t packets_received = 0;
+  // Total amount of bytes in received packets.
+  DataSize bytes_received = DataSize::Zero();
+  // Total amount of packets that were received, but no destination was found.
+  int64_t packets_dropped = 0;
+  // Total amount of bytes in dropped packets.
+  DataSize bytes_dropped = DataSize::Zero();
+
+  DataSize first_received_packet_size = DataSize::Zero();
+  DataSize first_sent_packet_size = DataSize::Zero();
+
+  Timestamp first_packet_sent_time = Timestamp::PlusInfinity();
+  Timestamp last_packet_sent_time = Timestamp::PlusInfinity();
+  Timestamp first_packet_received_time = Timestamp::PlusInfinity();
+  Timestamp last_packet_received_time = Timestamp::PlusInfinity();
+
+  DataRate AverageSendRate() const {
+    RTC_DCHECK_GE(packets_sent, 2);
+    return (bytes_sent - first_sent_packet_size) /
+           (last_packet_sent_time - first_packet_sent_time);
+  }
+  DataRate AverageReceiveRate() const {
+    RTC_DCHECK_GE(packets_received, 2);
+    return (bytes_received - first_received_packet_size) /
+           (last_packet_received_time - first_packet_received_time);
+  }
+};
+
+// EmulatedEndpoint is an abstraction for network interface on device. Instances
+// of this are created by NetworkEmulationManager::CreateEndpoint.
+class EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
+ public:
+  // Send packet into network.
+  // |from| will be used to set source address for the packet in destination
+  // socket.
+  // |to| will be used for routing verification and picking right socket by port
+  // on destination endpoint.
+  virtual void SendPacket(const rtc::SocketAddress& from,
+                          const rtc::SocketAddress& to,
+                          rtc::CopyOnWriteBuffer packet_data) = 0;
+
+  // Binds receiver to this endpoint to send and receive data.
+  // |desired_port| is a port that should be used. If it is equal to 0,
+  // endpoint will pick the first available port starting from
+  // |kFirstEphemeralPort|.
+  //
+  // Returns the port, that should be used (it will be equals to desired, if
+  // |desired_port| != 0 and is free or will be the one, selected by endpoint)
+  // or absl::nullopt if desired_port in used. Also fails if there are no more
+  // free ports to bind to.
+  virtual absl::optional<uint16_t> BindReceiver(
+      uint16_t desired_port,
+      EmulatedNetworkReceiverInterface* receiver) = 0;
+  virtual void UnbindReceiver(uint16_t port) = 0;
+  virtual rtc::IPAddress GetPeerLocalAddress() const = 0;
+
+  virtual EmulatedNetworkStats stats() = 0;
+
+ private:
+  // Ensure that there can be no other subclass than EmulatedEndpointImpl. This
+  // means that it's always safe to downcast EmulatedEndpoint instances to
+  // EmulatedEndpointImpl.
+  friend class EmulatedEndpointImpl;
+  EmulatedEndpoint() = default;
+};
+
+// Simulates a TCP connection, this roughly implements the Reno algorithm. In
+// difference from TCP this only support sending messages with a fixed length,
+// no streaming. This is useful to simulate signaling and cross traffic using
+// message based protocols such as HTTP. It differs from UDP messages in that
+// they are guranteed to be delivered eventually, even on lossy networks.
+class TcpMessageRoute {
+ public:
+  // Sends a TCP message of the given |size| over the route, |on_received| is
+  // called when the message has been delivered. Note that the connection
+  // parameters are reset iff there's no currently pending message on the route.
+  virtual void SendMessage(size_t size, std::function<void()> on_received) = 0;
+
+ protected:
+  ~TcpMessageRoute() = default;
+};
+}  // namespace webrtc
+
+#endif  // API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_
diff --git a/api/test/network_emulation_manager.cc b/api/test/network_emulation_manager.cc
new file mode 100644
index 0000000..e23c09b
--- /dev/null
+++ b/api/test/network_emulation_manager.cc
@@ -0,0 +1,59 @@
+/*
+ *  Copyright (c) 2019 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 <utility>
+
+#include "api/test/network_emulation_manager.h"
+#include "call/simulated_network.h"
+
+namespace webrtc {
+
+NetworkEmulationManager::SimulatedNetworkNode::Builder&
+NetworkEmulationManager::SimulatedNetworkNode::Builder::config(
+    BuiltInNetworkBehaviorConfig config) {
+  config_ = config;
+  return *this;
+}
+
+NetworkEmulationManager::SimulatedNetworkNode::Builder&
+NetworkEmulationManager::SimulatedNetworkNode::Builder::delay_ms(
+    int queue_delay_ms) {
+  config_.queue_delay_ms = queue_delay_ms;
+  return *this;
+}
+
+NetworkEmulationManager::SimulatedNetworkNode::Builder&
+NetworkEmulationManager::SimulatedNetworkNode::Builder::capacity_kbps(
+    int link_capacity_kbps) {
+  config_.link_capacity_kbps = link_capacity_kbps;
+  return *this;
+}
+
+NetworkEmulationManager::SimulatedNetworkNode::Builder&
+NetworkEmulationManager::SimulatedNetworkNode::Builder::capacity_Mbps(
+    int link_capacity_Mbps) {
+  config_.link_capacity_kbps = link_capacity_Mbps * 1000;
+  return *this;
+}
+
+NetworkEmulationManager::SimulatedNetworkNode::Builder&
+NetworkEmulationManager::SimulatedNetworkNode::Builder::loss(double loss_rate) {
+  config_.loss_percent = std::round(loss_rate * 100);
+  return *this;
+}
+
+NetworkEmulationManager::SimulatedNetworkNode
+NetworkEmulationManager::SimulatedNetworkNode::Builder::Build() const {
+  SimulatedNetworkNode res;
+  auto behavior = std::make_unique<SimulatedNetwork>(config_);
+  res.simulation = behavior.get();
+  res.node = net_->CreateEmulatedNode(std::move(behavior));
+  return res;
+}
+}  // namespace webrtc
diff --git a/api/test/network_emulation_manager.h b/api/test/network_emulation_manager.h
index c241cdb..b368aef 100644
--- a/api/test/network_emulation_manager.h
+++ b/api/test/network_emulation_manager.h
@@ -14,9 +14,9 @@
 #include <memory>
 #include <vector>
 
+#include "api/test/network_emulation/network_emulation_interfaces.h"
 #include "api/test/simulated_network.h"
-#include "api/units/data_rate.h"
-#include "api/units/data_size.h"
+
 #include "api/units/timestamp.h"
 #include "rtc_base/network.h"
 #include "rtc_base/thread.h"
@@ -36,8 +36,7 @@
 // Multiple networks can be joined into chain emulating a network path from
 // one peer to another.
 class EmulatedNetworkNode;
-// EmulatedEndpoint is and abstraction for network interface on device.
-class EmulatedEndpoint;
+
 // EmulatedRoute is handle for single route from one network interface on one
 // peer device to another network interface on another peer device.
 class EmulatedRoute;
@@ -54,37 +53,6 @@
   bool start_as_enabled = true;
 };
 
-struct EmulatedNetworkStats {
-  int64_t packets_sent = 0;
-  DataSize bytes_sent = DataSize::Zero();
-  // Total amount of packets received with or without destination.
-  int64_t packets_received = 0;
-  // Total amount of bytes in received packets.
-  DataSize bytes_received = DataSize::Zero();
-  // Total amount of packets that were received, but no destination was found.
-  int64_t packets_dropped = 0;
-  // Total amount of bytes in dropped packets.
-  DataSize bytes_dropped = DataSize::Zero();
-
-  DataSize first_received_packet_size = DataSize::Zero();
-  DataSize first_sent_packet_size = DataSize::Zero();
-
-  Timestamp first_packet_sent_time = Timestamp::PlusInfinity();
-  Timestamp last_packet_sent_time = Timestamp::PlusInfinity();
-  Timestamp first_packet_received_time = Timestamp::PlusInfinity();
-  Timestamp last_packet_received_time = Timestamp::PlusInfinity();
-
-  DataRate AverageSendRate() const {
-    RTC_DCHECK_GE(packets_sent, 2);
-    return (bytes_sent - first_sent_packet_size) /
-           (last_packet_sent_time - first_packet_sent_time);
-  }
-  DataRate AverageReceiveRate() const {
-    RTC_DCHECK_GE(packets_received, 2);
-    return (bytes_received - first_received_packet_size) /
-           (last_packet_received_time - first_packet_received_time);
-  }
-};
 
 // Provide interface to obtain all required objects to inject network emulation
 // layer into PeerConnection. Also contains information about network interfaces
@@ -106,6 +74,30 @@
 // and will be deleted when manager will be deleted.
 class NetworkEmulationManager {
  public:
+  // Helper struct to simplify creation of simulated network behaviors. Contains
+  // non-owning pointers as the underlying instances are owned by the manager.
+  struct SimulatedNetworkNode {
+    SimulatedNetworkInterface* simulation;
+    EmulatedNetworkNode* node;
+
+    class Builder {
+     public:
+      explicit Builder(NetworkEmulationManager* net) : net_(net) {}
+      Builder(const Builder&) = default;
+      // Sets the config state, note that this will replace any previously set
+      // values.
+      Builder& config(BuiltInNetworkBehaviorConfig config);
+      Builder& delay_ms(int queue_delay_ms);
+      Builder& capacity_kbps(int link_capacity_kbps);
+      Builder& capacity_Mbps(int link_capacity_Mbps);
+      Builder& loss(double loss_rate);
+      SimulatedNetworkNode Build() const;
+
+     private:
+      NetworkEmulationManager* const net_;
+      BuiltInNetworkBehaviorConfig config_;
+    };
+  };
   virtual ~NetworkEmulationManager() = default;
 
   // Creates an emulated network node, which represents single network in
@@ -115,6 +107,8 @@
   virtual EmulatedNetworkNode* CreateEmulatedNode(
       std::unique_ptr<NetworkBehaviorInterface> network_behavior) = 0;
 
+  virtual SimulatedNetworkNode::Builder NodeBuilder() = 0;
+
   // Creates an emulated endpoint, which represents single network interface on
   // the peer's device.
   virtual EmulatedEndpoint* CreateEndpoint(EmulatedEndpointConfig config) = 0;
@@ -149,11 +143,25 @@
       EmulatedEndpoint* from,
       const std::vector<EmulatedNetworkNode*>& via_nodes,
       EmulatedEndpoint* to) = 0;
+
+  // Creates a route over the given |via_nodes| creating the required endpoints
+  // in the process. The returned EmulatedRoute pointer can be used in other
+  // calls as a transport route for message or cross traffic.
+  virtual EmulatedRoute* CreateRoute(
+      const std::vector<EmulatedNetworkNode*>& via_nodes) = 0;
+
   // Removes route previously created by CreateRoute(...).
   // Caller mustn't call this function with route, that have been already
   // removed earlier.
   virtual void ClearRoute(EmulatedRoute* route) = 0;
 
+  // Creates a simulated TCP connection using |send_route| for traffic and
+  // |ret_route| for feedback. This can be used to emulate HTTP cross traffic
+  // and to implement realistic reliable signaling over lossy networks.
+  // TODO(srte): Handle clearing of the routes involved.
+  virtual TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route,
+                                          EmulatedRoute* ret_route) = 0;
+
   // Creates EmulatedNetworkManagerInterface which can be used then to inject
   // network emulation layer into PeerConnection. |endpoints| - are available
   // network interfaces for PeerConnection. If endpoint is enabled, it will be
diff --git a/api/test/simulated_network.h b/api/test/simulated_network.h
index 9b20c9c..7612923 100644
--- a/api/test/simulated_network.h
+++ b/api/test/simulated_network.h
@@ -80,6 +80,16 @@
   virtual ~NetworkBehaviorInterface() = default;
 };
 
+// Class simulating a network link. This is a simple and naive solution just
+// faking capacity and adding an extra transport delay in addition to the
+// capacity introduced delay.
+class SimulatedNetworkInterface : public NetworkBehaviorInterface {
+ public:
+  // Sets a new configuration. This won't affect packets already in the pipe.
+  virtual void SetConfig(const BuiltInNetworkBehaviorConfig& config) = 0;
+  virtual void PauseTransmissionUntil(int64_t until_us) = 0;
+};
+
 }  // namespace webrtc
 
 #endif  // API_TEST_SIMULATED_NETWORK_H_
diff --git a/call/simulated_network.cc b/call/simulated_network.cc
index a8c962a..d6a7369 100644
--- a/call/simulated_network.cc
+++ b/call/simulated_network.cc
@@ -79,15 +79,14 @@
   }
 }
 
-SimulatedNetwork::SimulatedNetwork(SimulatedNetwork::Config config,
-                                   uint64_t random_seed)
+SimulatedNetwork::SimulatedNetwork(Config config, uint64_t random_seed)
     : random_(random_seed), bursting_(false) {
   SetConfig(config);
 }
 
 SimulatedNetwork::~SimulatedNetwork() = default;
 
-void SimulatedNetwork::SetConfig(const SimulatedNetwork::Config& config) {
+void SimulatedNetwork::SetConfig(const Config& config) {
   rtc::CritScope crit(&config_lock_);
   config_state_.config = config;  // Shallow copy of the struct.
   double prob_loss = config.loss_percent / 100.0;
diff --git a/call/simulated_network.h b/call/simulated_network.h
index 2e42ddc..fa72762 100644
--- a/call/simulated_network.h
+++ b/call/simulated_network.h
@@ -54,15 +54,15 @@
 // Class simulating a network link. This is a simple and naive solution just
 // faking capacity and adding an extra transport delay in addition to the
 // capacity introduced delay.
-class SimulatedNetwork : public NetworkBehaviorInterface {
+class SimulatedNetwork : public SimulatedNetworkInterface {
  public:
   using Config = BuiltInNetworkBehaviorConfig;
   explicit SimulatedNetwork(Config config, uint64_t random_seed = 1);
   ~SimulatedNetwork() override;
 
   // Sets a new configuration. This won't affect packets already in the pipe.
-  void SetConfig(const Config& config);
-  void PauseTransmissionUntil(int64_t until_us);
+  void SetConfig(const Config& config) override;
+  void PauseTransmissionUntil(int64_t until_us) override;
 
   // NetworkBehaviorInterface
   bool EnqueuePacket(PacketInFlightInfo packet) override;
diff --git a/test/network/BUILD.gn b/test/network/BUILD.gn
index 5cb70b1..852d4b8 100644
--- a/test/network/BUILD.gn
+++ b/test/network/BUILD.gn
@@ -33,8 +33,6 @@
     "network_emulation.h",
     "network_emulation_manager.cc",
     "network_emulation_manager.h",
-    "simulated_network_node.cc",
-    "simulated_network_node.h",
     "traffic_route.cc",
     "traffic_route.h",
   ]
diff --git a/test/network/cross_traffic.cc b/test/network/cross_traffic.cc
index 07ca171..972e89f 100644
--- a/test/network/cross_traffic.cc
+++ b/test/network/cross_traffic.cc
@@ -116,10 +116,10 @@
       32);
 }
 
-TcpMessageRoute::TcpMessageRoute(Clock* clock,
-                                 TaskQueueBase* task_queue,
-                                 EmulatedRoute* send_route,
-                                 EmulatedRoute* ret_route)
+TcpMessageRouteImpl::TcpMessageRouteImpl(Clock* clock,
+                                         TaskQueueBase* task_queue,
+                                         EmulatedRoute* send_route,
+                                         EmulatedRoute* ret_route)
     : clock_(clock),
       task_queue_(task_queue),
       request_route_(send_route,
@@ -131,8 +131,8 @@
                         OnResponse(std::move(packet), arrival_time);
                       }) {}
 
-void TcpMessageRoute::SendMessage(size_t size,
-                                  std::function<void()> on_received) {
+void TcpMessageRouteImpl::SendMessage(size_t size,
+                                      std::function<void()> on_received) {
   task_queue_->PostTask(
       ToQueuedTask([this, size, handler = std::move(on_received)] {
         // If we are currently sending a message we won't reset the connection,
@@ -159,7 +159,7 @@
       }));
 }
 
-void TcpMessageRoute::OnRequest(TcpPacket packet_info) {
+void TcpMessageRouteImpl::OnRequest(TcpPacket packet_info) {
   for (auto it = messages_.begin(); it != messages_.end(); ++it) {
     if (it->pending_fragment_ids.count(packet_info.fragment.fragment_id) != 0) {
       it->pending_fragment_ids.erase(packet_info.fragment.fragment_id);
@@ -174,7 +174,7 @@
   response_route_.SendPacket(kAckPacketSize, packet_info);
 }
 
-void TcpMessageRoute::OnResponse(TcpPacket packet_info, Timestamp at_time) {
+void TcpMessageRouteImpl::OnResponse(TcpPacket packet_info, Timestamp at_time) {
   auto it = in_flight_.find(packet_info.sequence_number);
   if (it != in_flight_.end()) {
     last_rtt_ = at_time - packet_info.send_time;
@@ -198,7 +198,7 @@
   SendPackets(at_time);
 }
 
-void TcpMessageRoute::HandleLoss(Timestamp at_time) {
+void TcpMessageRouteImpl::HandleLoss(Timestamp at_time) {
   if (at_time - last_reduction_time_ < last_rtt_)
     return;
   last_reduction_time_ = at_time;
@@ -206,7 +206,7 @@
   cwnd_ = ssthresh_;
 }
 
-void TcpMessageRoute::SendPackets(Timestamp at_time) {
+void TcpMessageRouteImpl::SendPackets(Timestamp at_time) {
   const TimeDelta kPacketTimeout = TimeDelta::seconds(1);
   int cwnd = std::ceil(cwnd_);
   int packets_to_send = std::max(cwnd - static_cast<int>(in_flight_.size()), 0);
@@ -227,7 +227,7 @@
   }
 }
 
-void TcpMessageRoute::HandlePacketTimeout(int seq_num, Timestamp at_time) {
+void TcpMessageRouteImpl::HandlePacketTimeout(int seq_num, Timestamp at_time) {
   auto lost = in_flight_.find(seq_num);
   if (lost != in_flight_.end()) {
     pending_.push_front(lost->second.fragment);
diff --git a/test/network/cross_traffic.h b/test/network/cross_traffic.h
index aba02e1..663881f 100644
--- a/test/network/cross_traffic.h
+++ b/test/network/cross_traffic.h
@@ -92,22 +92,17 @@
   bool sending_ RTC_GUARDED_BY(sequence_checker_) = false;
 };
 
-// Simulates a TCP connection, this roughly implements the Reno algorithm. In
-// difference from TCP this only support sending messages with a fixed length,
-// no streaming. This is useful to simulate signaling and cross traffic using
-// message based protocols such as HTTP. It differs from UDP messages in that
-// they are guranteed to be delivered eventually, even on lossy networks.
-class TcpMessageRoute {
+class TcpMessageRouteImpl final : public TcpMessageRoute {
  public:
-  TcpMessageRoute(Clock* clock,
-                  TaskQueueBase* task_queue,
-                  EmulatedRoute* send_route,
-                  EmulatedRoute* ret_route);
+  TcpMessageRouteImpl(Clock* clock,
+                      TaskQueueBase* task_queue,
+                      EmulatedRoute* send_route,
+                      EmulatedRoute* ret_route);
 
   // Sends a TCP message of the given |size| over the route, |on_received| is
   // called when the message has been delivered. Note that the connection
   // parameters are reset iff there's no currently pending message on the route.
-  void SendMessage(size_t size, std::function<void()> on_received);
+  void SendMessage(size_t size, std::function<void()> on_received) override;
 
  private:
   // Represents a message sent over the route. When all fragments has been
diff --git a/test/network/cross_traffic_unittest.cc b/test/network/cross_traffic_unittest.cc
index 148ad09..52bbd48 100644
--- a/test/network/cross_traffic_unittest.cc
+++ b/test/network/cross_traffic_unittest.cc
@@ -45,8 +45,8 @@
   SimulatedClock clock{0};
   CountingReceiver counter;
   TaskQueueForTest task_queue_;
-  EmulatedEndpoint endpoint{/*id=*/1, rtc::IPAddress(kTestIpAddress),
-                            /*is_enabled=*/true, &task_queue_, &clock};
+  EmulatedEndpointImpl endpoint{/*id=*/1, rtc::IPAddress(kTestIpAddress),
+                                /*is_enabled=*/true, &task_queue_, &clock};
 };
 
 }  // namespace
diff --git a/test/network/emulated_network_manager.cc b/test/network/emulated_network_manager.cc
index 5367a80..9457244 100644
--- a/test/network/emulated_network_manager.cc
+++ b/test/network/emulated_network_manager.cc
@@ -32,7 +32,7 @@
   network_thread_.Start();
 }
 
-void EmulatedNetworkManager::EnableEndpoint(EmulatedEndpoint* endpoint) {
+void EmulatedNetworkManager::EnableEndpoint(EmulatedEndpointImpl* endpoint) {
   RTC_CHECK(endpoints_container_->HasEndpoint(endpoint))
       << "No such interface: " << endpoint->GetPeerLocalAddress().ToString();
   network_thread_.PostTask(RTC_FROM_HERE, [this, endpoint]() {
@@ -41,7 +41,7 @@
   });
 }
 
-void EmulatedNetworkManager::DisableEndpoint(EmulatedEndpoint* endpoint) {
+void EmulatedNetworkManager::DisableEndpoint(EmulatedEndpointImpl* endpoint) {
   RTC_CHECK(endpoints_container_->HasEndpoint(endpoint))
       << "No such interface: " << endpoint->GetPeerLocalAddress().ToString();
   network_thread_.PostTask(RTC_FROM_HERE, [this, endpoint]() {
diff --git a/test/network/emulated_network_manager.h b/test/network/emulated_network_manager.h
index 4e50e662..9cf0eb9 100644
--- a/test/network/emulated_network_manager.h
+++ b/test/network/emulated_network_manager.h
@@ -36,8 +36,8 @@
                          TaskQueueForTest* task_queue,
                          EndpointsContainer* endpoints_container);
 
-  void EnableEndpoint(EmulatedEndpoint* endpoint);
-  void DisableEndpoint(EmulatedEndpoint* endpoint);
+  void EnableEndpoint(EmulatedEndpointImpl* endpoint);
+  void DisableEndpoint(EmulatedEndpointImpl* endpoint);
 
   // NetworkManager interface. All these methods are supposed to be called from
   // the same thread.
diff --git a/test/network/fake_network_socket.h b/test/network/fake_network_socket.h
index 1715f1e..8ac91a0 100644
--- a/test/network/fake_network_socket.h
+++ b/test/network/fake_network_socket.h
@@ -39,7 +39,7 @@
   virtual void WakeUp() = 0;
   virtual void Unregister(SocketIoProcessor* io_processor) = 0;
   // Provides endpoints by IP address.
-  virtual EmulatedEndpoint* GetEndpointNode(const rtc::IPAddress& ip) = 0;
+  virtual EmulatedEndpointImpl* GetEndpointNode(const rtc::IPAddress& ip) = 0;
 };
 
 // Represents a socket, which will operate with emulated network.
@@ -82,7 +82,7 @@
   absl::optional<EmulatedIpPacket> PopFrontPacket();
 
   SocketManager* const socket_manager_;
-  EmulatedEndpoint* endpoint_;
+  EmulatedEndpointImpl* endpoint_;
 
   rtc::SocketAddress local_addr_;
   rtc::SocketAddress remote_addr_;
diff --git a/test/network/fake_network_socket_server.cc b/test/network/fake_network_socket_server.cc
index 9be61c5..a8e3eac 100644
--- a/test/network/fake_network_socket_server.cc
+++ b/test/network/fake_network_socket_server.cc
@@ -29,7 +29,7 @@
   msg_queue_ = nullptr;
 }
 
-EmulatedEndpoint* FakeNetworkSocketServer::GetEndpointNode(
+EmulatedEndpointImpl* FakeNetworkSocketServer::GetEndpointNode(
     const rtc::IPAddress& ip) {
   return endpoints_container_->LookupByLocalAddress(ip);
 }
diff --git a/test/network/fake_network_socket_server.h b/test/network/fake_network_socket_server.h
index 2597779..2421469 100644
--- a/test/network/fake_network_socket_server.h
+++ b/test/network/fake_network_socket_server.h
@@ -38,7 +38,7 @@
                           EndpointsContainer* endpoints_controller);
   ~FakeNetworkSocketServer() override;
 
-  EmulatedEndpoint* GetEndpointNode(const rtc::IPAddress& ip) override;
+  EmulatedEndpointImpl* GetEndpointNode(const rtc::IPAddress& ip) override;
   void Unregister(SocketIoProcessor* io_processor) override;
   void OnMessageQueueDestroyed();
 
diff --git a/test/network/network_emulation.cc b/test/network/network_emulation.cc
index 04ac744..2aabf59f 100644
--- a/test/network/network_emulation.cc
+++ b/test/network/network_emulation.cc
@@ -20,24 +20,6 @@
 
 namespace webrtc {
 
-namespace {
-constexpr size_t kIPv4HeaderSize = 20;
-constexpr size_t kIPv6HeaderSize = 40;
-}  // namespace
-
-EmulatedIpPacket::EmulatedIpPacket(const rtc::SocketAddress& from,
-                                   const rtc::SocketAddress& to,
-                                   rtc::CopyOnWriteBuffer data,
-                                   Timestamp arrival_time)
-    : from(from),
-      to(to),
-      data(data),
-      ip_header_size((to.family() == AF_INET) ? kIPv4HeaderSize
-                                              : kIPv6HeaderSize),
-      arrival_time(arrival_time) {
-  RTC_DCHECK(to.family() == AF_INET || to.family() == AF_INET6);
-}
-
 void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) {
   task_queue_->PostTask([this, packet = std::move(packet)]() mutable {
     RTC_DCHECK_RUN_ON(task_queue_);
@@ -172,11 +154,11 @@
 
 EmulatedNetworkNode::~EmulatedNetworkNode() = default;
 
-EmulatedEndpoint::EmulatedEndpoint(uint64_t id,
-                                   const rtc::IPAddress& ip,
-                                   bool is_enabled,
-                                   rtc::TaskQueue* task_queue,
-                                   Clock* clock)
+EmulatedEndpointImpl::EmulatedEndpointImpl(uint64_t id,
+                                           const rtc::IPAddress& ip,
+                                           bool is_enabled,
+                                           rtc::TaskQueue* task_queue,
+                                           Clock* clock)
     : id_(id),
       peer_local_addr_(ip),
       is_enabled_(is_enabled),
@@ -201,15 +183,15 @@
 
   enabled_state_checker_.Detach();
 }
-EmulatedEndpoint::~EmulatedEndpoint() = default;
+EmulatedEndpointImpl::~EmulatedEndpointImpl() = default;
 
-uint64_t EmulatedEndpoint::GetId() const {
+uint64_t EmulatedEndpointImpl::GetId() const {
   return id_;
 }
 
-void EmulatedEndpoint::SendPacket(const rtc::SocketAddress& from,
-                                  const rtc::SocketAddress& to,
-                                  rtc::CopyOnWriteBuffer packet_data) {
+void EmulatedEndpointImpl::SendPacket(const rtc::SocketAddress& from,
+                                      const rtc::SocketAddress& to,
+                                      rtc::CopyOnWriteBuffer packet_data) {
   RTC_CHECK(from.ipaddr() == peer_local_addr_);
   EmulatedIpPacket packet(from, to, std::move(packet_data),
                           clock_->CurrentTime());
@@ -228,7 +210,7 @@
   });
 }
 
-absl::optional<uint16_t> EmulatedEndpoint::BindReceiver(
+absl::optional<uint16_t> EmulatedEndpointImpl::BindReceiver(
     uint16_t desired_port,
     EmulatedNetworkReceiverInterface* receiver) {
   rtc::CritScope crit(&receiver_lock_);
@@ -259,7 +241,7 @@
   return port;
 }
 
-uint16_t EmulatedEndpoint::NextPort() {
+uint16_t EmulatedEndpointImpl::NextPort() {
   uint16_t out = next_port_;
   if (next_port_ == std::numeric_limits<uint16_t>::max()) {
     next_port_ = kFirstEphemeralPort;
@@ -269,16 +251,16 @@
   return out;
 }
 
-void EmulatedEndpoint::UnbindReceiver(uint16_t port) {
+void EmulatedEndpointImpl::UnbindReceiver(uint16_t port) {
   rtc::CritScope crit(&receiver_lock_);
   port_to_receiver_.erase(port);
 }
 
-rtc::IPAddress EmulatedEndpoint::GetPeerLocalAddress() const {
+rtc::IPAddress EmulatedEndpointImpl::GetPeerLocalAddress() const {
   return peer_local_addr_;
 }
 
-void EmulatedEndpoint::OnPacketReceived(EmulatedIpPacket packet) {
+void EmulatedEndpointImpl::OnPacketReceived(EmulatedIpPacket packet) {
   RTC_DCHECK_RUN_ON(task_queue_);
   RTC_CHECK(packet.to.ipaddr() == peer_local_addr_)
       << "Routing error: wrong destination endpoint. Packet.to.ipaddr()=: "
@@ -303,29 +285,29 @@
   it->second->OnPacketReceived(std::move(packet));
 }
 
-void EmulatedEndpoint::Enable() {
+void EmulatedEndpointImpl::Enable() {
   RTC_DCHECK_RUN_ON(&enabled_state_checker_);
   RTC_CHECK(!is_enabled_);
   is_enabled_ = true;
 }
 
-void EmulatedEndpoint::Disable() {
+void EmulatedEndpointImpl::Disable() {
   RTC_DCHECK_RUN_ON(&enabled_state_checker_);
   RTC_CHECK(is_enabled_);
   is_enabled_ = false;
 }
 
-bool EmulatedEndpoint::Enabled() const {
+bool EmulatedEndpointImpl::Enabled() const {
   RTC_DCHECK_RUN_ON(&enabled_state_checker_);
   return is_enabled_;
 }
 
-EmulatedNetworkStats EmulatedEndpoint::stats() {
+EmulatedNetworkStats EmulatedEndpointImpl::stats() {
   RTC_DCHECK_RUN_ON(task_queue_);
   return stats_;
 }
 
-void EmulatedEndpoint::UpdateReceiveStats(const EmulatedIpPacket& packet) {
+void EmulatedEndpointImpl::UpdateReceiveStats(const EmulatedIpPacket& packet) {
   RTC_DCHECK_RUN_ON(task_queue_);
   Timestamp current_time = clock_->CurrentTime();
   if (stats_.first_packet_received_time.IsInfinite()) {
@@ -339,10 +321,10 @@
 }
 
 EndpointsContainer::EndpointsContainer(
-    const std::vector<EmulatedEndpoint*>& endpoints)
+    const std::vector<EmulatedEndpointImpl*>& endpoints)
     : endpoints_(endpoints) {}
 
-EmulatedEndpoint* EndpointsContainer::LookupByLocalAddress(
+EmulatedEndpointImpl* EndpointsContainer::LookupByLocalAddress(
     const rtc::IPAddress& local_ip) const {
   for (auto* endpoint : endpoints_) {
     rtc::IPAddress peer_local_address = endpoint->GetPeerLocalAddress();
@@ -353,7 +335,7 @@
   RTC_CHECK(false) << "No network found for address" << local_ip.ToString();
 }
 
-bool EndpointsContainer::HasEndpoint(EmulatedEndpoint* endpoint) const {
+bool EndpointsContainer::HasEndpoint(EmulatedEndpointImpl* endpoint) const {
   for (auto* e : endpoints_) {
     if (e->GetId() == endpoint->GetId()) {
       return true;
diff --git a/test/network/network_emulation.h b/test/network/network_emulation.h
index 2051216..68def08 100644
--- a/test/network/network_emulation.h
+++ b/test/network/network_emulation.h
@@ -33,42 +33,6 @@
 
 namespace webrtc {
 
-struct EmulatedIpPacket {
- public:
-  static constexpr int kUdpHeaderSize = 8;
-
-  EmulatedIpPacket(const rtc::SocketAddress& from,
-                   const rtc::SocketAddress& to,
-                   rtc::CopyOnWriteBuffer data,
-                   Timestamp arrival_time);
-  ~EmulatedIpPacket() = default;
-  // This object is not copyable or assignable.
-  EmulatedIpPacket(const EmulatedIpPacket&) = delete;
-  EmulatedIpPacket& operator=(const EmulatedIpPacket&) = delete;
-  // This object is only moveable.
-  EmulatedIpPacket(EmulatedIpPacket&&) = default;
-  EmulatedIpPacket& operator=(EmulatedIpPacket&&) = default;
-
-  size_t size() const { return data.size(); }
-  const uint8_t* cdata() const { return data.cdata(); }
-
-  size_t ip_packet_size() const {
-    return size() + kUdpHeaderSize + ip_header_size;
-  }
-  rtc::SocketAddress from;
-  rtc::SocketAddress to;
-  // Holds the UDP payload.
-  rtc::CopyOnWriteBuffer data;
-  int ip_header_size;
-  Timestamp arrival_time;
-};
-
-class EmulatedNetworkReceiverInterface {
- public:
-  virtual ~EmulatedNetworkReceiverInterface() = default;
-
-  virtual void OnPacketReceived(EmulatedIpPacket packet) = 0;
-};
 
 class LinkEmulation : public EmulatedNetworkReceiverInterface {
  public:
@@ -158,42 +122,29 @@
 // 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 EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
+class EmulatedEndpointImpl : public EmulatedEndpoint {
  public:
-  EmulatedEndpoint(uint64_t id,
-                   const rtc::IPAddress& ip,
-                   bool is_enabled,
-                   rtc::TaskQueue* task_queue,
-                   Clock* clock);
-  ~EmulatedEndpoint() override;
+  EmulatedEndpointImpl(uint64_t id,
+                       const rtc::IPAddress& ip,
+                       bool is_enabled,
+                       rtc::TaskQueue* task_queue,
+                       Clock* clock);
+  ~EmulatedEndpointImpl() override;
 
   uint64_t GetId() const;
 
   NetworkRouterNode* router() { return &router_; }
-  // Send packet into network.
-  // |from| will be used to set source address for the packet in destination
-  // socket.
-  // |to| will be used for routing verification and picking right socket by port
-  // on destination endpoint.
+
   void SendPacket(const rtc::SocketAddress& from,
                   const rtc::SocketAddress& to,
-                  rtc::CopyOnWriteBuffer packet_data);
+                  rtc::CopyOnWriteBuffer packet_data) override;
 
-  // Binds receiver to this endpoint to send and receive data.
-  // |desired_port| is a port that should be used. If it is equal to 0,
-  // endpoint will pick the first available port starting from
-  // |kFirstEphemeralPort|.
-  //
-  // Returns the port, that should be used (it will be equals to desired, if
-  // |desired_port| != 0 and is free or will be the one, selected by endpoint)
-  // or absl::nullopt if desired_port in used. Also fails if there are no more
-  // free ports to bind to.
   absl::optional<uint16_t> BindReceiver(
       uint16_t desired_port,
-      EmulatedNetworkReceiverInterface* receiver);
-  void UnbindReceiver(uint16_t port);
+      EmulatedNetworkReceiverInterface* receiver) override;
+  void UnbindReceiver(uint16_t port) override;
 
-  rtc::IPAddress GetPeerLocalAddress() const;
+  rtc::IPAddress GetPeerLocalAddress() const override;
 
   // Will be called to deliver packet into endpoint from network node.
   void OnPacketReceived(EmulatedIpPacket packet) override;
@@ -204,7 +155,7 @@
 
   const rtc::Network& network() const { return *network_.get(); }
 
-  EmulatedNetworkStats stats();
+  EmulatedNetworkStats stats() override;
 
  private:
   static constexpr uint16_t kFirstEphemeralPort = 49152;
@@ -232,29 +183,31 @@
 
 class EmulatedRoute {
  public:
-  EmulatedRoute(EmulatedEndpoint* from,
+  EmulatedRoute(EmulatedEndpointImpl* from,
                 std::vector<EmulatedNetworkNode*> via_nodes,
-                EmulatedEndpoint* to)
+                EmulatedEndpointImpl* to)
       : from(from), via_nodes(std::move(via_nodes)), to(to), active(true) {}
 
-  EmulatedEndpoint* from;
+  EmulatedEndpointImpl* from;
   std::vector<EmulatedNetworkNode*> via_nodes;
-  EmulatedEndpoint* to;
+  EmulatedEndpointImpl* to;
   bool active;
 };
 class EndpointsContainer {
  public:
-  explicit EndpointsContainer(const std::vector<EmulatedEndpoint*>& endpoints);
+  explicit EndpointsContainer(
+      const std::vector<EmulatedEndpointImpl*>& endpoints);
 
-  EmulatedEndpoint* LookupByLocalAddress(const rtc::IPAddress& local_ip) const;
-  bool HasEndpoint(EmulatedEndpoint* endpoint) const;
+  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;
   EmulatedNetworkStats GetStats() const;
 
  private:
-  const std::vector<EmulatedEndpoint*> endpoints_;
+  const std::vector<EmulatedEndpointImpl*> endpoints_;
 };
 
 template <typename FakePacketType>
diff --git a/test/network/network_emulation_manager.cc b/test/network/network_emulation_manager.cc
index a2d8d90..77ac460 100644
--- a/test/network/network_emulation_manager.cc
+++ b/test/network/network_emulation_manager.cc
@@ -62,7 +62,8 @@
   return out;
 }
 
-SimulatedNetworkNode::Builder NetworkEmulationManagerImpl::NodeBuilder() {
+NetworkEmulationManager::SimulatedNetworkNode::Builder
+NetworkEmulationManagerImpl::NodeBuilder() {
   return SimulatedNetworkNode::Builder(this);
 }
 
@@ -85,7 +86,7 @@
 
   bool res = used_ip_addresses_.insert(*ip).second;
   RTC_CHECK(res) << "IP=" << ip->ToString() << " already in use";
-  auto node = std::make_unique<EmulatedEndpoint>(
+  auto node = std::make_unique<EmulatedEndpointImpl>(
       next_node_id_++, *ip, config.start_as_enabled, &task_queue_, clock_);
   EmulatedEndpoint* out = node.get();
   endpoints_.push_back(std::move(node));
@@ -96,14 +97,15 @@
   EmulatedNetworkManager* network_manager =
       endpoint_to_network_manager_[endpoint];
   RTC_CHECK(network_manager);
-  network_manager->EnableEndpoint(endpoint);
+  network_manager->EnableEndpoint(static_cast<EmulatedEndpointImpl*>(endpoint));
 }
 
 void NetworkEmulationManagerImpl::DisableEndpoint(EmulatedEndpoint* endpoint) {
   EmulatedNetworkManager* network_manager =
       endpoint_to_network_manager_[endpoint];
   RTC_CHECK(network_manager);
-  network_manager->DisableEndpoint(endpoint);
+  network_manager->DisableEndpoint(
+      static_cast<EmulatedEndpointImpl*>(endpoint));
 }
 
 EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
@@ -114,7 +116,8 @@
   // provided here.
   RTC_CHECK(!via_nodes.empty());
 
-  from->router()->SetReceiver(to->GetPeerLocalAddress(), via_nodes[0]);
+  static_cast<EmulatedEndpointImpl*>(from)->router()->SetReceiver(
+      to->GetPeerLocalAddress(), via_nodes[0]);
   EmulatedNetworkNode* cur_node = via_nodes[0];
   for (size_t i = 1; i < via_nodes.size(); ++i) {
     cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), via_nodes[i]);
@@ -122,8 +125,9 @@
   }
   cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), to);
 
-  std::unique_ptr<EmulatedRoute> route =
-      std::make_unique<EmulatedRoute>(from, std::move(via_nodes), to);
+  std::unique_ptr<EmulatedRoute> route = std::make_unique<EmulatedRoute>(
+      static_cast<EmulatedEndpointImpl*>(from), std::move(via_nodes),
+      static_cast<EmulatedEndpointImpl*>(to));
   EmulatedRoute* out = route.get();
   routes_.push_back(std::move(route));
   return out;
@@ -231,8 +235,8 @@
 TcpMessageRoute* NetworkEmulationManagerImpl::CreateTcpRoute(
     EmulatedRoute* send_route,
     EmulatedRoute* ret_route) {
-  auto tcp_route = std::make_unique<TcpMessageRoute>(clock_, task_queue_.Get(),
-                                                     send_route, ret_route);
+  auto tcp_route = std::make_unique<TcpMessageRouteImpl>(
+      clock_, task_queue_.Get(), send_route, ret_route);
   auto* route_ptr = tcp_route.get();
   task_queue_.PostTask([this, tcp_route = std::move(tcp_route)]() mutable {
     tcp_message_routes_.push_back(std::move(tcp_route));
@@ -254,7 +258,12 @@
 EmulatedNetworkManagerInterface*
 NetworkEmulationManagerImpl::CreateEmulatedNetworkManagerInterface(
     const std::vector<EmulatedEndpoint*>& endpoints) {
-  auto endpoints_container = std::make_unique<EndpointsContainer>(endpoints);
+  std::vector<EmulatedEndpointImpl*> endpoint_impls;
+  for (EmulatedEndpoint* endpoint : endpoints) {
+    endpoint_impls.push_back(static_cast<EmulatedEndpointImpl*>(endpoint));
+  }
+  auto endpoints_container =
+      std::make_unique<EndpointsContainer>(endpoint_impls);
   auto network_manager = std::make_unique<EmulatedNetworkManager>(
       clock_, &task_queue_, endpoints_container.get());
   for (auto* endpoint : endpoints) {
diff --git a/test/network/network_emulation_manager.h b/test/network/network_emulation_manager.h
index f19ded8..d640ea2 100644
--- a/test/network/network_emulation_manager.h
+++ b/test/network/network_emulation_manager.h
@@ -32,7 +32,6 @@
 #include "test/network/emulated_network_manager.h"
 #include "test/network/fake_network_socket_server.h"
 #include "test/network/network_emulation.h"
-#include "test/network/simulated_network_node.h"
 #include "test/network/traffic_route.h"
 
 namespace webrtc {
@@ -49,7 +48,7 @@
   EmulatedNetworkNode* CreateEmulatedNode(
       std::unique_ptr<NetworkBehaviorInterface> network_behavior) override;
 
-  SimulatedNetworkNode::Builder NodeBuilder();
+  SimulatedNetworkNode::Builder NodeBuilder() override;
 
   EmulatedEndpoint* CreateEndpoint(EmulatedEndpointConfig config) override;
   void EnableEndpoint(EmulatedEndpoint* endpoint) override;
@@ -60,7 +59,7 @@
                              EmulatedEndpoint* to) override;
 
   EmulatedRoute* CreateRoute(
-      const std::vector<EmulatedNetworkNode*>& via_nodes);
+      const std::vector<EmulatedNetworkNode*>& via_nodes) override;
 
   void ClearRoute(EmulatedRoute* route) override;
 
@@ -78,7 +77,7 @@
       FakeTcpConfig config);
 
   TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route,
-                                  EmulatedRoute* ret_route);
+                                  EmulatedRoute* ret_route) override;
 
   void StopCrossTraffic(FakeTcpCrossTraffic* traffic);
 
@@ -105,7 +104,7 @@
   std::vector<std::unique_ptr<RandomWalkCrossTraffic>> random_cross_traffics_;
   std::vector<std::unique_ptr<PulsedPeaksCrossTraffic>> pulsed_cross_traffics_;
   std::list<std::unique_ptr<FakeTcpCrossTraffic>> tcp_cross_traffics_;
-  std::list<std::unique_ptr<TcpMessageRoute>> tcp_message_routes_;
+  std::list<std::unique_ptr<TcpMessageRouteImpl>> tcp_message_routes_;
   std::vector<std::unique_ptr<EndpointsContainer>> endpoints_containers_;
   std::vector<std::unique_ptr<EmulatedNetworkManager>> network_managers_;
 
diff --git a/test/network/simulated_network_node.cc b/test/network/simulated_network_node.cc
deleted file mode 100644
index d85f2e6..0000000
--- a/test/network/simulated_network_node.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-#include "test/network/simulated_network_node.h"
-
-#include <memory>
-#include <utility>
-
-namespace webrtc {
-namespace test {
-
-SimulatedNetworkNode::Builder::Builder() {}
-
-SimulatedNetworkNode::Builder::Builder(NetworkEmulationManager* net)
-    : net_(net) {}
-
-SimulatedNetworkNode::Builder& SimulatedNetworkNode::Builder::config(
-    SimulatedNetwork::Config config) {
-  config_ = config;
-  return *this;
-}
-
-SimulatedNetworkNode::Builder& SimulatedNetworkNode::Builder::delay_ms(
-    int queue_delay_ms) {
-  config_.queue_delay_ms = queue_delay_ms;
-  return *this;
-}
-
-SimulatedNetworkNode::Builder& SimulatedNetworkNode::Builder::capacity_kbps(
-    int link_capacity_kbps) {
-  config_.link_capacity_kbps = link_capacity_kbps;
-  return *this;
-}
-
-SimulatedNetworkNode::Builder& SimulatedNetworkNode::Builder::capacity_Mbps(
-    int link_capacity_Mbps) {
-  config_.link_capacity_kbps = link_capacity_Mbps * 1000;
-  return *this;
-}
-
-SimulatedNetworkNode::Builder& SimulatedNetworkNode::Builder::loss(
-    double loss_rate) {
-  config_.loss_percent = std::round(loss_rate * 100);
-  return *this;
-}
-
-SimulatedNetworkNode SimulatedNetworkNode::Builder::Build() const {
-  RTC_DCHECK(net_);
-  return Build(net_);
-}
-
-SimulatedNetworkNode SimulatedNetworkNode::Builder::Build(
-    NetworkEmulationManager* net) const {
-  SimulatedNetworkNode res;
-  auto behavior = std::make_unique<SimulatedNetwork>(config_);
-  res.simulation = behavior.get();
-  res.node = net->CreateEmulatedNode(std::move(behavior));
-  return res;
-}
-
-}  // namespace test
-}  // namespace webrtc
diff --git a/test/network/simulated_network_node.h b/test/network/simulated_network_node.h
deleted file mode 100644
index e374c59..0000000
--- a/test/network/simulated_network_node.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  Copyright (c) 2019 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_SIMULATED_NETWORK_NODE_H_
-#define TEST_NETWORK_SIMULATED_NETWORK_NODE_H_
-
-#include "api/test/network_emulation_manager.h"
-#include "call/simulated_network.h"
-
-namespace webrtc {
-namespace test {
-// Helper struct to simplify creation of simulated network behaviors.
-struct SimulatedNetworkNode {
-  SimulatedNetwork* simulation;
-  EmulatedNetworkNode* node;
-  class Builder {
-   public:
-    Builder();
-    explicit Builder(NetworkEmulationManager* net);
-    Builder& config(SimulatedNetwork::Config config);
-    Builder& delay_ms(int queue_delay_ms);
-    Builder& capacity_kbps(int link_capacity_kbps);
-    Builder& capacity_Mbps(int link_capacity_Mbps);
-    Builder& loss(double loss_rate);
-    SimulatedNetworkNode Build() const;
-    SimulatedNetworkNode Build(NetworkEmulationManager* net) const;
-
-   private:
-    NetworkEmulationManager* const net_ = nullptr;
-    SimulatedNetwork::Config config_;
-  };
-};
-}  // namespace test
-}  // namespace webrtc
-
-#endif  // TEST_NETWORK_SIMULATED_NETWORK_NODE_H_