httpportallocator.cc revision 269fb4bc90b79bebbb8311da0110ccd6803fd0a8
1269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org/*
2269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *
4269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
5269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
6269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
7269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
8269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org */
10269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
11269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/p2p/client/httpportallocator.h"
12269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
13269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include <algorithm>
14269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include <map>
15269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
16269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/asynchttprequest.h"
17269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/basicdefs.h"
18269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/common.h"
19269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/helpers.h"
20269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/logging.h"
21269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/nethelpers.h"
22269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/signalthread.h"
23269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org#include "webrtc/base/stringencode.h"
24269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
25269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgnamespace {
26269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
27269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Helper routine to remove whitespace from the ends of a string.
28269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid Trim(std::string& str) {
29269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  size_t first = str.find_first_not_of(" \t\r\n");
30269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (first == std::string::npos) {
31269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    str.clear();
32269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
33269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
34269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
35269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ASSERT(str.find_last_not_of(" \t\r\n") != std::string::npos);
36269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
37269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
38269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// Parses the lines in the result of the HTTP request that are of the form
39269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// 'a=b' and returns them in a map.
40269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgtypedef std::map<std::string, std::string> StringMap;
41269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid ParseMap(const std::string& string, StringMap& map) {
42269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  size_t start_of_line = 0;
43269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  size_t end_of_line = 0;
44269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
45269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (;;) {  // for each line
46269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    start_of_line = string.find_first_not_of("\r\n", end_of_line);
47269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (start_of_line == std::string::npos)
48269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      break;
49269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
50269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    end_of_line = string.find_first_of("\r\n", start_of_line);
51269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if (end_of_line == std::string::npos) {
52269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      end_of_line = string.length();
53269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    }
54269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
55269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    size_t equals = string.find('=', start_of_line);
56269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if ((equals >= end_of_line) || (equals == std::string::npos))
57269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      continue;
58269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
59269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    std::string key(string, start_of_line, equals - start_of_line);
60269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    std::string value(string, equals + 1, end_of_line - equals - 1);
61269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
62269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Trim(key);
63269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    Trim(value);
64269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
65269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    if ((key.size() > 0) && (value.size() > 0))
66269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      map[key] = value;
67269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
68269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
69269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
70269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}  // namespace
71269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
72269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgnamespace cricket {
73269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
74269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// HttpPortAllocatorBase
75269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
76269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgconst int HttpPortAllocatorBase::kNumRetries = 5;
77269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
78269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgconst char HttpPortAllocatorBase::kCreateSessionURL[] = "/create_session";
79269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
80269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgHttpPortAllocatorBase::HttpPortAllocatorBase(
81269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    rtc::NetworkManager* network_manager,
82269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    rtc::PacketSocketFactory* socket_factory,
83269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string &user_agent)
84269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    : BasicPortAllocator(network_manager, socket_factory), agent_(user_agent) {
85269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  relay_hosts_.push_back("relay.google.com");
86269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  stun_hosts_.push_back(
87269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      rtc::SocketAddress("stun.l.google.com", 19302));
88269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
89269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
90269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgHttpPortAllocatorBase::HttpPortAllocatorBase(
91269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    rtc::NetworkManager* network_manager,
92269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string &user_agent)
93269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    : BasicPortAllocator(network_manager), agent_(user_agent) {
94269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  relay_hosts_.push_back("relay.google.com");
95269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  stun_hosts_.push_back(
96269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      rtc::SocketAddress("stun.l.google.com", 19302));
97269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
98269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
99269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgHttpPortAllocatorBase::~HttpPortAllocatorBase() {
100269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
101269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
102269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// HttpPortAllocatorSessionBase
103269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
104269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgHttpPortAllocatorSessionBase::HttpPortAllocatorSessionBase(
105269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    HttpPortAllocatorBase* allocator,
106269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& content_name,
107269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    int component,
108269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& ice_ufrag,
109269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& ice_pwd,
110269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::vector<rtc::SocketAddress>& stun_hosts,
111269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::vector<std::string>& relay_hosts,
112269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& relay_token,
113269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& user_agent)
114269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    : BasicPortAllocatorSession(allocator, content_name, component,
115269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                ice_ufrag, ice_pwd),
116269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      relay_hosts_(relay_hosts), stun_hosts_(stun_hosts),
117269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      relay_token_(relay_token), agent_(user_agent), attempts_(0) {
118269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
119269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
120269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgHttpPortAllocatorSessionBase::~HttpPortAllocatorSessionBase() {}
121269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
122269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid HttpPortAllocatorSessionBase::GetPortConfigurations() {
123269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Creating relay sessions can take time and is done asynchronously.
124269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Creating stun sessions could also take time and could be done aysnc also,
125269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // but for now is done here and added to the initial config.  Note any later
126269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // configs will have unresolved stun ips and will be discarded by the
127269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // AllocationSequence.
128269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ServerAddresses hosts;
129269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (std::vector<rtc::SocketAddress>::iterator it = stun_hosts_.begin();
130269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      it != stun_hosts_.end(); ++it) {
131269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    hosts.insert(*it);
132269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
133269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
134269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  PortConfiguration* config = new PortConfiguration(hosts,
135269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                                    username(),
136269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                                    password());
137269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ConfigReady(config);
138269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  TryCreateRelaySession();
139269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
140269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
141269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid HttpPortAllocatorSessionBase::TryCreateRelaySession() {
142269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (allocator()->flags() & PORTALLOCATOR_DISABLE_RELAY) {
143269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_VERBOSE) << "HttpPortAllocator: Relay ports disabled, skipping.";
144269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
145269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
146269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
147269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (attempts_ == HttpPortAllocator::kNumRetries) {
148269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_ERROR) << "HttpPortAllocator: maximum number of requests reached; "
149269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                  << "giving up on relay.";
150269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
151269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
152269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
153269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (relay_hosts_.size() == 0) {
154269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_ERROR) << "HttpPortAllocator: no relay hosts configured.";
155269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
156269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
157269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
158269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Choose the next host to try.
159269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string host = relay_hosts_[attempts_ % relay_hosts_.size()];
160269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  attempts_++;
161269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  LOG(LS_INFO) << "HTTPPortAllocator: sending to relay host " << host;
162269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (relay_token_.empty()) {
163269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_WARNING) << "No relay auth token found.";
164269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
165269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
166269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  SendSessionRequest(host, rtc::HTTP_SECURE_PORT);
167269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
168269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
169269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgstd::string HttpPortAllocatorSessionBase::GetSessionRequestUrl() {
170269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string url = std::string(HttpPortAllocator::kCreateSessionURL);
171269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (allocator()->flags() & PORTALLOCATOR_ENABLE_SHARED_UFRAG) {
172269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT(!username().empty());
173269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    ASSERT(!password().empty());
174269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    url = url + "?username=" + rtc::s_url_encode(username()) +
175269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org        "&password=" + rtc::s_url_encode(password());
176269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
177269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return url;
178269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
179269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
180269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid HttpPortAllocatorSessionBase::ReceiveSessionResponse(
181269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& response) {
182269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
183269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  StringMap map;
184269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ParseMap(response, map);
185269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
186269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!username().empty() && map["username"] != username()) {
187269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_WARNING) << "Received unexpected username value from relay server.";
188269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
189269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!password().empty() && map["password"] != password()) {
190269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_WARNING) << "Received unexpected password value from relay server.";
191269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
192269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
193269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string relay_ip = map["relay.ip"];
194269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string relay_udp_port = map["relay.udp_port"];
195269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string relay_tcp_port = map["relay.tcp_port"];
196269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string relay_ssltcp_port = map["relay.ssltcp_port"];
197269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
198269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ServerAddresses hosts;
199269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (std::vector<rtc::SocketAddress>::iterator it = stun_hosts_.begin();
200269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      it != stun_hosts_.end(); ++it) {
201269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    hosts.insert(*it);
202269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
203269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
204269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  PortConfiguration* config = new PortConfiguration(hosts,
205269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                                    map["username"],
206269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                                    map["password"]);
207269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
208269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  RelayServerConfig relay_config(RELAY_GTURN);
209269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!relay_udp_port.empty()) {
210269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    rtc::SocketAddress address(relay_ip, atoi(relay_udp_port.c_str()));
211269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    relay_config.ports.push_back(ProtocolAddress(address, PROTO_UDP));
212269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
213269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!relay_tcp_port.empty()) {
214269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    rtc::SocketAddress address(relay_ip, atoi(relay_tcp_port.c_str()));
215269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    relay_config.ports.push_back(ProtocolAddress(address, PROTO_TCP));
216269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
217269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (!relay_ssltcp_port.empty()) {
218269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    rtc::SocketAddress address(relay_ip, atoi(relay_ssltcp_port.c_str()));
219269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    relay_config.ports.push_back(ProtocolAddress(address, PROTO_SSLTCP));
220269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
221269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  config->AddRelay(relay_config);
222269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ConfigReady(config);
223269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
224269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
225269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// HttpPortAllocator
226269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
227269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgHttpPortAllocator::HttpPortAllocator(
228269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    rtc::NetworkManager* network_manager,
229269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    rtc::PacketSocketFactory* socket_factory,
230269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string &user_agent)
231269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    : HttpPortAllocatorBase(network_manager, socket_factory, user_agent) {
232269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
233269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
234269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgHttpPortAllocator::HttpPortAllocator(
235269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    rtc::NetworkManager* network_manager,
236269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string &user_agent)
237269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    : HttpPortAllocatorBase(network_manager, user_agent) {
238269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
239269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgHttpPortAllocator::~HttpPortAllocator() {}
240269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
241269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgPortAllocatorSession* HttpPortAllocator::CreateSessionInternal(
242269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& content_name,
243269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    int component,
244269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& ice_ufrag, const std::string& ice_pwd) {
245269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  return new HttpPortAllocatorSession(this, content_name, component,
246269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                      ice_ufrag, ice_pwd, stun_hosts(),
247269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                      relay_hosts(), relay_token(),
248269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                      user_agent());
249269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
250269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
251269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org// HttpPortAllocatorSession
252269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
253269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgHttpPortAllocatorSession::HttpPortAllocatorSession(
254269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    HttpPortAllocator* allocator,
255269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& content_name,
256269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    int component,
257269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& ice_ufrag,
258269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& ice_pwd,
259269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::vector<rtc::SocketAddress>& stun_hosts,
260269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::vector<std::string>& relay_hosts,
261269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& relay,
262269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    const std::string& agent)
263269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    : HttpPortAllocatorSessionBase(allocator, content_name, component,
264269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   ice_ufrag, ice_pwd, stun_hosts,
265269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                   relay_hosts, relay, agent) {
266269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
267269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
268269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgHttpPortAllocatorSession::~HttpPortAllocatorSession() {
269269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  for (std::list<rtc::AsyncHttpRequest*>::iterator it = requests_.begin();
270269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org       it != requests_.end(); ++it) {
271269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    (*it)->Destroy(true);
272269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
273269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
274269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
275269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid HttpPortAllocatorSession::SendSessionRequest(const std::string& host,
276269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                                                  int port) {
277269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Initiate an HTTP request to create a session through the chosen host.
278269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::AsyncHttpRequest* request =
279269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      new rtc::AsyncHttpRequest(user_agent());
280269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->SignalWorkDone.connect(this,
281269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      &HttpPortAllocatorSession::OnRequestDone);
282269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
283269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->set_secure(port == rtc::HTTP_SECURE_PORT);
284269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->set_proxy(allocator()->proxy());
285269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->response().document.reset(new rtc::MemoryStream);
286269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->request().verb = rtc::HV_GET;
287269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->request().path = GetSessionRequestUrl();
288269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->request().addHeader("X-Talk-Google-Relay-Auth", relay_token(), true);
289269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->request().addHeader("X-Stream-Type", "video_rtp", true);
290269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->set_host(host);
291269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->set_port(port);
292269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->Start();
293269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  request->Release();
294269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
295269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  requests_.push_back(request);
296269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
297269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
298269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.orgvoid HttpPortAllocatorSession::OnRequestDone(rtc::SignalThread* data) {
299269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::AsyncHttpRequest* request =
300269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      static_cast<rtc::AsyncHttpRequest*>(data);
301269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
302269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  // Remove the request from the list of active requests.
303269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::list<rtc::AsyncHttpRequest*>::iterator it =
304269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      std::find(requests_.begin(), requests_.end(), request);
305269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (it != requests_.end()) {
306269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    requests_.erase(it);
307269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
308269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
309269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  if (request->response().scode != 200) {
310269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    LOG(LS_WARNING) << "HTTPPortAllocator: request "
311269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org                    << " received error " << request->response().scode;
312269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    TryCreateRelaySession();
313269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org    return;
314269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  }
315269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  LOG(LS_INFO) << "HTTPPortAllocator: request succeeded";
316269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
317269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  rtc::MemoryStream* stream =
318269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org      static_cast<rtc::MemoryStream*>(request->response().document.get());
319269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  stream->Rewind();
320269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  size_t length;
321269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  stream->GetSize(&length);
322269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  std::string resp = std::string(stream->GetBuffer(), length);
323269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org  ReceiveSessionResponse(resp);
324269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}
325269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org
326269fb4bc90b79bebbb8311da0110ccd6803fd0a8henrike@webrtc.org}  // namespace cricket
327