blob: 0d360cf2487bd432c807aaaa97ba90bc2a344e89 [file] [log] [blame]
/*
* Copyright 2008 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 P2P_BASE_TESTRELAYSERVER_H_
#define P2P_BASE_TESTRELAYSERVER_H_
#include <memory>
#include "p2p/base/relayserver.h"
#include "rtc_base/asynctcpsocket.h"
#include "rtc_base/sigslot.h"
#include "rtc_base/socketadapters.h"
#include "rtc_base/thread.h"
namespace cricket {
// A test relay server. Useful for unit tests.
class TestRelayServer : public sigslot::has_slots<> {
public:
TestRelayServer(rtc::Thread* thread,
const rtc::SocketAddress& udp_int_addr,
const rtc::SocketAddress& udp_ext_addr,
const rtc::SocketAddress& tcp_int_addr,
const rtc::SocketAddress& tcp_ext_addr,
const rtc::SocketAddress& ssl_int_addr,
const rtc::SocketAddress& ssl_ext_addr)
: server_(thread) {
server_.AddInternalSocket(rtc::AsyncUDPSocket::Create(
thread->socketserver(), udp_int_addr));
server_.AddExternalSocket(rtc::AsyncUDPSocket::Create(
thread->socketserver(), udp_ext_addr));
tcp_int_socket_.reset(CreateListenSocket(thread, tcp_int_addr));
tcp_ext_socket_.reset(CreateListenSocket(thread, tcp_ext_addr));
ssl_int_socket_.reset(CreateListenSocket(thread, ssl_int_addr));
ssl_ext_socket_.reset(CreateListenSocket(thread, ssl_ext_addr));
}
int GetConnectionCount() const {
return server_.GetConnectionCount();
}
rtc::SocketAddressPair GetConnection(int connection) const {
return server_.GetConnection(connection);
}
bool HasConnection(const rtc::SocketAddress& address) const {
return server_.HasConnection(address);
}
private:
rtc::AsyncSocket* CreateListenSocket(rtc::Thread* thread,
const rtc::SocketAddress& addr) {
rtc::AsyncSocket* socket =
thread->socketserver()->CreateAsyncSocket(addr.family(), SOCK_STREAM);
socket->Bind(addr);
socket->Listen(5);
socket->SignalReadEvent.connect(this, &TestRelayServer::OnAccept);
return socket;
}
void OnAccept(rtc::AsyncSocket* socket) {
bool external = (socket == tcp_ext_socket_.get() ||
socket == ssl_ext_socket_.get());
bool ssl = (socket == ssl_int_socket_.get() ||
socket == ssl_ext_socket_.get());
rtc::AsyncSocket* raw_socket = socket->Accept(NULL);
if (raw_socket) {
rtc::AsyncTCPSocket* packet_socket = new rtc::AsyncTCPSocket(
(!ssl) ? raw_socket :
new rtc::AsyncSSLServerSocket(raw_socket), false);
if (!external) {
packet_socket->SignalClose.connect(this,
&TestRelayServer::OnInternalClose);
server_.AddInternalSocket(packet_socket);
} else {
packet_socket->SignalClose.connect(this,
&TestRelayServer::OnExternalClose);
server_.AddExternalSocket(packet_socket);
}
}
}
void OnInternalClose(rtc::AsyncPacketSocket* socket, int error) {
server_.RemoveInternalSocket(socket);
}
void OnExternalClose(rtc::AsyncPacketSocket* socket, int error) {
server_.RemoveExternalSocket(socket);
}
private:
cricket::RelayServer server_;
std::unique_ptr<rtc::AsyncSocket> tcp_int_socket_;
std::unique_ptr<rtc::AsyncSocket> tcp_ext_socket_;
std::unique_ptr<rtc::AsyncSocket> ssl_int_socket_;
std::unique_ptr<rtc::AsyncSocket> ssl_ext_socket_;
};
} // namespace cricket
#endif // P2P_BASE_TESTRELAYSERVER_H_