henrike@webrtc.org | 28e2075 | 2013-07-10 00:45:36 +0000 | [diff] [blame] | 1 | /* |
| 2 | * libjingle |
| 3 | * Copyright 2008 Google Inc. |
| 4 | * |
| 5 | * Redistribution and use in source and binary forms, with or without |
| 6 | * modification, are permitted provided that the following conditions are met: |
| 7 | * |
| 8 | * 1. Redistributions of source code must retain the above copyright notice, |
| 9 | * this list of conditions and the following disclaimer. |
| 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
| 11 | * this list of conditions and the following disclaimer in the documentation |
| 12 | * and/or other materials provided with the distribution. |
| 13 | * 3. The name of the author may not be used to endorse or promote products |
| 14 | * derived from this software without specific prior written permission. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| 17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| 19 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| 22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| 24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| 25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 | */ |
| 27 | |
| 28 | #ifndef TALK_P2P_BASE_TESTRELAYSERVER_H_ |
| 29 | #define TALK_P2P_BASE_TESTRELAYSERVER_H_ |
| 30 | |
| 31 | #include "talk/base/asynctcpsocket.h" |
| 32 | #include "talk/base/scoped_ptr.h" |
| 33 | #include "talk/base/socketadapters.h" |
| 34 | #include "talk/base/sigslot.h" |
| 35 | #include "talk/base/thread.h" |
| 36 | #include "talk/p2p/base/relayserver.h" |
| 37 | |
| 38 | namespace cricket { |
| 39 | |
| 40 | // A test relay server. Useful for unit tests. |
| 41 | class TestRelayServer : public sigslot::has_slots<> { |
| 42 | public: |
| 43 | TestRelayServer(talk_base::Thread* thread, |
| 44 | const talk_base::SocketAddress& udp_int_addr, |
| 45 | const talk_base::SocketAddress& udp_ext_addr, |
| 46 | const talk_base::SocketAddress& tcp_int_addr, |
| 47 | const talk_base::SocketAddress& tcp_ext_addr, |
| 48 | const talk_base::SocketAddress& ssl_int_addr, |
| 49 | const talk_base::SocketAddress& ssl_ext_addr) |
| 50 | : server_(thread) { |
| 51 | server_.AddInternalSocket(talk_base::AsyncUDPSocket::Create( |
| 52 | thread->socketserver(), udp_int_addr)); |
| 53 | server_.AddExternalSocket(talk_base::AsyncUDPSocket::Create( |
| 54 | thread->socketserver(), udp_ext_addr)); |
| 55 | |
| 56 | tcp_int_socket_.reset(CreateListenSocket(thread, tcp_int_addr)); |
| 57 | tcp_ext_socket_.reset(CreateListenSocket(thread, tcp_ext_addr)); |
| 58 | ssl_int_socket_.reset(CreateListenSocket(thread, ssl_int_addr)); |
| 59 | ssl_ext_socket_.reset(CreateListenSocket(thread, ssl_ext_addr)); |
| 60 | } |
| 61 | int GetConnectionCount() const { |
| 62 | return server_.GetConnectionCount(); |
| 63 | } |
| 64 | talk_base::SocketAddressPair GetConnection(int connection) const { |
| 65 | return server_.GetConnection(connection); |
| 66 | } |
| 67 | bool HasConnection(const talk_base::SocketAddress& address) const { |
| 68 | return server_.HasConnection(address); |
| 69 | } |
| 70 | |
| 71 | private: |
| 72 | talk_base::AsyncSocket* CreateListenSocket(talk_base::Thread* thread, |
| 73 | const talk_base::SocketAddress& addr) { |
| 74 | talk_base::AsyncSocket* socket = |
| 75 | thread->socketserver()->CreateAsyncSocket(addr.family(), SOCK_STREAM); |
| 76 | socket->Bind(addr); |
| 77 | socket->Listen(5); |
| 78 | socket->SignalReadEvent.connect(this, &TestRelayServer::OnAccept); |
| 79 | return socket; |
| 80 | } |
| 81 | void OnAccept(talk_base::AsyncSocket* socket) { |
| 82 | bool external = (socket == tcp_ext_socket_.get() || |
| 83 | socket == ssl_ext_socket_.get()); |
| 84 | bool ssl = (socket == ssl_int_socket_.get() || |
| 85 | socket == ssl_ext_socket_.get()); |
| 86 | talk_base::AsyncSocket* raw_socket = socket->Accept(NULL); |
| 87 | if (raw_socket) { |
| 88 | talk_base::AsyncTCPSocket* packet_socket = new talk_base::AsyncTCPSocket( |
| 89 | (!ssl) ? raw_socket : |
| 90 | new talk_base::AsyncSSLServerSocket(raw_socket), false); |
| 91 | if (!external) { |
| 92 | packet_socket->SignalClose.connect(this, |
| 93 | &TestRelayServer::OnInternalClose); |
| 94 | server_.AddInternalSocket(packet_socket); |
| 95 | } else { |
| 96 | packet_socket->SignalClose.connect(this, |
| 97 | &TestRelayServer::OnExternalClose); |
| 98 | server_.AddExternalSocket(packet_socket); |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | void OnInternalClose(talk_base::AsyncPacketSocket* socket, int error) { |
| 103 | server_.RemoveInternalSocket(socket); |
| 104 | } |
| 105 | void OnExternalClose(talk_base::AsyncPacketSocket* socket, int error) { |
| 106 | server_.RemoveExternalSocket(socket); |
| 107 | } |
| 108 | private: |
| 109 | cricket::RelayServer server_; |
| 110 | talk_base::scoped_ptr<talk_base::AsyncSocket> tcp_int_socket_; |
| 111 | talk_base::scoped_ptr<talk_base::AsyncSocket> tcp_ext_socket_; |
| 112 | talk_base::scoped_ptr<talk_base::AsyncSocket> ssl_int_socket_; |
| 113 | talk_base::scoped_ptr<talk_base::AsyncSocket> ssl_ext_socket_; |
| 114 | }; |
| 115 | |
| 116 | } // namespace cricket |
| 117 | |
| 118 | #endif // TALK_P2P_BASE_TESTRELAYSERVER_H_ |