1 /*
2  *  Copyright 2008 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef WEBRTC_P2P_BASE_TESTRELAYSERVER_H_
12 #define WEBRTC_P2P_BASE_TESTRELAYSERVER_H_
13 
14 #include "webrtc/p2p/base/relayserver.h"
15 #include "webrtc/base/asynctcpsocket.h"
16 #include "webrtc/base/scoped_ptr.h"
17 #include "webrtc/base/sigslot.h"
18 #include "webrtc/base/socketadapters.h"
19 #include "webrtc/base/thread.h"
20 
21 namespace cricket {
22 
23 // A test relay server. Useful for unit tests.
24 class TestRelayServer : public sigslot::has_slots<> {
25  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)26   TestRelayServer(rtc::Thread* thread,
27                   const rtc::SocketAddress& udp_int_addr,
28                   const rtc::SocketAddress& udp_ext_addr,
29                   const rtc::SocketAddress& tcp_int_addr,
30                   const rtc::SocketAddress& tcp_ext_addr,
31                   const rtc::SocketAddress& ssl_int_addr,
32                   const rtc::SocketAddress& ssl_ext_addr)
33       : server_(thread) {
34     server_.AddInternalSocket(rtc::AsyncUDPSocket::Create(
35         thread->socketserver(), udp_int_addr));
36     server_.AddExternalSocket(rtc::AsyncUDPSocket::Create(
37         thread->socketserver(), udp_ext_addr));
38 
39     tcp_int_socket_.reset(CreateListenSocket(thread, tcp_int_addr));
40     tcp_ext_socket_.reset(CreateListenSocket(thread, tcp_ext_addr));
41     ssl_int_socket_.reset(CreateListenSocket(thread, ssl_int_addr));
42     ssl_ext_socket_.reset(CreateListenSocket(thread, ssl_ext_addr));
43   }
GetConnectionCount()44   int GetConnectionCount() const {
45     return server_.GetConnectionCount();
46   }
GetConnection(int connection)47   rtc::SocketAddressPair GetConnection(int connection) const {
48     return server_.GetConnection(connection);
49   }
HasConnection(const rtc::SocketAddress & address)50   bool HasConnection(const rtc::SocketAddress& address) const {
51     return server_.HasConnection(address);
52   }
53 
54  private:
CreateListenSocket(rtc::Thread * thread,const rtc::SocketAddress & addr)55   rtc::AsyncSocket* CreateListenSocket(rtc::Thread* thread,
56       const rtc::SocketAddress& addr) {
57     rtc::AsyncSocket* socket =
58         thread->socketserver()->CreateAsyncSocket(addr.family(), SOCK_STREAM);
59     socket->Bind(addr);
60     socket->Listen(5);
61     socket->SignalReadEvent.connect(this, &TestRelayServer::OnAccept);
62     return socket;
63   }
OnAccept(rtc::AsyncSocket * socket)64   void OnAccept(rtc::AsyncSocket* socket) {
65     bool external = (socket == tcp_ext_socket_.get() ||
66                      socket == ssl_ext_socket_.get());
67     bool ssl = (socket == ssl_int_socket_.get() ||
68                 socket == ssl_ext_socket_.get());
69     rtc::AsyncSocket* raw_socket = socket->Accept(NULL);
70     if (raw_socket) {
71       rtc::AsyncTCPSocket* packet_socket = new rtc::AsyncTCPSocket(
72           (!ssl) ? raw_socket :
73           new rtc::AsyncSSLServerSocket(raw_socket), false);
74       if (!external) {
75         packet_socket->SignalClose.connect(this,
76             &TestRelayServer::OnInternalClose);
77         server_.AddInternalSocket(packet_socket);
78       } else {
79         packet_socket->SignalClose.connect(this,
80             &TestRelayServer::OnExternalClose);
81         server_.AddExternalSocket(packet_socket);
82       }
83     }
84   }
OnInternalClose(rtc::AsyncPacketSocket * socket,int error)85   void OnInternalClose(rtc::AsyncPacketSocket* socket, int error) {
86     server_.RemoveInternalSocket(socket);
87   }
OnExternalClose(rtc::AsyncPacketSocket * socket,int error)88   void OnExternalClose(rtc::AsyncPacketSocket* socket, int error) {
89     server_.RemoveExternalSocket(socket);
90   }
91  private:
92   cricket::RelayServer server_;
93   rtc::scoped_ptr<rtc::AsyncSocket> tcp_int_socket_;
94   rtc::scoped_ptr<rtc::AsyncSocket> tcp_ext_socket_;
95   rtc::scoped_ptr<rtc::AsyncSocket> ssl_int_socket_;
96   rtc::scoped_ptr<rtc::AsyncSocket> ssl_ext_socket_;
97 };
98 
99 }  // namespace cricket
100 
101 #endif  // WEBRTC_P2P_BASE_TESTRELAYSERVER_H_
102