This was generated by Running $ for i in test/network/*.cc; do ./tools_webrtc/iwyu/apply-include-cleaner $i; done $ for i in test/network/*.h; do ./tools_webrtc/iwyu/apply-include-cleaner $i; done $ python3 ./tools_webrtc/gn_check_autofix.py -C out/Default manually removing <sys/socket.h> include as suspicious. manually modifying test/DEPS file. Bug: webrtc:42226242 Change-Id: Ifda037e1385996ac3b68190c7e30e5309356ebb1 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/376382 Reviewed-by: Per Kjellander <perkj@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Reviewed-by: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/main@{#43857}
212 lines
7.4 KiB
C++
212 lines
7.4 KiB
C++
/*
|
|
* Copyright (c) 2020 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/emulated_turn_server.h"
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
#include "api/async_dns_resolver.h"
|
|
#include "api/packet_socket_factory.h"
|
|
#include "api/sequence_checker.h"
|
|
#include "api/test/network_emulation/network_emulation_interfaces.h"
|
|
#include "api/test/network_emulation_manager.h"
|
|
#include "p2p/base/port_interface.h"
|
|
#include "p2p/base/turn_server.h"
|
|
#include "rtc_base/async_packet_socket.h"
|
|
#include "rtc_base/checks.h"
|
|
#include "rtc_base/copy_on_write_buffer.h"
|
|
#include "rtc_base/network/received_packet.h"
|
|
#include "rtc_base/socket.h"
|
|
#include "rtc_base/socket_address.h"
|
|
#include "rtc_base/strings/string_builder.h"
|
|
#include "rtc_base/task_queue_for_test.h"
|
|
#include "rtc_base/thread.h"
|
|
|
|
namespace {
|
|
|
|
static const char kTestRealm[] = "example.org";
|
|
static const char kTestSoftware[] = "TestTurnServer";
|
|
|
|
// A wrapper class for cricket::TurnServer to allocate sockets.
|
|
class PacketSocketFactoryWrapper : public rtc::PacketSocketFactory {
|
|
public:
|
|
explicit PacketSocketFactoryWrapper(
|
|
webrtc::test::EmulatedTURNServer* turn_server)
|
|
: turn_server_(turn_server) {}
|
|
~PacketSocketFactoryWrapper() override {}
|
|
|
|
// This method is called from TurnServer when making a TURN ALLOCATION.
|
|
// It will create a socket on the `peer_` endpoint.
|
|
rtc::AsyncPacketSocket* CreateUdpSocket(const rtc::SocketAddress& address,
|
|
uint16_t min_port,
|
|
uint16_t max_port) override {
|
|
return turn_server_->CreatePeerSocket();
|
|
}
|
|
|
|
rtc::AsyncListenSocket* CreateServerTcpSocket(
|
|
const rtc::SocketAddress& local_address,
|
|
uint16_t min_port,
|
|
uint16_t max_port,
|
|
int opts) override {
|
|
return nullptr;
|
|
}
|
|
rtc::AsyncPacketSocket* CreateClientTcpSocket(
|
|
const rtc::SocketAddress& local_address,
|
|
const rtc::SocketAddress& remote_address,
|
|
const rtc::PacketSocketTcpOptions& tcp_options) override {
|
|
return nullptr;
|
|
}
|
|
std::unique_ptr<webrtc::AsyncDnsResolverInterface> CreateAsyncDnsResolver()
|
|
override {
|
|
return nullptr;
|
|
}
|
|
|
|
private:
|
|
webrtc::test::EmulatedTURNServer* turn_server_;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
namespace webrtc {
|
|
namespace test {
|
|
|
|
// A wrapper class for copying data between an AsyncPacketSocket and a
|
|
// EmulatedEndpoint. This is used by the cricket::TurnServer when
|
|
// sending data back into the emulated network.
|
|
class EmulatedTURNServer::AsyncPacketSocketWrapper
|
|
: public rtc::AsyncPacketSocket {
|
|
public:
|
|
AsyncPacketSocketWrapper(webrtc::test::EmulatedTURNServer* turn_server,
|
|
webrtc::EmulatedEndpoint* endpoint,
|
|
uint16_t port)
|
|
: turn_server_(turn_server),
|
|
endpoint_(endpoint),
|
|
local_address_(
|
|
rtc::SocketAddress(endpoint_->GetPeerLocalAddress(), port)) {}
|
|
~AsyncPacketSocketWrapper() { turn_server_->Unbind(local_address_); }
|
|
|
|
rtc::SocketAddress GetLocalAddress() const override { return local_address_; }
|
|
rtc::SocketAddress GetRemoteAddress() const override {
|
|
return rtc::SocketAddress();
|
|
}
|
|
int Send(const void* pv,
|
|
size_t cb,
|
|
const rtc::PacketOptions& options) override {
|
|
RTC_CHECK(false) << "TCP not implemented";
|
|
return -1;
|
|
}
|
|
int SendTo(const void* pv,
|
|
size_t cb,
|
|
const rtc::SocketAddress& addr,
|
|
const rtc::PacketOptions& options) override {
|
|
// Copy from rtc::AsyncPacketSocket to EmulatedEndpoint.
|
|
rtc::CopyOnWriteBuffer buf(reinterpret_cast<const char*>(pv), cb);
|
|
endpoint_->SendPacket(local_address_, addr, buf);
|
|
return cb;
|
|
}
|
|
int Close() override { return 0; }
|
|
void NotifyPacketReceived(const rtc::ReceivedPacket& packet) {
|
|
rtc::AsyncPacketSocket::NotifyPacketReceived(packet);
|
|
}
|
|
|
|
rtc::AsyncPacketSocket::State GetState() const override {
|
|
return rtc::AsyncPacketSocket::STATE_BOUND;
|
|
}
|
|
int GetOption(rtc::Socket::Option opt, int* value) override { return 0; }
|
|
int SetOption(rtc::Socket::Option opt, int value) override { return 0; }
|
|
int GetError() const override { return 0; }
|
|
void SetError(int error) override {}
|
|
|
|
private:
|
|
webrtc::test::EmulatedTURNServer* const turn_server_;
|
|
webrtc::EmulatedEndpoint* const endpoint_;
|
|
const rtc::SocketAddress local_address_;
|
|
};
|
|
|
|
EmulatedTURNServer::EmulatedTURNServer(const EmulatedTURNServerConfig& config,
|
|
std::unique_ptr<rtc::Thread> thread,
|
|
EmulatedEndpoint* client,
|
|
EmulatedEndpoint* peer)
|
|
: thread_(std::move(thread)), client_(client), peer_(peer) {
|
|
ice_config_.username = "keso";
|
|
ice_config_.password = "keso";
|
|
SendTask(thread_.get(), [this, enable_permission_checks =
|
|
config.enable_permission_checks]() {
|
|
RTC_DCHECK_RUN_ON(thread_.get());
|
|
turn_server_ = std::make_unique<cricket::TurnServer>(thread_.get());
|
|
turn_server_->set_realm(kTestRealm);
|
|
turn_server_->set_realm(kTestSoftware);
|
|
turn_server_->set_auth_hook(this);
|
|
turn_server_->set_enable_permission_checks(enable_permission_checks);
|
|
|
|
auto client_socket = Wrap(client_);
|
|
turn_server_->AddInternalSocket(client_socket, cricket::PROTO_UDP);
|
|
turn_server_->SetExternalSocketFactory(new PacketSocketFactoryWrapper(this),
|
|
rtc::SocketAddress());
|
|
client_address_ = client_socket->GetLocalAddress();
|
|
char buf[256];
|
|
rtc::SimpleStringBuilder str(buf);
|
|
str.AppendFormat("turn:%s?transport=udp",
|
|
client_address_.ToString().c_str());
|
|
ice_config_.url = str.str();
|
|
});
|
|
}
|
|
|
|
void EmulatedTURNServer::Stop() {
|
|
SendTask(thread_.get(), [this]() {
|
|
RTC_DCHECK_RUN_ON(thread_.get());
|
|
sockets_.clear();
|
|
});
|
|
}
|
|
|
|
EmulatedTURNServer::~EmulatedTURNServer() {
|
|
SendTask(thread_.get(), [this]() {
|
|
RTC_DCHECK_RUN_ON(thread_.get());
|
|
turn_server_.reset(nullptr);
|
|
});
|
|
}
|
|
|
|
rtc::AsyncPacketSocket* EmulatedTURNServer::Wrap(EmulatedEndpoint* endpoint) {
|
|
RTC_DCHECK_RUN_ON(thread_.get());
|
|
auto port = endpoint->BindReceiver(0, this).value();
|
|
auto socket = new AsyncPacketSocketWrapper(this, endpoint, port);
|
|
sockets_[rtc::SocketAddress(endpoint->GetPeerLocalAddress(), port)] = socket;
|
|
return socket;
|
|
}
|
|
|
|
void EmulatedTURNServer::OnPacketReceived(webrtc::EmulatedIpPacket packet) {
|
|
// Copy from EmulatedEndpoint to rtc::AsyncPacketSocket.
|
|
thread_->PostTask([this, packet(std::move(packet))]() {
|
|
RTC_DCHECK_RUN_ON(thread_.get());
|
|
auto it = sockets_.find(packet.to);
|
|
if (it != sockets_.end()) {
|
|
it->second->NotifyPacketReceived(
|
|
rtc::ReceivedPacket(packet.data, packet.from, packet.arrival_time));
|
|
}
|
|
});
|
|
}
|
|
|
|
void EmulatedTURNServer::Unbind(rtc::SocketAddress address) {
|
|
RTC_DCHECK_RUN_ON(thread_.get());
|
|
if (GetClientEndpoint()->GetPeerLocalAddress() == address.ipaddr()) {
|
|
GetClientEndpoint()->UnbindReceiver(address.port());
|
|
} else {
|
|
GetPeerEndpoint()->UnbindReceiver(address.port());
|
|
}
|
|
sockets_.erase(address);
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace webrtc
|