15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/p2p/port_allocator.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/command_line.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/public/common/content_switches.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/renderer/p2p/host_address_request.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jingle/glue/utils.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/ip_endpoint.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLError.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLLoader.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLRequest.h" 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLResponse.h" 217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h" 227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebURLLoaderOptions.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebString; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebURL; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebURLLoader; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebURLLoaderOptions; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebURLRequest; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using WebKit::WebURLResponse; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// URL used to create a relay session. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kCreateRelaySessionURL[] = "/create_session"; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Number of times we will try to request relay session. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kRelaySessionRetries = 3; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Manimum relay server size we would try to parse. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaximumRelayResponseSize = 102400; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParsePortNumber( 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& string, int* value) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::StringToInt(string, value) || *value <= 0 || *value >= 65536) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Received invalid port number from relay server: " << string; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)P2PPortAllocator::Config::Config() 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : stun_server_port(0), 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) legacy_relay(true), 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable_tcp_transport(false) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)P2PPortAllocator::Config::~Config() { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochP2PPortAllocator::Config::RelayServerConfig::RelayServerConfig() 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : port(0) { 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochP2PPortAllocator::Config::RelayServerConfig::~RelayServerConfig() { 69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)P2PPortAllocator::P2PPortAllocator( 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebKit::WebFrame* web_frame, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) P2PSocketDispatcher* socket_dispatcher, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) talk_base::NetworkManager* network_manager, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) talk_base::PacketSocketFactory* socket_factory, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Config& config) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : cricket::BasicPortAllocator(network_manager, socket_factory), 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_frame_(web_frame), 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket_dispatcher_(socket_dispatcher), 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_(config) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 flags = 0; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (config_.disable_tcp_transport) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags |= cricket::PORTALLOCATOR_DISABLE_TCP; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_flags(flags); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(ronghuawu): crbug/138185 add ourselves to the firewall list in browser 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // process and then remove below line. 877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!CommandLine::ForCurrentProcess()->HasSwitch( 887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) switches::kEnableWebRtcTcpServerSocket)) { 897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) set_allow_tcp_listen(false); 907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)P2PPortAllocator::~P2PPortAllocator() { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)cricket::PortAllocatorSession* P2PPortAllocator::CreateSessionInternal( 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& content_name, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int component, 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& ice_username_fragment, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& ice_password) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new P2PPortAllocatorSession( 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, content_name, component, ice_username_fragment, ice_password); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochP2PPortAllocatorSession::RelayServer::RelayServer() { 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochP2PPortAllocatorSession::RelayServer::~RelayServer() { 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)P2PPortAllocatorSession::P2PPortAllocatorSession( 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) P2PPortAllocator* allocator, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& content_name, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int component, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& ice_username_fragment, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& ice_password) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : cricket::BasicPortAllocatorSession( 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allocator, content_name, component, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ice_username_fragment, ice_password), 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allocator_(allocator), 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_session_attempts_(0), 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_udp_port_(0), 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_tcp_port_(0), 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch relay_ssltcp_port_(0), 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch pending_relay_requests_(0) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)P2PPortAllocatorSession::~P2PPortAllocatorSession() { 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (stun_address_request_.get()) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stun_address_request_->Cancel(); 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < relay_info_.size(); ++i) { 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (relay_info_[i].relay_address_request.get()) 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch relay_info_[i].relay_address_request->Cancel(); 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void P2PPortAllocatorSession::didReceiveData( 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebURLLoader* loader, const char* data, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data_length, int encoded_data_length) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(loader, relay_session_request_.get()); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (static_cast<int>(relay_session_response_.size()) + data_length > 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMaximumRelayResponseSize) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Response received from the server is too big."; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loader->cancel(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_session_response_.append(data, data + data_length); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void P2PPortAllocatorSession::didFinishLoading(WebURLLoader* loader, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double finish_time) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseRelayResponse(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void P2PPortAllocatorSession::didFail(WebKit::WebURLLoader* loader, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebKit::WebURLError& error) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(loader, relay_session_request_.get()); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(error.reason, 0); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Relay session request failed."; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Retry the request. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllocateLegacyRelaySession(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void P2PPortAllocatorSession::GetPortConfigurations() { 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Resolve Stun and Relay server addresses. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!allocator_->config_.stun_server.empty() && 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stun_server_address_.IsNil()) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResolveStunServerAddress(); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddConfig(); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (allocator_->config_.legacy_relay) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllocateLegacyRelaySession(); 178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ResolveRelayServerAddresses(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void P2PPortAllocatorSession::ResolveStunServerAddress() { 184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (stun_address_request_.get()) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stun_address_request_ = 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new P2PHostAddressRequest(allocator_->socket_dispatcher_); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stun_address_request_->Request(allocator_->config_.stun_server, base::Bind( 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &P2PPortAllocatorSession::OnStunServerAddress, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this))); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void P2PPortAllocatorSession::OnStunServerAddress( 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const net::IPAddressNumber& address) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (address.empty()) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to resolve STUN server address " 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << allocator_->config_.stun_server; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allocating local ports on stun failure. 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddConfig(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!jingle_glue::IPEndPointToSocketAddress( 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::IPEndPoint(address, allocator_->config_.stun_server_port), 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &stun_server_address_)) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddConfig(); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid P2PPortAllocatorSession::ResolveRelayServerAddresses() { 213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < allocator_->config_.relays.size(); ++i) { 214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_refptr<P2PHostAddressRequest> relay_request = 215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch new P2PHostAddressRequest(allocator_->socket_dispatcher_); 216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch relay_request->Request( 217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch allocator_->config_.relays[i].server_address, 218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Bind(&P2PPortAllocatorSession::OnRelayServerAddressResolved, 219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch base::Unretained(this), i)); 220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Copy relay configuration from alloctor and keeping it in a map. 221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RelayServer relay; 222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch relay.config = allocator_->config_.relays[i]; 223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch relay.relay_address_request = relay_request; 224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch relay_info_.push_back(relay); 225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ++pending_relay_requests_; 226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid P2PPortAllocatorSession::OnRelayServerAddressResolved( 230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch size_t index, const net::IPAddressNumber& address) { 231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Let's first decrement the pending requests count. 232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch --pending_relay_requests_; 233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (index > relay_info_.size()) { 234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTREACHED(); 235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return; 236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (address.empty()) { 239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(ERROR) << "Failed to resolve Relay server address " 240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << relay_info_.at(index).config.server_address; 241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } else { 242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Getting relay server info for which this resolved address belongs. 243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RelayServer& relay_server = relay_info_.at(index); 244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch talk_base::SocketAddress socket_address; 246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!jingle_glue::IPEndPointToSocketAddress( 247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch net::IPEndPoint(address, relay_server.config.port), 248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &socket_address)) { 249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch NOTREACHED(); 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch relay_server.resolved_relay_address = socket_address; 252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!pending_relay_requests_) 255eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch AddConfig(); 256eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 257eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void P2PPortAllocatorSession::AllocateLegacyRelaySession() { 259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (allocator_->config_.relays.empty()) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // If we are using legacy relay, we will have only one entry in relay server 262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // list. 263eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch P2PPortAllocator::Config::RelayServerConfig relay_config = 264eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch allocator_->config_.relays[0]; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (relay_session_attempts_ > kRelaySessionRetries) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_session_attempts_++; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_session_response_.clear(); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebURLLoaderOptions options; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.allowCredentials = false; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.crossOriginRequestPolicy = 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebURLLoaderOptions::CrossOriginRequestPolicyUseAccessControl; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_session_request_.reset( 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) allocator_->web_frame_->createAssociatedURLLoader(options)); 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!relay_session_request_) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to create URL loader."; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string url = "https://" + relay_config.server_address + 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCreateRelaySessionURL + 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "?username=" + net::EscapeUrlEncodedData(username(), true) + 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "&password=" + net::EscapeUrlEncodedData(password(), true); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebURLRequest request; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.initialize(); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.setURL(WebURL(GURL(url))); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.setAllowStoredCredentials(false); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.setCachePolicy(WebURLRequest::ReloadIgnoringCacheData); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.setHTTPMethod("GET"); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.addHTTPHeaderField( 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebString::fromUTF8("X-Talk-Google-Relay-Auth"), 298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WebString::fromUTF8(relay_config.password)); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.addHTTPHeaderField( 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebString::fromUTF8("X-Google-Relay-Auth"), 301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WebString::fromUTF8(relay_config.username)); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request.addHTTPHeaderField(WebString::fromUTF8("X-Stream-Type"), 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebString::fromUTF8("chromoting")); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_session_request_->loadAsynchronously(request, this); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void P2PPortAllocatorSession::ParseRelayResponse() { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::pair<std::string, std::string> > value_pairs; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::SplitStringIntoKeyValuePairs(relay_session_response_, '=', '\n', 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &value_pairs)) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Received invalid response from relay server"; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_ip_.Clear(); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_udp_port_ = 0; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_tcp_port_ = 0; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_ssltcp_port_ = 0; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<std::pair<std::string, std::string> >::iterator 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it = value_pairs.begin(); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != value_pairs.end(); ++it) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string key; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrimWhitespaceASCII(it->first, TRIM_ALL, &key); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TrimWhitespaceASCII(it->second, TRIM_ALL, &value); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key == "username") { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value != username()) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "When creating relay session received user name " 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " that was different from the value specified in the query."; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (key == "password") { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value != password()) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "When creating relay session received password " 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "that was different from the value specified in the query."; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (key == "relay.ip") { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relay_ip_.SetIP(value); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (relay_ip_.ip() == 0) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Received unresolved relay server address: " << value; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (key == "relay.udp_port") { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ParsePortNumber(value, &relay_udp_port_)) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (key == "relay.tcp_port") { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ParsePortNumber(value, &relay_tcp_port_)) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (key == "relay.ssltcp_port") { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ParsePortNumber(value, &relay_ssltcp_port_)) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddConfig(); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void P2PPortAllocatorSession::AddConfig() { 363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch cricket::PortConfiguration* port_config = new cricket::PortConfiguration( 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) stun_server_address_, std::string(), std::string()); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!pending_relay_requests_) { 367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Push all resolved addresses and transport port type to allocator. 368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (size_t i = 0; i < relay_info_.size(); ++i) { 369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (relay_info_[i].resolved_relay_address.IsNil()) 370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 3717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch RelayServer relay_info = relay_info_[i]; 373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch cricket::RelayCredentials credentials(relay_info.config.username, 374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch relay_info.config.password); 375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch cricket::RelayServerConfig relay_server(cricket::RELAY_TURN); 3767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) cricket::ProtocolType protocol; 377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!cricket::StringToProto(relay_info.config.transport_type.c_str(), 378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch &protocol)) { 3797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DLOG(WARNING) << "Ignoring TURN server " 380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << relay_info.config.server_address << ". " 3817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) << "Reason= Incorrect " 382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << relay_info.config.transport_type 3837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) << " transport parameter."; 384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch continue; 3857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch relay_server.ports.push_back(cricket::ProtocolAddress( 388f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch relay_info.resolved_relay_address, 389f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch protocol, 390f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch relay_info.config.secure)); 391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch relay_server.credentials = credentials; 392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch port_config->AddRelay(relay_server); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ConfigReady(port_config); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 399