Index: webrtc/p2p/client/connectivitychecker.cc |
diff --git a/webrtc/p2p/client/connectivitychecker.cc b/webrtc/p2p/client/connectivitychecker.cc |
deleted file mode 100644 |
index 8a7fc0d740887e4b42ffd9cb080ea5d859668372..0000000000000000000000000000000000000000 |
--- a/webrtc/p2p/client/connectivitychecker.cc |
+++ /dev/null |
@@ -1,529 +0,0 @@ |
-/* |
- * Copyright 2011 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 <string> |
- |
-#include "webrtc/p2p/client/connectivitychecker.h" |
- |
-#include "webrtc/p2p/base/candidate.h" |
-#include "webrtc/p2p/base/common.h" |
-#include "webrtc/p2p/base/constants.h" |
-#include "webrtc/p2p/base/port.h" |
-#include "webrtc/p2p/base/relayport.h" |
-#include "webrtc/p2p/base/stunport.h" |
-#include "webrtc/base/asynchttprequest.h" |
-#include "webrtc/base/autodetectproxy.h" |
-#include "webrtc/base/helpers.h" |
-#include "webrtc/base/httpcommon-inl.h" |
-#include "webrtc/base/httpcommon.h" |
-#include "webrtc/base/logging.h" |
-#include "webrtc/base/proxydetect.h" |
-#include "webrtc/base/thread.h" |
- |
-namespace cricket { |
- |
-static const char kDefaultStunHostname[] = "stun.l.google.com"; |
-static const int kDefaultStunPort = 19302; |
- |
-// Default maximum time in milliseconds we will wait for connections. |
-static const uint32 kDefaultTimeoutMs = 3000; |
- |
-enum { |
- MSG_START = 1, |
- MSG_STOP = 2, |
- MSG_TIMEOUT = 3, |
- MSG_SIGNAL_RESULTS = 4 |
-}; |
- |
-class TestHttpPortAllocator : public HttpPortAllocator { |
- public: |
- TestHttpPortAllocator(rtc::NetworkManager* network_manager, |
- const std::string& user_agent, |
- const std::string& relay_token) : |
- HttpPortAllocator(network_manager, user_agent) { |
- SetRelayToken(relay_token); |
- } |
- PortAllocatorSession* CreateSessionInternal( |
- const std::string& content_name, |
- int component, |
- const std::string& ice_ufrag, |
- const std::string& ice_pwd) { |
- return new TestHttpPortAllocatorSession(this, content_name, component, |
- ice_ufrag, ice_pwd, |
- stun_hosts(), relay_hosts(), |
- relay_token(), user_agent()); |
- } |
-}; |
- |
-void TestHttpPortAllocatorSession::ConfigReady(PortConfiguration* config) { |
- SignalConfigReady(username(), password(), config, proxy_); |
- delete config; |
-} |
- |
-void TestHttpPortAllocatorSession::OnRequestDone( |
- rtc::SignalThread* data) { |
- rtc::AsyncHttpRequest* request = |
- static_cast<rtc::AsyncHttpRequest*>(data); |
- |
- // Tell the checker that the request is complete. |
- SignalRequestDone(request); |
- |
- // Pass on the response to super class. |
- HttpPortAllocatorSession::OnRequestDone(data); |
-} |
- |
-ConnectivityChecker::ConnectivityChecker( |
- rtc::Thread* worker, |
- const std::string& jid, |
- const std::string& session_id, |
- const std::string& user_agent, |
- const std::string& relay_token, |
- const std::string& connection) |
- : worker_(worker), |
- jid_(jid), |
- session_id_(session_id), |
- user_agent_(user_agent), |
- relay_token_(relay_token), |
- connection_(connection), |
- proxy_detect_(NULL), |
- timeout_ms_(kDefaultTimeoutMs), |
- stun_address_(kDefaultStunHostname, kDefaultStunPort), |
- started_(false) { |
-} |
- |
-ConnectivityChecker::~ConnectivityChecker() { |
- if (started_) { |
- // We try to clear the TIMEOUT below. But worker may still handle it and |
- // cause SignalCheckDone to happen on main-thread. So we finally clear any |
- // pending SIGNAL_RESULTS. |
- worker_->Clear(this, MSG_TIMEOUT); |
- worker_->Send(this, MSG_STOP); |
- nics_.clear(); |
- main_->Clear(this, MSG_SIGNAL_RESULTS); |
- } |
-} |
- |
-bool ConnectivityChecker::Initialize() { |
- network_manager_.reset(CreateNetworkManager()); |
- socket_factory_.reset(CreateSocketFactory(worker_)); |
- port_allocator_.reset(CreatePortAllocator(network_manager_.get(), |
- user_agent_, relay_token_)); |
- return true; |
-} |
- |
-void ConnectivityChecker::Start() { |
- main_ = rtc::Thread::Current(); |
- worker_->Post(this, MSG_START); |
- started_ = true; |
-} |
- |
-void ConnectivityChecker::CleanUp() { |
- ASSERT(worker_ == rtc::Thread::Current()); |
- if (proxy_detect_) { |
- proxy_detect_->Release(); |
- proxy_detect_ = NULL; |
- } |
- |
- for (uint32 i = 0; i < sessions_.size(); ++i) { |
- delete sessions_[i]; |
- } |
- sessions_.clear(); |
- for (uint32 i = 0; i < ports_.size(); ++i) { |
- delete ports_[i]; |
- } |
- ports_.clear(); |
-} |
- |
-bool ConnectivityChecker::AddNic(const rtc::IPAddress& ip, |
- const rtc::SocketAddress& proxy_addr) { |
- NicMap::iterator i = nics_.find(NicId(ip, proxy_addr)); |
- if (i != nics_.end()) { |
- // Already have it. |
- return false; |
- } |
- uint32 now = rtc::Time(); |
- NicInfo info; |
- info.ip = ip; |
- info.proxy_info = GetProxyInfo(); |
- info.stun.start_time_ms = now; |
- nics_.insert(std::pair<NicId, NicInfo>(NicId(ip, proxy_addr), info)); |
- return true; |
-} |
- |
-void ConnectivityChecker::SetProxyInfo(const rtc::ProxyInfo& proxy_info) { |
- port_allocator_->set_proxy(user_agent_, proxy_info); |
- AllocatePorts(); |
-} |
- |
-rtc::ProxyInfo ConnectivityChecker::GetProxyInfo() const { |
- rtc::ProxyInfo proxy_info; |
- if (proxy_detect_) { |
- proxy_info = proxy_detect_->proxy(); |
- } |
- return proxy_info; |
-} |
- |
-void ConnectivityChecker::CheckNetworks() { |
- network_manager_->SignalNetworksChanged.connect( |
- this, &ConnectivityChecker::OnNetworksChanged); |
- network_manager_->StartUpdating(); |
-} |
- |
-void ConnectivityChecker::OnMessage(rtc::Message *msg) { |
- switch (msg->message_id) { |
- case MSG_START: |
- ASSERT(worker_ == rtc::Thread::Current()); |
- worker_->PostDelayed(timeout_ms_, this, MSG_TIMEOUT); |
- CheckNetworks(); |
- break; |
- case MSG_STOP: |
- // We're being stopped, free resources. |
- CleanUp(); |
- break; |
- case MSG_TIMEOUT: |
- // We need to signal results on the main thread. |
- main_->Post(this, MSG_SIGNAL_RESULTS); |
- break; |
- case MSG_SIGNAL_RESULTS: |
- ASSERT(main_ == rtc::Thread::Current()); |
- SignalCheckDone(this); |
- break; |
- default: |
- LOG(LS_ERROR) << "Unknown message: " << msg->message_id; |
- } |
-} |
- |
-void ConnectivityChecker::OnProxyDetect(rtc::SignalThread* thread) { |
- ASSERT(worker_ == rtc::Thread::Current()); |
- if (proxy_detect_->proxy().type != rtc::PROXY_NONE) { |
- SetProxyInfo(proxy_detect_->proxy()); |
- } |
-} |
- |
-void ConnectivityChecker::OnRequestDone(rtc::AsyncHttpRequest* request) { |
- ASSERT(worker_ == rtc::Thread::Current()); |
- // Since we don't know what nic were actually used for the http request, |
- // for now, just use the first one. |
- std::vector<rtc::Network*> networks; |
- network_manager_->GetNetworks(&networks); |
- if (networks.empty()) { |
- LOG(LS_ERROR) << "No networks while registering http start."; |
- return; |
- } |
- rtc::ProxyInfo proxy_info = request->proxy(); |
- NicMap::iterator i = |
- nics_.find(NicId(networks[0]->GetBestIP(), proxy_info.address)); |
- if (i != nics_.end()) { |
- int port = request->port(); |
- uint32 now = rtc::Time(); |
- NicInfo* nic_info = &i->second; |
- if (port == rtc::HTTP_SECURE_PORT) { |
- nic_info->https.rtt = now - nic_info->https.start_time_ms; |
- } else { |
- LOG(LS_ERROR) << "Got response with unknown port: " << port; |
- } |
- } else { |
- LOG(LS_ERROR) << "No nic info found while receiving response."; |
- } |
-} |
- |
-void ConnectivityChecker::OnConfigReady( |
- const std::string& username, const std::string& password, |
- const PortConfiguration* config, const rtc::ProxyInfo& proxy_info) { |
- ASSERT(worker_ == rtc::Thread::Current()); |
- |
- // Since we send requests on both HTTP and HTTPS we will get two |
- // configs per nic. Results from the second will overwrite the |
- // result from the first. |
- // TODO: Handle multiple pings on one nic. |
- CreateRelayPorts(username, password, config, proxy_info); |
-} |
- |
-void ConnectivityChecker::OnRelayPortComplete(Port* port) { |
- ASSERT(worker_ == rtc::Thread::Current()); |
- RelayPort* relay_port = reinterpret_cast<RelayPort*>(port); |
- const ProtocolAddress* address = relay_port->ServerAddress(0); |
- rtc::IPAddress ip = port->Network()->GetBestIP(); |
- NicMap::iterator i = nics_.find(NicId(ip, port->proxy().address)); |
- if (i != nics_.end()) { |
- // We have it already, add the new information. |
- NicInfo* nic_info = &i->second; |
- ConnectInfo* connect_info = NULL; |
- if (address) { |
- switch (address->proto) { |
- case PROTO_UDP: |
- connect_info = &nic_info->udp; |
- break; |
- case PROTO_TCP: |
- connect_info = &nic_info->tcp; |
- break; |
- case PROTO_SSLTCP: |
- connect_info = &nic_info->ssltcp; |
- break; |
- default: |
- LOG(LS_ERROR) << " relay address with bad protocol added"; |
- } |
- if (connect_info) { |
- connect_info->rtt = |
- rtc::TimeSince(connect_info->start_time_ms); |
- } |
- } |
- } else { |
- LOG(LS_ERROR) << " got relay address for non-existing nic"; |
- } |
-} |
- |
-void ConnectivityChecker::OnStunPortComplete(Port* port) { |
- ASSERT(worker_ == rtc::Thread::Current()); |
- const std::vector<Candidate> candidates = port->Candidates(); |
- Candidate c = candidates[0]; |
- rtc::IPAddress ip = port->Network()->GetBestIP(); |
- NicMap::iterator i = nics_.find(NicId(ip, port->proxy().address)); |
- if (i != nics_.end()) { |
- // We have it already, add the new information. |
- uint32 now = rtc::Time(); |
- NicInfo* nic_info = &i->second; |
- nic_info->external_address = c.address(); |
- |
- nic_info->stun_server_addresses = |
- static_cast<StunPort*>(port)->server_addresses(); |
- nic_info->stun.rtt = now - nic_info->stun.start_time_ms; |
- } else { |
- LOG(LS_ERROR) << "Got stun address for non-existing nic"; |
- } |
-} |
- |
-void ConnectivityChecker::OnStunPortError(Port* port) { |
- ASSERT(worker_ == rtc::Thread::Current()); |
- LOG(LS_ERROR) << "Stun address error."; |
- rtc::IPAddress ip = port->Network()->GetBestIP(); |
- NicMap::iterator i = nics_.find(NicId(ip, port->proxy().address)); |
- if (i != nics_.end()) { |
- // We have it already, add the new information. |
- NicInfo* nic_info = &i->second; |
- |
- nic_info->stun_server_addresses = |
- static_cast<StunPort*>(port)->server_addresses(); |
- } |
-} |
- |
-void ConnectivityChecker::OnRelayPortError(Port* port) { |
- ASSERT(worker_ == rtc::Thread::Current()); |
- LOG(LS_ERROR) << "Relay address error."; |
-} |
- |
-void ConnectivityChecker::OnNetworksChanged() { |
- ASSERT(worker_ == rtc::Thread::Current()); |
- std::vector<rtc::Network*> networks; |
- network_manager_->GetNetworks(&networks); |
- if (networks.empty()) { |
- LOG(LS_ERROR) << "Machine has no networks; nothing to do"; |
- return; |
- } |
- AllocatePorts(); |
-} |
- |
-HttpPortAllocator* ConnectivityChecker::CreatePortAllocator( |
- rtc::NetworkManager* network_manager, |
- const std::string& user_agent, |
- const std::string& relay_token) { |
- return new TestHttpPortAllocator(network_manager, user_agent, relay_token); |
-} |
- |
-StunPort* ConnectivityChecker::CreateStunPort( |
- const std::string& username, const std::string& password, |
- const PortConfiguration* config, rtc::Network* network) { |
- return StunPort::Create(worker_, |
- socket_factory_.get(), |
- network, |
- network->GetBestIP(), |
- 0, |
- 0, |
- username, |
- password, |
- config->stun_servers, |
- std::string()); |
-} |
- |
-RelayPort* ConnectivityChecker::CreateRelayPort( |
- const std::string& username, const std::string& password, |
- const PortConfiguration* config, rtc::Network* network) { |
- return RelayPort::Create(worker_, |
- socket_factory_.get(), |
- network, |
- network->GetBestIP(), |
- port_allocator_->min_port(), |
- port_allocator_->max_port(), |
- username, |
- password); |
-} |
- |
-void ConnectivityChecker::CreateRelayPorts( |
- const std::string& username, const std::string& password, |
- const PortConfiguration* config, const rtc::ProxyInfo& proxy_info) { |
- PortConfiguration::RelayList::const_iterator relay; |
- std::vector<rtc::Network*> networks; |
- network_manager_->GetNetworks(&networks); |
- if (networks.empty()) { |
- LOG(LS_ERROR) << "Machine has no networks; no relay ports created."; |
- return; |
- } |
- for (relay = config->relays.begin(); |
- relay != config->relays.end(); ++relay) { |
- for (uint32 i = 0; i < networks.size(); ++i) { |
- NicMap::iterator iter = |
- nics_.find(NicId(networks[i]->GetBestIP(), proxy_info.address)); |
- if (iter != nics_.end()) { |
- // TODO: Now setting the same start time for all protocols. |
- // This might affect accuracy, but since we are mainly looking for |
- // connect failures or number that stick out, this is good enough. |
- uint32 now = rtc::Time(); |
- NicInfo* nic_info = &iter->second; |
- nic_info->udp.start_time_ms = now; |
- nic_info->tcp.start_time_ms = now; |
- nic_info->ssltcp.start_time_ms = now; |
- |
- // Add the addresses of this protocol. |
- PortList::const_iterator relay_port; |
- for (relay_port = relay->ports.begin(); |
- relay_port != relay->ports.end(); |
- ++relay_port) { |
- RelayPort* port = CreateRelayPort(username, password, |
- config, networks[i]); |
- port->AddServerAddress(*relay_port); |
- port->AddExternalAddress(*relay_port); |
- |
- nic_info->media_server_address = port->ServerAddress(0)->address; |
- |
- // Listen to network events. |
- port->SignalPortComplete.connect( |
- this, &ConnectivityChecker::OnRelayPortComplete); |
- port->SignalPortError.connect( |
- this, &ConnectivityChecker::OnRelayPortError); |
- |
- port->set_proxy(user_agent_, proxy_info); |
- |
- // Start fetching an address for this port. |
- port->PrepareAddress(); |
- ports_.push_back(port); |
- } |
- } else { |
- LOG(LS_ERROR) << "Failed to find nic info when creating relay ports."; |
- } |
- } |
- } |
-} |
- |
-void ConnectivityChecker::AllocatePorts() { |
- const std::string username = rtc::CreateRandomString(ICE_UFRAG_LENGTH); |
- const std::string password = rtc::CreateRandomString(ICE_PWD_LENGTH); |
- ServerAddresses stun_servers; |
- stun_servers.insert(stun_address_); |
- PortConfiguration config(stun_servers, username, password); |
- std::vector<rtc::Network*> networks; |
- network_manager_->GetNetworks(&networks); |
- if (networks.empty()) { |
- LOG(LS_ERROR) << "Machine has no networks; no ports will be allocated"; |
- return; |
- } |
- rtc::ProxyInfo proxy_info = GetProxyInfo(); |
- bool allocate_relay_ports = false; |
- for (uint32 i = 0; i < networks.size(); ++i) { |
- if (AddNic(networks[i]->GetBestIP(), proxy_info.address)) { |
- Port* port = CreateStunPort(username, password, &config, networks[i]); |
- if (port) { |
- |
- // Listen to network events. |
- port->SignalPortComplete.connect( |
- this, &ConnectivityChecker::OnStunPortComplete); |
- port->SignalPortError.connect( |
- this, &ConnectivityChecker::OnStunPortError); |
- |
- port->set_proxy(user_agent_, proxy_info); |
- port->PrepareAddress(); |
- ports_.push_back(port); |
- allocate_relay_ports = true; |
- } |
- } |
- } |
- |
- // If any new ip/proxy combinations were added, send a relay allocate. |
- if (allocate_relay_ports) { |
- AllocateRelayPorts(); |
- } |
- |
- // Initiate proxy detection. |
- InitiateProxyDetection(); |
-} |
- |
-void ConnectivityChecker::InitiateProxyDetection() { |
- // Only start if we haven't been started before. |
- if (!proxy_detect_) { |
- proxy_detect_ = new rtc::AutoDetectProxy(user_agent_); |
- rtc::Url<char> host_url("/", "relay.google.com", |
- rtc::HTTP_SECURE_PORT); |
- host_url.set_secure(true); |
- proxy_detect_->set_server_url(host_url.url()); |
- proxy_detect_->SignalWorkDone.connect( |
- this, &ConnectivityChecker::OnProxyDetect); |
- proxy_detect_->Start(); |
- } |
-} |
- |
-void ConnectivityChecker::AllocateRelayPorts() { |
- // Currently we are using the 'default' nic for http(s) requests. |
- TestHttpPortAllocatorSession* allocator_session = |
- reinterpret_cast<TestHttpPortAllocatorSession*>( |
- port_allocator_->CreateSessionInternal( |
- "connectivity checker test content", |
- ICE_CANDIDATE_COMPONENT_RTP, |
- rtc::CreateRandomString(ICE_UFRAG_LENGTH), |
- rtc::CreateRandomString(ICE_PWD_LENGTH))); |
- allocator_session->set_proxy(port_allocator_->proxy()); |
- allocator_session->SignalConfigReady.connect( |
- this, &ConnectivityChecker::OnConfigReady); |
- allocator_session->SignalRequestDone.connect( |
- this, &ConnectivityChecker::OnRequestDone); |
- |
- // Try https only since using http would result in credentials being sent |
- // over the network unprotected. |
- RegisterHttpStart(rtc::HTTP_SECURE_PORT); |
- allocator_session->SendSessionRequest("relay.l.google.com", |
- rtc::HTTP_SECURE_PORT); |
- |
- sessions_.push_back(allocator_session); |
-} |
- |
-void ConnectivityChecker::RegisterHttpStart(int port) { |
- // Since we don't know what nic were actually used for the http request, |
- // for now, just use the first one. |
- std::vector<rtc::Network*> networks; |
- network_manager_->GetNetworks(&networks); |
- if (networks.empty()) { |
- LOG(LS_ERROR) << "No networks while registering http start."; |
- return; |
- } |
- rtc::ProxyInfo proxy_info = GetProxyInfo(); |
- NicMap::iterator i = |
- nics_.find(NicId(networks[0]->GetBestIP(), proxy_info.address)); |
- if (i != nics_.end()) { |
- uint32 now = rtc::Time(); |
- NicInfo* nic_info = &i->second; |
- if (port == rtc::HTTP_SECURE_PORT) { |
- nic_info->https.start_time_ms = now; |
- } else { |
- LOG(LS_ERROR) << "Registering start time for unknown port: " << port; |
- } |
- } else { |
- LOG(LS_ERROR) << "Error, no nic info found while registering http start."; |
- } |
-} |
- |
-} // namespace rtc |