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