1 /* 2 * Copyright 2012 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 P2P_BASE_TEST_TURN_SERVER_H_ 12 #define P2P_BASE_TEST_TURN_SERVER_H_ 13 14 #include <memory> 15 #include <string> 16 #include <utility> 17 #include <vector> 18 19 #include "absl/strings/string_view.h" 20 #include "api/sequence_checker.h" 21 #include "api/transport/stun.h" 22 #include "p2p/base/basic_packet_socket_factory.h" 23 #include "p2p/base/turn_server.h" 24 #include "rtc_base/async_udp_socket.h" 25 #include "rtc_base/ssl_adapter.h" 26 #include "rtc_base/ssl_identity.h" 27 #include "rtc_base/thread.h" 28 29 namespace cricket { 30 31 static const char kTestRealm[] = "example.org"; 32 static const char kTestSoftware[] = "TestTurnServer"; 33 34 class TestTurnRedirector : public TurnRedirectInterface { 35 public: TestTurnRedirector(const std::vector<rtc::SocketAddress> & addresses)36 explicit TestTurnRedirector(const std::vector<rtc::SocketAddress>& addresses) 37 : alternate_server_addresses_(addresses), 38 iter_(alternate_server_addresses_.begin()) {} 39 ShouldRedirect(const rtc::SocketAddress &,rtc::SocketAddress * out)40 virtual bool ShouldRedirect(const rtc::SocketAddress&, 41 rtc::SocketAddress* out) { 42 if (!out || iter_ == alternate_server_addresses_.end()) { 43 return false; 44 } 45 *out = *iter_++; 46 return true; 47 } 48 49 private: 50 const std::vector<rtc::SocketAddress>& alternate_server_addresses_; 51 std::vector<rtc::SocketAddress>::const_iterator iter_; 52 }; 53 54 class TestTurnServer : public TurnAuthInterface { 55 public: 56 TestTurnServer(rtc::Thread* thread, 57 rtc::SocketFactory* socket_factory, 58 const rtc::SocketAddress& int_addr, 59 const rtc::SocketAddress& udp_ext_addr, 60 ProtocolType int_protocol = PROTO_UDP, 61 bool ignore_bad_cert = true, 62 absl::string_view common_name = "test turn server") server_(thread)63 : server_(thread), socket_factory_(socket_factory) { 64 AddInternalSocket(int_addr, int_protocol, ignore_bad_cert, common_name); 65 server_.SetExternalSocketFactory( 66 new rtc::BasicPacketSocketFactory(socket_factory), udp_ext_addr); 67 server_.set_realm(kTestRealm); 68 server_.set_software(kTestSoftware); 69 server_.set_auth_hook(this); 70 } 71 ~TestTurnServer()72 ~TestTurnServer() { RTC_DCHECK(thread_checker_.IsCurrent()); } 73 set_enable_otu_nonce(bool enable)74 void set_enable_otu_nonce(bool enable) { 75 RTC_DCHECK(thread_checker_.IsCurrent()); 76 server_.set_enable_otu_nonce(enable); 77 } 78 server()79 TurnServer* server() { 80 RTC_DCHECK(thread_checker_.IsCurrent()); 81 return &server_; 82 } 83 set_redirect_hook(TurnRedirectInterface * redirect_hook)84 void set_redirect_hook(TurnRedirectInterface* redirect_hook) { 85 RTC_DCHECK(thread_checker_.IsCurrent()); 86 server_.set_redirect_hook(redirect_hook); 87 } 88 set_enable_permission_checks(bool enable)89 void set_enable_permission_checks(bool enable) { 90 RTC_DCHECK(thread_checker_.IsCurrent()); 91 server_.set_enable_permission_checks(enable); 92 } 93 94 void AddInternalSocket(const rtc::SocketAddress& int_addr, 95 ProtocolType proto, 96 bool ignore_bad_cert = true, 97 absl::string_view common_name = "test turn server") { 98 RTC_DCHECK(thread_checker_.IsCurrent()); 99 if (proto == cricket::PROTO_UDP) { 100 server_.AddInternalSocket( 101 rtc::AsyncUDPSocket::Create(socket_factory_, int_addr), proto); 102 } else if (proto == cricket::PROTO_TCP || proto == cricket::PROTO_TLS) { 103 // For TCP we need to create a server socket which can listen for incoming 104 // new connections. 105 rtc::Socket* socket = socket_factory_->CreateSocket(AF_INET, SOCK_STREAM); 106 socket->Bind(int_addr); 107 socket->Listen(5); 108 if (proto == cricket::PROTO_TLS) { 109 // For TLS, wrap the TCP socket with an SSL adapter. The adapter must 110 // be configured with a self-signed certificate for testing. 111 // Additionally, the client will not present a valid certificate, so we 112 // must not fail when checking the peer's identity. 113 std::unique_ptr<rtc::SSLAdapterFactory> ssl_adapter_factory = 114 rtc::SSLAdapterFactory::Create(); 115 ssl_adapter_factory->SetRole(rtc::SSL_SERVER); 116 ssl_adapter_factory->SetIdentity( 117 rtc::SSLIdentity::Create(common_name, rtc::KeyParams())); 118 ssl_adapter_factory->SetIgnoreBadCert(ignore_bad_cert); 119 server_.AddInternalServerSocket(socket, proto, 120 std::move(ssl_adapter_factory)); 121 } else { 122 server_.AddInternalServerSocket(socket, proto); 123 } 124 } else { 125 RTC_DCHECK_NOTREACHED() << "Unknown protocol type: " << proto; 126 } 127 } 128 129 // Finds the first allocation in the server allocation map with a source 130 // ip and port matching the socket address provided. FindAllocation(const rtc::SocketAddress & src)131 TurnServerAllocation* FindAllocation(const rtc::SocketAddress& src) { 132 RTC_DCHECK(thread_checker_.IsCurrent()); 133 const TurnServer::AllocationMap& map = server_.allocations(); 134 for (TurnServer::AllocationMap::const_iterator it = map.begin(); 135 it != map.end(); ++it) { 136 if (src == it->first.src()) { 137 return it->second.get(); 138 } 139 } 140 return NULL; 141 } 142 143 private: 144 // For this test server, succeed if the password is the same as the username. 145 // Obviously, do not use this in a production environment. GetKey(absl::string_view username,absl::string_view realm,std::string * key)146 virtual bool GetKey(absl::string_view username, 147 absl::string_view realm, 148 std::string* key) { 149 RTC_DCHECK(thread_checker_.IsCurrent()); 150 return ComputeStunCredentialHash(std::string(username), std::string(realm), 151 std::string(username), key); 152 } 153 154 TurnServer server_; 155 rtc::SocketFactory* socket_factory_; 156 webrtc::SequenceChecker thread_checker_; 157 }; 158 159 } // namespace cricket 160 161 #endif // P2P_BASE_TEST_TURN_SERVER_H_ 162