mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-14 14:20:45 +01:00

Bug: webrtc:11318 Change-Id: I14e3fbc694d41c785a61c88d8207005c681576c4 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/271540 Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37774}
191 lines
6.6 KiB
C++
191 lines
6.6 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 <string>
|
|
#include <utility>
|
|
|
|
#include "api/packet_socket_factory.h"
|
|
#include "rtc_base/strings/string_builder.h"
|
|
#include "rtc_base/task_queue_for_test.h"
|
|
|
|
namespace {
|
|
|
|
static const char kTestRealm[] = "example.org";
|
|
static const char kTestSoftware[] = "TestTurnServer";
|
|
|
|
// 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 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; }
|
|
|
|
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_;
|
|
};
|
|
|
|
// 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::ProxyInfo& proxy_info,
|
|
const std::string& user_agent,
|
|
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 {
|
|
|
|
EmulatedTURNServer::EmulatedTURNServer(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(), [=]() {
|
|
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);
|
|
|
|
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(), [=]() {
|
|
RTC_DCHECK_RUN_ON(thread_.get());
|
|
sockets_.clear();
|
|
});
|
|
}
|
|
|
|
EmulatedTURNServer::~EmulatedTURNServer() {
|
|
SendTask(thread_.get(), [=]() {
|
|
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->SignalReadPacket(
|
|
it->second, reinterpret_cast<const char*>(packet.cdata()),
|
|
packet.size(), packet.from, packet.arrival_time.ms());
|
|
}
|
|
});
|
|
}
|
|
|
|
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
|